001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 * Created on 26.04.2004 021 * @author Andreas Prlic 022 * 023 */ 024package org.biojava.nbio.structure; 025 026import java.util.ArrayList; 027import java.util.List; 028import java.util.ListIterator; 029 030import org.biojava.nbio.structure.io.FileConvert; 031import org.slf4j.Logger; 032import org.slf4j.LoggerFactory; 033 034/** 035 * Implementation of a PDB Structure. This class 036 * provides the data contained in a PDB file. 037 * to get structure objects from different sources 038 * see io package. 039 * 040 * @author Andreas Prlic 041 * @author Jules Jacobsen 042 * @since 1.4 043 * @version %I% %G% 044 */ 045public class StructureImpl implements Structure { 046 047 private static final long serialVersionUID = -8344837138032851348L; 048 049 private static final Logger logger = LoggerFactory.getLogger(StructureImpl.class); 050 051 private String pdb_id ; 052 053 private List<Model> models; 054 055 private List<EntityInfo> entityInfos; 056 private List<DBRef> dbrefs; 057 private List<Bond> ssbonds; 058 private List<Site> sites; 059 private String name ; 060 private StructureIdentifier structureIdentifier; 061 062 private PDBHeader pdbHeader; 063 064 private Long id; 065 private boolean biologicalAssembly; 066 067 /** 068 * Constructs a StructureImpl object. 069 */ 070 public StructureImpl() { 071 super(); 072 073 models = new ArrayList<>(); 074 name = ""; 075 entityInfos = new ArrayList<>(); 076 dbrefs = new ArrayList<>(); 077 pdbHeader = new PDBHeader(); 078 ssbonds = new ArrayList<>(); 079 sites = new ArrayList<>(); 080 } 081 082 083 /** get the ID used by Hibernate 084 * 085 * @return the ID used by Hibernate 086 */ 087 @Override 088 public Long getId() { 089 return id; 090 } 091 092 /** set the ID used by Hibernate 093 * 094 * @param id the hibernate ID 095 */ 096 @Override 097 public void setId(Long id) { 098 this.id = id; 099 } 100 101 102 103 /** Construct a Structure object that only contains a single group 104 * 105 * @param g group object 106 */ 107 public StructureImpl(Group g){ 108 this(); 109 110 Chain c = new ChainImpl(); 111 c.addGroup(g); 112 113 addChain(c); 114 } 115 116 /** construct a Structure object that contains a particular chain 117 * 118 * @param c chain 119 */ 120 public StructureImpl(Chain c){ 121 this(); 122 addChain(c); 123 } 124 125 /** returns an identical copy of this structure . 126 * @return an identical Structure object 127 */ 128 @Override 129 public Structure clone() { 130 // Note: structures are also cloned in SubstructureIdentifier.reduce(). 131 // Changes might need to be made there as well 132 133 Structure n = new StructureImpl(); 134 // go through whole substructure and clone ... 135 136 // copy structure data 137 138 n.setPDBCode(getPDBCode()); 139 n.setName(getName()); 140 //TODO the header data is not being deep-copied, that's a minor issue since it is just some static metadata, but we should recheck this if needed - JD 2014-12-11 141 n.setPDBHeader(pdbHeader); 142 n.setDBRefs(this.getDBRefs()); 143 n.setSites(getSites()); 144 145 146 // go through each chain and clone chain 147 for (int i=0;i<nrModels();i++){ 148 List<Chain> cloned_model = new ArrayList<Chain>(); 149 150 for (int j=0;j<size(i);j++){ 151 152 Chain cloned_chain = (Chain) getChainByIndex(i,j).clone(); 153 154 // setting the parent: can only be done from the parent 155 cloned_chain.setStructure(n); 156 157 cloned_model.add(cloned_chain); 158 159 } 160 n.addModel(cloned_model); 161 162 } 163 164 // deep-copying of entityInfofos is tricky: there's cross references also in the Chains 165 // beware: if we copy the entityInfos we would also need to reset the references to entityInfos in the individual chains 166 List<EntityInfo> newEntityInfoList = new ArrayList<>(); 167 for (EntityInfo entityInfo : this.entityInfos) { 168 EntityInfo newEntityInfo = new EntityInfo(entityInfo); // this sets everything but the chains 169 for (String asymId:entityInfo.getChainIds()) { 170 171 for (int modelNr=0;modelNr<n.nrModels();modelNr++) { 172 Chain newChain = n.getChain(asymId,modelNr); 173 if (newChain==null) { 174 // this actually happens for structure 1msh, which has no chain B for model 29 (clearly a deposition error) 175 logger.warn("Could not find chain asymId "+asymId+" of model "+modelNr+" while cloning entityInfo "+entityInfo.getMolId()+". Something is wrong!"); 176 continue; 177 } 178 newChain.setEntityInfo(newEntityInfo); 179 newEntityInfo.addChain(newChain); 180 } 181 } 182 newEntityInfoList.add(newEntityInfo); 183 } 184 n.setEntityInfos(newEntityInfoList); 185 // TODO ssbonds are complicated to clone: there are deep references inside Atom objects, how would we do it? - JD 2016-03-03 186 187 return n ; 188 } 189 190 191 /** {@inheritDoc} */ 192 @Override 193 public Group findGroup(String chainName, String pdbResnum, int modelnr) 194 throws StructureException { 195 196 197 // if structure is xray there will be only one "model". 198 if ( modelnr > models.size()) 199 throw new StructureException(" no model nr " + modelnr + 200 " in this structure. (contains "+models.size()+")"); 201 202 203 // first we need to gather all groups with the author id chainName: polymers, non-polymers and waters 204 Chain polyChain = getPolyChainByPDB(chainName, modelnr); 205 if(polyChain != null) { 206 List<Group> groups = new ArrayList<>(); 207 208 groups.addAll(polyChain.getAtomGroups()); 209 210 211 // there can be more than one non-poly chain for a given author id 212 for (Chain chain: getNonPolyChainsByPDB(chainName, modelnr)) { 213 groups.addAll(chain.getAtomGroups()); 214 } 215 216 Chain water = getWaterChainByPDB(chainName, modelnr); 217 218 if (water!=null) 219 groups.addAll(water.getAtomGroups()); 220 221 222 223 // now iterate over all groups 224 // in order to find the amino acid that has this pdbRenum. 225 226 for (Group g : groups) { 227 String rnum = g.getResidueNumber().toString(); 228 //System.out.println(g + " >" + rnum + "< >" + pdbResnum + "<"); 229 // we only mutate amino acids 230 // and ignore hetatoms and nucleotides in this case 231 if (rnum.equals(pdbResnum)) { 232 return g; 233 } 234 } 235 } 236 throw new StructureException("could not find group " + pdbResnum + 237 " in chain " + chainName); 238 } 239 240 241 /** {@inheritDoc} */ 242 @Override 243 public Group findGroup(String chainName, String pdbResnum) throws StructureException 244 { 245 return findGroup(chainName, pdbResnum, 0); 246 247 } 248 249 250 251 252 /** {@inheritDoc} */ 253 @Override 254 public Chain findChain(String chainName, int modelnr) throws StructureException { 255 256 return getChainByPDB(chainName, modelnr); 257 258 } 259 260 261 /** {@inheritDoc} */ 262 @Override 263 public Chain findChain(String chainId) throws StructureException { 264 265 return findChain(chainId,0); 266 } 267 268 269 /** {@inheritDoc} */ 270 @Override 271 public void setPDBCode (String pdb_id_) { 272 pdb_id = pdb_id_ ; 273 } 274 275 /** {@inheritDoc} */ 276 @Override 277 public String getPDBCode () { 278 return pdb_id ; 279 } 280 281 282 283 /** {@inheritDoc} */ 284 @Override 285 public void setName(String nam) { name = nam; } 286 287 /** {@inheritDoc} */ 288 @Override 289 public String getName() { return name; } 290 291 292 293 /** 294 * @return The StructureIdentifier used to create this structure 295 */ 296 @Override 297 public StructureIdentifier getStructureIdentifier() { 298 return structureIdentifier; 299 } 300 301 /** 302 * @param structureIdentifier the structureIdentifier corresponding to this structure 303 */ 304 @Override 305 public void setStructureIdentifier(StructureIdentifier structureIdentifier) { 306 this.structureIdentifier = structureIdentifier; 307 } 308 309 /** {@inheritDoc} */ 310 @Override 311 public void addChain(Chain chain) { 312 int modelnr = 0 ; 313 addChain(chain,modelnr); 314 } 315 316 /** {@inheritDoc} */ 317 @Override 318 public void addChain(Chain chain, int modelnr) { 319 // if model has not been initialized, init it! 320 chain.setStructure(this); 321 if (models.isEmpty()) { 322 Model model = new Model(); 323 List<Chain> modelChains = new ArrayList<>() ; 324 modelChains.add(chain); 325 model.setChains(modelChains); 326 models.add(model); 327 328 } else { 329 Model model = models.get(modelnr); 330 model.addChain(chain); 331 } 332 333 334 335 } 336 337 338 339 /** {@inheritDoc} */ 340 @Override 341 public Chain getChainByIndex(int number) { 342 343 int modelnr = 0 ; 344 345 return getChainByIndex(modelnr,number); 346 } 347 348 349 /** {@inheritDoc} */ 350 @Override 351 public Chain getChainByIndex(int modelnr,int number) { 352 353 Model model = models.get(modelnr); 354 355 return model.getChains().get(number); 356 } 357 358 359 360 /** {@inheritDoc} */ 361 @Override 362 public void addModel(List<Chain> modelChains){ 363 for (Chain c: modelChains){ 364 c.setStructure(this); 365 } 366 Model model = new Model(); 367 model.setChains(modelChains); 368 models.add(model); 369 } 370 371 372 /** {@inheritDoc} */ 373 @Override 374 public void setChains(List<Chain> chains){ 375 376 setModel(0,chains); 377 } 378 379 380 381 /** {@inheritDoc} */ 382 @Override 383 public void setModel(int position, List<Chain> modelChains){ 384 if (modelChains == null) 385 throw new IllegalArgumentException("trying to set model to null!"); 386 387 for (Chain c: modelChains) 388 c.setStructure(this); 389 390 //System.out.println("model size:" + models.size()); 391 392 393 Model model = new Model(); 394 model.setChains(modelChains); 395 396 if (models.isEmpty()){ 397 models.add(model); 398 } else { 399 models.set(position, model); 400 } 401 } 402 403 /** String representation. 404 * 405 */ 406 @Override 407 public String toString(){ 408 String newline = System.getProperty("line.separator"); 409 StringBuilder str = new StringBuilder(); 410 str.append("structure "); 411 str.append(name); 412 str.append(" "); 413 str.append(pdb_id); 414 str.append(" "); 415 416 if ( nrModels()>1 ){ 417 str.append( " models: "); 418 str.append(nrModels()); 419 str.append(newline) ; 420 } 421 422 str.append(pdbHeader); 423 str.append(newline) ; 424 425 for (int i=0;i<nrModels();i++){ 426 if ( nrModels()>1 ) { 427 str.append(" model["); 428 str.append(i); 429 str.append("]:"); 430 str.append(newline); 431 } 432 str.append(" chains:"); 433 str.append(newline); 434 435 for (int j=0;j<size(i);j++){ 436 437 Chain cha = getChainByIndex(i,j); 438 List<Group> agr = cha.getAtomGroups(GroupType.AMINOACID); 439 List<Group> hgr = cha.getAtomGroups(GroupType.HETATM); 440 List<Group> ngr = cha.getAtomGroups(GroupType.NUCLEOTIDE); 441 442 443 444 445 str.append("chain ") 446 .append(j).append(": asymId:") 447 .append(cha.getId()) 448 .append(" authId:") 449 .append(cha.getName()).append(" "); 450 451 452 if ( cha.getEntityInfo() != null){ 453 EntityInfo comp = cha.getEntityInfo(); 454 String molName = comp.getDescription(); 455 if ( molName != null){ 456 str.append(molName); 457 } 458 String type = comp.getType().toString(); 459 str.append(" (") 460 .append(type) 461 .append(")"); 462 } 463 464 465 str.append(newline); 466 str.append(" length SEQRES: ").append(cha.getSeqResLength()); 467 str.append(" length ATOM: ").append(cha.getAtomLength()); 468 str.append(" aminos: ").append(agr.size()); 469 str.append(" hetatms: ").append(hgr.size()); 470 str.append(" nucleotides: ").append(ngr.size()).append(newline); 471 } 472 473 } 474 str.append("DBRefs: ").append(dbrefs.size()).append(newline); 475 for (DBRef dbref: dbrefs){ 476 str.append(dbref.toPDB()).append(newline); 477 } 478 str.append("Molecules: ").append(newline); 479 for (EntityInfo mol : entityInfos) { 480 str.append(mol).append(newline); 481 } 482 483 484 return str.toString() ; 485 } 486 487 @Override 488 public int size() { 489 int modelnr = 0 ; 490 491 if (!models.isEmpty()) { 492 return models.get(modelnr).getPolyChains().size(); 493 } 494 else { 495 return 0 ; 496 } 497 498 } 499 500 /** return number of chains of model. 501 * 502 */ 503 @Override 504 public int size(int modelnr) { return models.get(modelnr).size(); } 505 506 // some NMR stuff : 507 508 /** return number of models. */ 509 @Override 510 public int nrModels() { 511 return models.size() ; 512 } 513 514 /** 515 * Whether this Structure is a crystallographic structure or not. 516 * It will first check the experimental technique and if not present it will try 517 * to guess from the presence of a space group and sensible cell parameters 518 * 519 * @return true if crystallographic, false otherwise 520 */ 521 @Override 522 public boolean isCrystallographic() { 523 if (pdbHeader.getExperimentalTechniques()!=null) { 524 return ExperimentalTechnique.isCrystallographic(pdbHeader.getExperimentalTechniques()); 525 } else { 526 // no experimental technique known, we try to guess... 527 if (pdbHeader.getCrystallographicInfo().getSpaceGroup()!=null) { 528 // space group defined but no crystal cell: incomplete info, return false 529 return pdbHeader.getCrystallographicInfo().getCrystalCell() != null && 530 pdbHeader.getCrystallographicInfo().getCrystalCell().isCellReasonable(); 531 } 532 } 533 return false; 534 } 535 536 /** 537 * Whether this Structure is a NMR structure or not. 538 * It will first check the experimental technique and if not present it will try 539 * to guess from the presence of more than 1 model and from b-factors being 0 in first chain of first model 540 * @return true if NMR, false otherwise 541 */ 542 @Override 543 public boolean isNmr() { 544 545 // old implementation was: 546 //return nmrflag; 547 548 if (pdbHeader.getExperimentalTechniques()!=null) { 549 return ExperimentalTechnique.isNmr(pdbHeader.getExperimentalTechniques()); 550 } else { 551 // no experimental technique known, we try to guess... 552 if (nrModels()>1) { 553 if (pdbHeader.getCrystallographicInfo().getSpaceGroup()!=null) { 554 // multimodel, sg defined, but missing cell: must be NMR 555 if (pdbHeader.getCrystallographicInfo().getCrystalCell()==null) 556 return true; 557 // multi-model, sg defined and cell unreasonable: must be NMR 558 if (!pdbHeader.getCrystallographicInfo().getCrystalCell().isCellReasonable()) 559 return true; 560 } else { 561 // multi-model and missing space group: must be NMR 562 return true; 563 } 564 } 565 } 566 return false; 567 } 568 569 /** {@inheritDoc} */ 570 @Override 571 public List<Chain> getChains(int modelIdx){ 572 return getModel(modelIdx); 573 } 574 575 /** {@inheritDoc} */ 576 @Override 577 public List<Chain> getChains(){ 578 if (models.size()==0) { 579 return new ArrayList<>(0); 580 } 581 return getChains(0); 582 583 } 584 585 @Override 586 public List<Chain> getPolyChains() { 587 if (models.size()==0) { 588 return new ArrayList<>(0); 589 } 590 return getPolyChains(0); 591 } 592 593 @Override 594 public List<Chain> getPolyChains(int modelIdx) { 595 return models.get(modelIdx).getPolyChains(); 596 } 597 598 @Override 599 public List<Chain> getNonPolyChains() { 600 if (models.size()==0) { 601 return new ArrayList<>(0); 602 } 603 return getNonPolyChains(0); 604 } 605 606 @Override 607 public List<Chain> getNonPolyChains(int modelIdx) { 608 return models.get(modelIdx).getNonPolyChains(); 609 } 610 611 @Override 612 public List<Chain> getWaterChains() { 613 if (models.size()==0) { 614 return new ArrayList<>(0); 615 } 616 return getWaterChains(0); 617 } 618 619 @Override 620 public List<Chain> getWaterChains(int modelIdx) { 621 return models.get(modelIdx).getWaterChains(); 622 } 623 624 625 626 /** {@inheritDoc} */ 627 @Override 628 public void setChains(int modelnr, List<Chain> chains){ 629 for (Chain c: chains){ 630 c.setStructure(this); 631 } 632 if (models.size()>modelnr) { 633 models.remove(modelnr); 634 } 635 636 Model model = new Model(); 637 model.setChains(chains); 638 models.add(modelnr, model); 639 640 } 641 642 /** Retrieve all Chains belonging to a model . 643 * 644 * @param modelnr an int 645 * @return a List object 646 */ 647 @Override 648 public List<Chain> getModel(int modelnr) { 649 650 return models.get(modelnr).getChains(); 651 } 652 653 /** {@inheritDoc} */ 654 @Override 655 public Chain getChainByPDB(String authId, int modelnr) 656 throws StructureException{ 657 658 Chain c = getPolyChainByPDB(authId, modelnr); 659 660 if (c==null ) { 661 throw new StructureException("Could not find chain with authId \"" + authId + "\"" + " for PDB id " + pdb_id + ", model "+modelnr); 662 } 663 664 return c; 665 } 666 667 /** {@inheritDoc} */ 668 @Override 669 public Chain getChain(String asymId, int modelnr) { 670 671 List<Chain> chains = getChains(modelnr); 672 for (Chain c : chains) { 673 if (c.getId().equals(asymId)) { 674 return c; 675 } 676 } 677 return null; 678 679 } 680 681 /** {@inheritDoc} */ 682 @Override 683 public Chain getChain(String asymId) { 684 685 return getChain(asymId,0); 686 687 } 688 689 /** {@inheritDoc} */ 690 @Override 691 public Chain getChainByPDB(String chainId) 692 throws StructureException{ 693 if(nrModels() < 1 ) { 694 throw new StructureException("No chains are present."); 695 } 696 return getChainByPDB(chainId,0); 697 } 698 699 @Override 700 public Chain getPolyChain(String asymId) { 701 return getPolyChain(asymId, 0); 702 703 } 704 705 @Override 706 public Chain getPolyChain(String asymId, int modelIdx) { 707 Model model = models.get(modelIdx); 708 if (model==null) { 709 return null; 710 } 711 List<Chain> polyChains = model.getPolyChains(); 712 for (Chain c : polyChains){ 713 if (c.getId().equals(asymId)) 714 return c; 715 } 716 return null; 717 } 718 719 720 @Override 721 public Chain getNonPolyChain(String asymId) { 722 return getNonPolyChain(asymId, 0); 723 } 724 725 @Override 726 public Chain getNonPolyChain(String asymId, int modelIdx) { 727 Model model = models.get(modelIdx); 728 if (model==null) { 729 return null; 730 } 731 732 List<Chain> nonpolyChains = model.getNonPolyChains(); 733 for (Chain c : nonpolyChains){ 734 if (c.getId().equals(asymId)) 735 return c; 736 } 737 738 return null; 739 } 740 741 @Override 742 public Chain getPolyChainByPDB(String authId) { 743 return getPolyChainByPDB(authId, 0); 744 } 745 746 @Override 747 public Chain getPolyChainByPDB(String authId, int modelIdx) { 748 Model model = models.get(modelIdx); 749 if (model==null) { 750 return null; 751 } 752 753 List<Chain> polyChains = model.getPolyChains(); 754 for (Chain c : polyChains){ 755 if (c.getName().equals(authId)) 756 return c; 757 } 758 759 return null; 760 } 761 762 @Override 763 public List<Chain> getNonPolyChainsByPDB(String authId) { 764 return getNonPolyChainsByPDB(authId, 0); 765 } 766 767 @Override 768 public List<Chain> getNonPolyChainsByPDB(String authId, int modelIdx) { 769 List<Chain> chains = new ArrayList<>(); 770 Model model = models.get(modelIdx); 771 if (model==null) { 772 return chains; 773 } 774 775 776 List<Chain> nonpolyChains = model.getNonPolyChains(); 777 for (Chain c : nonpolyChains){ 778 if (c.getName().equals(authId)) 779 chains.add(c); 780 } 781 782 return chains; 783 } 784 785 @Override 786 public Chain getWaterChain(String asymId) { 787 return getWaterChain(asymId, 0); 788 } 789 790 791 @Override 792 public Chain getWaterChain(String asymId, int modelIdx) { 793 Model model = models.get(modelIdx); 794 if (model==null) { 795 return null; 796 } 797 List<Chain> waterChains = model.getWaterChains(); 798 for (Chain c : waterChains){ 799 if (c.getId().equals(asymId)) 800 return c; 801 } 802 return null; 803 } 804 805 806 @Override 807 public Chain getWaterChainByPDB(String authId) { 808 return getWaterChainByPDB(authId, 0); 809 } 810 811 812 @Override 813 public Chain getWaterChainByPDB(String authId, int modelIdx) { 814 Model model = models.get(modelIdx); 815 if (model==null) { 816 return null; 817 } 818 List<Chain> waterChains = model.getWaterChains(); 819 for (Chain c : waterChains){ 820 if (c.getName().equals(authId)) 821 return c; 822 } 823 824 return null; 825 } 826 827 828 829 /** {@inheritDoc} */ 830 @Override 831 public String toPDB() { 832 FileConvert f = new FileConvert(this) ; 833 return f.toPDB(); 834 } 835 836 /** {@inheritDoc} */ 837 @Override 838 public String toMMCIF() { 839 FileConvert f = new FileConvert(this); 840 return f.toMMCIF(); 841 } 842 843 /** {@inheritDoc} */ 844 @Override 845 public boolean hasChain(String authId) { 846 int modelnr = 0; 847 848 List<Chain> chains = getChains(modelnr); 849 for (Chain c : chains) { 850 // we check here with equals because we might want to distinguish between upper and lower case chains! 851 if (c.getId().equals(authId)) { 852 return true; 853 } 854 } 855 return false; 856 } 857 858 /** {@inheritDoc} */ 859 @Override 860 public boolean hasNonPolyChain(String asymId){ 861 int modelnr = 0; 862 863 List<Chain> chains = models.get(modelnr).getNonPolyChains(); 864 for (Chain c : chains) { 865 // we check here with equals because we might want to distinguish between upper and lower case chains! 866 if (c.getId().equals(asymId)) { 867 return true; 868 } 869 } 870 return false; 871 } 872 873 /** {@inheritDoc} */ 874 @Override 875 public boolean hasPdbChain(String authId) { 876 int modelnr = 0; 877 878 List<Chain> chains = getChains(modelnr); 879 for (Chain c : chains) { 880 // we check here with equals because we might want to distinguish between upper and lower case chains! 881 if (c.getName().equals(authId)) { 882 return true; 883 } 884 } 885 return false; 886 } 887 888 /** {@inheritDoc} */ 889 @Override 890 public void setEntityInfos(List<EntityInfo> molList){ 891 this.entityInfos = molList; 892 } 893 894 /** {@inheritDoc} */ 895 @Override 896 public void addEntityInfo(EntityInfo entityInfo) { 897 this.entityInfos.add(entityInfo); 898 } 899 900 /** {@inheritDoc} */ 901 @Override 902 public List<EntityInfo> getEntityInfos() { 903 return entityInfos; 904 } 905 906 /** {@inheritDoc} */ 907 @Override 908 public EntityInfo getCompoundById(int molId) { 909 return getEntityById(molId); 910 } 911 912 /** {@inheritDoc} */ 913 @Override 914 public EntityInfo getEntityById(int entityId) { 915 for (EntityInfo mol : this.entityInfos){ 916 if (mol.getMolId()==entityId){ 917 return mol; 918 } 919 } 920 return null; 921 } 922 923 924 /** {@inheritDoc} */ 925 @Override 926 public List<DBRef> getDBRefs() { 927 return dbrefs; 928 } 929 930 931 /** {@inheritDoc} */ 932 @Override 933 public void setDBRefs(List<DBRef> dbrefs) { 934 if ( dbrefs == null) 935 throw new IllegalArgumentException("trying to set dbrefs to null!"); 936 937 for( DBRef ref : dbrefs){ 938 ref.setParent(this); 939 } 940 this.dbrefs = dbrefs; 941 } 942 943 944 /** {@inheritDoc} */ 945 @Override 946 public PDBHeader getPDBHeader() { 947 return pdbHeader; 948 } 949 950 /** {@inheritDoc} */ 951 @Override 952 public void setPDBHeader(PDBHeader pdbHeader){ 953 this.pdbHeader = pdbHeader; 954 } 955 956 /** {@inheritDoc} */ 957 @Override 958 public List<Bond> getSSBonds(){ 959 return ssbonds; 960 961 } 962 963 /** {@inheritDoc} */ 964 @Override 965 public void setSSBonds(List<Bond> ssbonds){ 966 this.ssbonds = ssbonds; 967 } 968 969 /** 970 * Adds a single disulfide Bond to this structure 971 * 972 * @param ssbond the SSBond. 973 */ 974 @Override 975 public void addSSBond(Bond ssbond){ 976 ssbonds.add(ssbond); 977 } 978 979 /** 980 * Return whether or not the entry has an associated journal article 981 * or publication. The JRNL section is not mandatory and thus may not be 982 * present. 983 * @return flag if a JournalArticle could be found. 984 */ 985 @Override 986 public boolean hasJournalArticle() { 987 return this.pdbHeader.hasJournalArticle(); 988 } 989 990 /** 991 * get the associated publication as defined by the JRNL records in a PDB 992 * file. 993 * @return a JournalArticle 994 */ 995 @Override 996 public JournalArticle getJournalArticle() { 997 return this.pdbHeader.getJournalArticle(); 998 } 999 1000 /** 1001 * set the associated publication as defined by the JRNL records in a PDB 1002 * file. 1003 * @param journalArticle the article 1004 */ 1005 @Override 1006 public void setJournalArticle(JournalArticle journalArticle) { 1007 this.pdbHeader.setJournalArticle(journalArticle); 1008 } 1009 1010 /** 1011 * @return the sites contained in this structure 1012 */ 1013 1014 @Override 1015 public List<Site> getSites() { 1016 return sites; 1017 } 1018 1019 /** 1020 * @param sites the sites to set in the structure 1021 */ 1022 1023 @Override 1024 public void setSites(List<Site> sites) { 1025 this.sites = sites; 1026 } 1027 1028 /** Caution: we should probably remove this to avoid confusion. Currently this is always an empty list! 1029 * 1030 * @return a list of Groups listed in the HET records - this will not 1031 * include any waters. 1032 */ 1033 1034 /** 1035 * Sets a flag to indicate if this structure is a biological assembly 1036 * @param biologicalAssembly true if biological assembly, otherwise false 1037 * @since 3.2 1038 */ 1039 @Override 1040 public void setBiologicalAssembly(boolean biologicalAssembly) { 1041 this.biologicalAssembly = biologicalAssembly; 1042 } 1043 1044 /** 1045 * Gets flag that indicates if this structure is a biological assembly 1046 * @return the sites contained in this structure 1047 * @since 3.2 1048 */ 1049 @Override 1050 public boolean isBiologicalAssembly() { 1051 return biologicalAssembly; 1052 } 1053 1054 /** 1055 * Sets crystallographic information for this structure 1056 * @param crystallographicInfo crystallographic information 1057 * @since 3.2 1058 */ 1059 1060 @Override 1061 public void setCrystallographicInfo(PDBCrystallographicInfo crystallographicInfo) { 1062 this.pdbHeader.setCrystallographicInfo(crystallographicInfo); 1063 } 1064 1065 /** 1066 * Gets crystallographic information for this structure 1067 * @return PDBCrystallographicInfo crystallographic information 1068 * @since 3.2 1069 */ 1070 @Override 1071 public PDBCrystallographicInfo getCrystallographicInfo() { 1072 return pdbHeader.getCrystallographicInfo(); 1073 } 1074 1075 /** {@inheritDoc} */ 1076 @Override 1077 public String getIdentifier() { 1078 //1. StructureIdentifier 1079 if(getStructureIdentifier() != null) { 1080 return getStructureIdentifier().getIdentifier(); 1081 } 1082 //2. Name 1083 if(getName() != null) { 1084 return getName(); 1085 } 1086 //3. PDBCode + ranges 1087 return toCanonical().getIdentifier(); 1088 } 1089 1090 /** {@inheritDoc} */ 1091 @Deprecated 1092 @Override 1093 public String getPdbId() { 1094 return pdb_id; 1095 } 1096 1097 /** {@inheritDoc} */ 1098 @Override 1099 public void resetModels() { 1100 models = new ArrayList<>(); 1101 } 1102 /** {@inheritDoc} */ 1103 @Deprecated 1104 @Override 1105 public List<ResidueRange> getResidueRanges() { 1106 return toCanonical().getResidueRanges(); 1107 } 1108 /** {@inheritDoc} */ 1109 @Deprecated 1110 @Override 1111 public List<String> getRanges() { 1112 return ResidueRange.toStrings(getResidueRanges()); 1113 } 1114 1115 /** 1116 * Creates a SubstructureIdentifier based on the residues in this Structure. 1117 * 1118 * Only the first and last residues of each chain are considered, so chains 1119 * with gaps 1120 * @return A {@link SubstructureIdentifier} with residue ranges constructed from each chain 1121 */ 1122 private SubstructureIdentifier toCanonical() { 1123 StructureIdentifier real = getStructureIdentifier(); 1124 if(real != null) { 1125 try { 1126 return real.toCanonical(); 1127 } catch (StructureException e) { 1128 // generate fake one if needed 1129 } 1130 } 1131 1132 // No identifier set, so generate based on residues present in the structure 1133 List<ResidueRange> range = new ArrayList<>(); 1134 for (Chain chain : getChains()) { 1135 List<Group> groups = chain.getAtomGroups(); 1136 ListIterator<Group> groupsIt = groups.listIterator(); 1137 if(!groupsIt.hasNext()) { 1138 continue; // no groups in chain 1139 } 1140 Group g = groupsIt.next(); 1141 ResidueNumber first = g.getResidueNumber(); 1142 1143 //TODO Detect missing intermediate residues -sbliven, 2015-01-28 1144 //Already better than previous whole-chain representation 1145 1146 // get last residue 1147 while(groupsIt.hasNext()) { 1148 g = groupsIt.next(); 1149 } 1150 ResidueNumber last = g.getResidueNumber(); 1151 1152 range.add(new ResidueRange(chain.getName(),first,last)); 1153 } 1154 return new SubstructureIdentifier(getPDBCode(),range); 1155 } 1156 1157 1158 1159 1160 1161}