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