diff --git a/biojava-aa-prop/pom.xml b/biojava-aa-prop/pom.xml index 56992a067a..e0083abd83 100644 --- a/biojava-aa-prop/pom.xml +++ b/biojava-aa-prop/pom.xml @@ -2,7 +2,7 @@ biojava org.biojava - 4.2.1 + 4.2.2 4.0.0 biojava-aa-prop @@ -70,12 +70,12 @@ org.biojava biojava-core - 4.2.1 + 4.2.2 org.biojava biojava-structure - 4.2.1 + 4.2.2 diff --git a/biojava-alignment/pom.xml b/biojava-alignment/pom.xml index 99133e7a97..70f3e659f6 100644 --- a/biojava-alignment/pom.xml +++ b/biojava-alignment/pom.xml @@ -4,7 +4,7 @@ biojava org.biojava - 4.2.1 + 4.2.2 biojava-alignment biojava-alignment @@ -46,7 +46,7 @@ org.biojava biojava-core - 4.2.1 + 4.2.2 compile @@ -74,7 +74,7 @@ org.biojava biojava-phylo - 4.2.1 + 4.2.2 diff --git a/biojava-core/pom.xml b/biojava-core/pom.xml index d5f45ef45b..352ffa37e8 100644 --- a/biojava-core/pom.xml +++ b/biojava-core/pom.xml @@ -3,7 +3,7 @@ biojava org.biojava - 4.2.1 + 4.2.2 4.0.0 biojava-core diff --git a/biojava-genome/pom.xml b/biojava-genome/pom.xml index 5ca7be55b6..e78cefe396 100644 --- a/biojava-genome/pom.xml +++ b/biojava-genome/pom.xml @@ -3,7 +3,7 @@ biojava org.biojava - 4.2.1 + 4.2.2 4.0.0 biojava-genome @@ -79,13 +79,13 @@ org.biojava biojava-core - 4.2.1 + 4.2.2 compile org.biojava biojava-alignment - 4.2.1 + 4.2.2 compile diff --git a/biojava-integrationtest/pom.xml b/biojava-integrationtest/pom.xml index c269db8521..ecdaf3e4a3 100644 --- a/biojava-integrationtest/pom.xml +++ b/biojava-integrationtest/pom.xml @@ -4,7 +4,7 @@ biojava org.biojava - 4.2.1 + 4.2.2 biojava-integrationtest jar @@ -32,7 +32,7 @@ org.biojava biojava-structure - 4.2.1 + 4.2.2 diff --git a/biojava-modfinder/pom.xml b/biojava-modfinder/pom.xml index eda4cc2aae..8bbe1063cc 100644 --- a/biojava-modfinder/pom.xml +++ b/biojava-modfinder/pom.xml @@ -4,7 +4,7 @@ biojava org.biojava - 4.2.1 + 4.2.2 biojava-modfinder biojava-modfinder @@ -31,7 +31,7 @@ org.biojava biojava-structure - 4.2.1 + 4.2.2 jar compile diff --git a/biojava-modfinder/src/main/java/org/biojava/nbio/protmod/structure/ProteinModificationIdentifier.java b/biojava-modfinder/src/main/java/org/biojava/nbio/protmod/structure/ProteinModificationIdentifier.java index 0e0b1fad82..67d85524e0 100644 --- a/biojava-modfinder/src/main/java/org/biojava/nbio/protmod/structure/ProteinModificationIdentifier.java +++ b/biojava-modfinder/src/main/java/org/biojava/nbio/protmod/structure/ProteinModificationIdentifier.java @@ -95,7 +95,7 @@ public void setbondLengthTolerance(final double bondLengthTolerance) { /** * - * @param recordUnidentifiableAtomLinkages true if choosing to record unidentifiable + * @param recordUnidentifiableModifiedCompounds true if choosing to record unidentifiable * atoms; false, otherwise. * @see #getRecordUnidentifiableCompounds * @see #getUnidentifiableModifiedResidues @@ -276,7 +276,6 @@ public void identify(final List chains, List ress = StructureUtil.getAminoAcids(chain); - //List ligs = chain.getAtomLigands(); List ligs = StructureTools.filterLigands(chain.getAtomGroups()); residues.addAll(ress); @@ -378,9 +377,10 @@ private void processCrosslink1(Map> mapCompGroups, /** * identify additional groups that are not directly attached to amino acids. - * @param mc {@link ModifiedCompound}. - * @param chain a {@link Chain}. - * @return a list of added groups. + * @param mc {@link ModifiedCompound} + * @param ligands {@link Group} + * @param chains List of {@link Chain}s + * @return a list of added groups */ private void identifyAdditionalAttachments(ModifiedCompound mc, List ligands, Map mapChainIdChain) { @@ -406,7 +406,9 @@ private void identifyAdditionalAttachments(ModifiedCompound mc, resNum.setSeqNum(num.getResidueNumber()); resNum.setInsCode(num.getInsCode()); //group = chain.getGroupByPDB(numIns); + group = mapChainIdChain.get(num.getChainId()).getGroupByPDB(resNum); + //group = mapChainIdChain.get(num.getChainId()).getGroupByPDB(resNum); } catch (StructureException e) { logger.error("Exception: ", e); // should not happen @@ -442,6 +444,23 @@ private void identifyAdditionalAttachments(ModifiedCompound mc, } } + private Group getGroup(StructureGroup num, List chains) throws StructureException { + for (Chain c : chains){ + if ( c.getId().equals(num.getChainId())){ + + ResidueNumber resNum = new ResidueNumber(); + + resNum.setSeqNum(num.getResidueNumber()); + resNum.setInsCode(num.getInsCode()); + + + return c.getGroupByPDB(resNum); + } + } + + throw new StructureException("Could not find residue " + num); + } + /** * Merge identified modified compounds if linked. */ @@ -547,6 +566,8 @@ private void recordUnidentifiableModifiedResidues(List modComp if (group.getType().equals(GroupType.HETATM)) { StructureGroup strucGroup = StructureUtil.getStructureGroup( group, true); + //strucGroup.setChainId(group.getChainId()); + if (!identifiedComps.contains(strucGroup)) { unidentifiableModifiedResidues.add(strucGroup); } @@ -777,13 +798,12 @@ private List> getMatchedAtomsOfLinkages( return matchedAtomsOfLinkages; } - /** - * Assembly the matched linkages. + /** Assembly the matched linkages + * * @param matchedAtomsOfLinkages * @param mod - * @param condition - * @param ret ModifiedCompound will be stored here. - */ + * @param ret ModifiedCompound will be stored here + */ private void assembleLinkages(List> matchedAtomsOfLinkages, ProteinModification mod, List ret) { ModificationCondition condition = mod.getCondition(); diff --git a/biojava-modfinder/src/main/java/org/biojava/nbio/protmod/structure/StructureUtil.java b/biojava-modfinder/src/main/java/org/biojava/nbio/protmod/structure/StructureUtil.java index 745ef09a45..80b4a10d33 100644 --- a/biojava-modfinder/src/main/java/org/biojava/nbio/protmod/structure/StructureUtil.java +++ b/biojava-modfinder/src/main/java/org/biojava/nbio/protmod/structure/StructureUtil.java @@ -25,10 +25,13 @@ package org.biojava.nbio.protmod.structure; import org.biojava.nbio.structure.*; +import org.biojava.nbio.structure.io.mmcif.MetalBondParser; +import org.biojava.nbio.structure.io.mmcif.chem.MetalBondDistance; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; public final class StructureUtil { private StructureUtil() { @@ -53,7 +56,11 @@ public static StructureGroup getStructureGroup(Group group, boolean isAminoAcid) * @return the {@link StructureAtom} of the atom. */ public static StructureAtom getStructureAtom(Atom atom, boolean isParentAminoAcid) { - StructureGroup strucGroup = getStructureGroup(atom.getGroup(), isParentAminoAcid); + + Group g = atom.getGroup(); + String chainId = g.getChainId(); + StructureGroup strucGroup = getStructureGroup(g, isParentAminoAcid); + strucGroup.setChainId(chainId); return new StructureAtom(strucGroup, atom.getName()); } @@ -104,6 +111,8 @@ public static double getAtomDistance(Atom atom1, Atom atom2) { public static Atom[] findNearestAtomLinkage(final Group group1, final Group group2, List potentialNamesOfAtomOnGroup1, List potentialNamesOfAtomOnGroup2, final boolean ignoreNCLinkage, double bondLengthTolerance) { + + List linkages = findAtomLinkages(group1, group2, potentialNamesOfAtomOnGroup1, potentialNamesOfAtomOnGroup2, ignoreNCLinkage, bondLengthTolerance); @@ -216,31 +225,96 @@ public static List findAtomLinkages(final Group group1, public static Atom[] findLinkage(final Group group1, final Group group2, String nameOfAtomOnGroup1, String nameOfAtomOnGroup2, double bondLengthTolerance) { - Atom[] ret = new Atom[2]; - double distance; + Atom[] ret = new Atom[2]; ret[0] = group1.getAtom(nameOfAtomOnGroup1); ret[1] = group2.getAtom(nameOfAtomOnGroup2); + if (ret[0]==null || ret[1]==null) { return null; } - distance = Calc.getDistance(ret[0], ret[1]); + Atom a1 = ret[0]; + Atom a2 = ret[1]; + boolean hasBond = a1.hasBond(a2); - float radiusOfAtom1 = ret[0].getElement().getCovalentRadius(); - float radiusOfAtom2 = ret[1].getElement().getCovalentRadius(); + if ( hasBond ) { + + return ret; + } + + // is it a metal ? + + if ( a1.getElement().isMetal() || a2.getElement().isMetal()){ + + MetalBondDistance defined = getMetalDistanceCutoff(a1.getElement().name(),a2.getElement().name()); + + if ( defined != null) { + + if (hasMetalBond(a1, a2, defined)) + return ret; + else + return null; + } - if (Math.abs(distance-radiusOfAtom1 -radiusOfAtom2) - > bondLengthTolerance) { - return null; } + // not a metal + + double distance = Calc.getDistance(a1, a2); + + float radiusOfAtom1 = ret[0].getElement().getCovalentRadius(); + float radiusOfAtom2 = ret[1].getElement().getCovalentRadius(); + + if (Math.abs(distance - radiusOfAtom1 - radiusOfAtom2) + > bondLengthTolerance) { + return null; + } + + return ret; } + private static boolean hasMetalBond(Atom a1, Atom a2, MetalBondDistance definition) { + + double distance = Calc.getDistance(a1,a2); + + Float min = definition.getLowerLimit(); + Float max = definition.getUpperLimit(); + + return ( min < distance && max > distance); + + } + + private static MetalBondDistance getMetalDistanceCutoff(String name1, String name2) { + Map> defs= MetalBondParser.getMetalBondDefinitions(); + + List distances = defs.get(name1); + + if ( distances == null){ + + distances = defs.get(name2); + String tmp = name1; + name2 = name1; + name1 = tmp; + } + if ( distances == null){ + return null; + } + + for ( MetalBondDistance d : distances){ + if ( name1.equalsIgnoreCase(d.getAtomType1()) && name2.equalsIgnoreCase(d.getAtomType2()) ) + return d; + } + + // no matching atom definitions found + return null; + + } + /** * * @param group a {@link Group}. diff --git a/biojava-modfinder/src/main/resources/org/biojava/nbio/protmod/ptm_list.xml b/biojava-modfinder/src/main/resources/org/biojava/nbio/protmod/ptm_list.xml index b84b0226b6..f8e066d2f5 100644 --- a/biojava-modfinder/src/main/resources/org/biojava/nbio/protmod/ptm_list.xml +++ b/biojava-modfinder/src/main/resources/org/biojava/nbio/protmod/ptm_list.xml @@ -1,9 +1,20 @@ + - 2011-08-12 - Added glycosylation entries 386-429 + 2016-06-13 + Added new chromophore definitions + + + 2016-06-10 + Updated legacy chemical component and atom names to current naming conventions. Removed two obsolete entires (CLE and CGL) + + + 2016-05-10 + Added definition for PLP + 2011-08-12 + Added glycosylation entries 386-429 2011-07-26 @@ -68,7 +79,7 @@ ASN - + NAG @@ -728,7 +739,7 @@ (R)-2-amino-3-selanylpropanoic acid PDBCC - CSE + SEC selenocysteine @@ -743,7 +754,7 @@ - CSE + SEC natural @@ -956,7 +967,7 @@ PDBCC DDE - {3-[4-(2-amino-2-carboxy-ethyl)-1H-imidazol-2-yl]-1-carbamoyl-propyl}-trimethyl-ammonium + {3-[4-(2-amino-2-carboxy-ethyl)-1H-imidazol-2-yl]-1-carbamoyl-propyl}-trimethyl-ammonium RESID @@ -1351,35 +1362,6 @@ modified residue amidated carboxyl end - - 0045 - A protein modification that effectively converts an L-leucine residue to L-leucine amide. - (S)-2-amino-4-methylpentanamide - - PDBCC - CLE - leucine amide - - - RESID - AA0091 - L-leucine amide - - - PSI-MOD - MOD:00100 - L-leucine amide - - - - CLE - C - - - natural - modified residue - amidated carboxyl end - 0046 A protein modification that effectively converts an L-phenylalanine residue to L-phenylalanine amide. @@ -2917,6 +2899,8 @@ natural modified residue CRQ has two modifications: RESID:AA0183 and RESID:AA0189 + RCSB PDB added keyword chromoprotein + chromoprotein 0091 @@ -2974,6 +2958,8 @@ natural crosslink1 CRO has two modifications: RESID:AA0183 and RESID:AA0184 + RCSB PDB added keyword chromoprotein + chromoprotein 0093 @@ -3753,7 +3739,7 @@ (R)-2-amino-2-carboxyethanesulfinic acid PDBCC - CSW + CSD cysteine-S-dioxide @@ -3768,7 +3754,7 @@ - CSW + CSD natural @@ -4573,30 +4559,37 @@ SG + FE1,FE2,FE3,FE4,FE5,FE6,FE7,FE8 SG + FE1,FE2,FE3,FE4,FE5,FE6,FE7,FE8 SG + FE1,FE2,FE3,FE4,FE5,FE6,FE7,FE8 SG + FE1,FE2,FE3,FE4,FE5,FE6,FE7,FE8 SG + FE1,FE2,FE3,FE4,FE5,FE6,FE7,FE8 SG + FE1,FE2,FE3,FE4,FE5,FE6,FE7,FE8 OG + FE1,FE2,FE3,FE4,FE5,FE6,FE7,FE8 @@ -5944,6 +5937,8 @@ natural modified residue CRU has two modifications: RESID:AA0183 and RESID:AA0378 + RCSB PDB added keyword chromoprotein + chromoprotein 0173 @@ -6001,6 +5996,8 @@ natural modified residue CH6 has two modifications: RESID:AA0183 and RESID:AA0379 + RCSB PDB added keyword chromoprotein + chromoprotein 0175 @@ -6058,6 +6055,8 @@ natural modified residue NRQ has two modifications: RESID:AA0183 and RESID:AA0379 + RCSB PDB added keyword chromoprotein + chromoprotein 0177 @@ -6114,6 +6113,8 @@ natural modified residue NYG has two modifications: RESID:AA0183 and RESID:AA0380 + RCSB PDB added chromoprotein keyword + chromoprotein 0179 @@ -6197,6 +6198,8 @@ natural modified residue CR7 has two modifications: RESID:AA0183 and RESID:AA0381/AA0382 + RCSB PDB added keyword chromoprotein + chromoprotein 0182 @@ -6786,8 +6789,8 @@ SEC - SEG - SEG + SE + SE hypothetical @@ -6981,7 +6984,7 @@ MOD:00363 L-cysteinyl-L-selenocysteine (Cys-Sec) - + PDBCC SEC 2-amino-3-selenino-propionic acid @@ -6995,7 +6998,7 @@ SG - SEG + SE natural @@ -7058,7 +7061,7 @@ TY2 - CE2,CE1 + CE2 NE2 @@ -8485,7 +8488,7 @@ modified residue acetylated amino end - + 0255 A protein modification that effectively converts an L-glutamic acid residue to N-acetyl-L-glutamic acid. (S)-2-(acetamido)pentanedioic acid @@ -8512,8 +8515,8 @@ natural modified residue acetylated amino end - - + + 0256 A protein modification that effectively converts an L-threonine residue to N-acetyl-L-threonine. (2S,3R)-2-acetamido-3-hydroxybutanoic acid @@ -8540,7 +8543,7 @@ natural modified residue acetylated amino end - + 0257 A protein modification that effectively converts an L-serine residue to N-acetyl-L-serine. @@ -8568,7 +8571,7 @@ natural modified residue acetylated amino end - + 0258 A protein modification that effectively converts an L-tyrosine residue to N-acetyl-L-tyrosine. @@ -8625,7 +8628,7 @@ modified residue thioether bond acetylated amino end - + 0260 A protein modification that effectively converts a glycine residue to N-methylglycine. @@ -8654,7 +8657,7 @@ modified residue methylated amino acid methylated amino end - + 0261 A protein modification that effectively converts an L-arginine residue to L-arginine amide. @@ -8760,7 +8763,7 @@ natural attachment amidated carboxyl end - + 0264 A protein modification that effectively converts an L-phenylalanine residue to L-phenylalanine amide. @@ -8830,7 +8833,7 @@ natural attachment amidated carboxyl end - + 0266 A protein modification that effectively converts an L-serine residue to L-serine amide. @@ -8865,7 +8868,7 @@ natural attachment amidated carboxyl end - + 0267 A protein modification that effectively converts an L-serine residue to L-serine amide. @@ -8893,7 +8896,7 @@ natural modified residue amidated carboxyl end - + 0268 A protein modification that effectively converts an L-threonine residue to L-threonine amide. @@ -8928,8 +8931,8 @@ natural attachment amidated carboxyl end - - + + 0269 A protein modification that effectively converts an L-tryptophan residue to L-tryptophan amide. @@ -8964,7 +8967,7 @@ attachment amidated carboxyl end - + 0270 A protein modification that effectively converts an L-tryptophan residue to L-tryptophan amide. (2S)-2-amino-3-(1H-indol-3-yl)propanamide @@ -8991,7 +8994,7 @@ natural modified residue amidated carboxyl end - + 0271 A protein modification that effectively converts an L-tyrosine residue to L-tyrosine amide. @@ -9061,7 +9064,7 @@ natural attachment amidated carboxyl end - + 0273 A protein modification that effectively converts an L-cysteine residue to S-farnesyl-L-cysteine. @@ -9096,9 +9099,9 @@ natural attachment lipoprotein - prenylation - thioether bond - + prenylation + thioether bond + 0274 A protein modification that effectively converts an L-cysteine residue to S-geranylgeranyl-L-cysteine. @@ -9133,9 +9136,9 @@ natural attachment lipoprotein - prenylation - thioether bond - + prenylation + thioether bond + 0275 A protein modification that effectively converts an L-cysteine, L-serine, or L-tyrosine residue to pyruvic acid. @@ -9173,8 +9176,8 @@ natural modified residue blocked amino end - - + + 0276 A protein modification that effectively converts an L-threonine residue into 2-oxobutanoic acid. 2-oxobutanoic acid @@ -9235,13 +9238,13 @@ natural attachment - chromoprotein - heme - iron - metalloprotein - thioether bond - - + chromoprotein + heme + iron + metalloprotein + thioether bond + + 0278 A protein modification that effectively converts an L-tyrosine residue to L-3',4'-dihydroxyphenylalanine. (S)-2-amino-3-(3,4-dihydroxyphenyl)propanoic acid @@ -9268,8 +9271,8 @@ natural modified residue hydroxylation - - + + 0279 A protein modification that effectively converts an L-tryptophan residue to L-6'-chlorotryptophan. (2S)-2-amino-3-(6-chloro-1H-indol-3-yl)propanoic acid @@ -9296,8 +9299,8 @@ natural modified residue chlorine - - + + 0280 A protein modification that effectively converts an L-threonine residue to dehydrobutyrine. (2Z)-2-aminobut-2-enoic acid @@ -9324,7 +9327,7 @@ natural modified residue - + 0281 A protein modification that effectively converts an L-serine residue to an amino-terminal lactic acid. @@ -9436,7 +9439,7 @@ natural modified residue D-amino acid - + 0285 A protein modification that effectively converts an L-leucine residue to D-leucine. @@ -9498,8 +9501,8 @@ natural attachment - phosphoprotein - + phosphoprotein + 0287 @@ -9533,7 +9536,7 @@ natural attachment - phosphoprotein + phosphoprotein 0288 @@ -9589,11 +9592,11 @@ natural crosslink4 - 2Fe-2S - metalloprotein - Rieske iron-sulfur protein + 2Fe-2S + metalloprotein + Rieske iron-sulfur protein - + 0289 A protein modification that effectively crosslinks an L-lysine residue and 5'-phosphoadenosine through a phosphoramide ester bond to form N6-(phospho-5'-adenosine)-L-lysine. (S)-2-amino-6-(5'-adenosine phosphonamino)hexanoic acid @@ -9627,39 +9630,6 @@ natural attachment phosphoprotein - - - 0290 - A protein modification that effectively converts an L-cysteine residue to S-glutathionyl-L-cysteine. - (2S)-2-amino-3-((2S)-2-((4R)-4-amino-4-carboxyl-1-oxobutyl)amino-3-(carboxylmethyl)amino-3-oxo-propyl)dithio-propanoic acid - - PDBCC - CGL - - - - RESID - AA0229 - L-cysteine glutathione disulfide - - - PSI-MOD - MOD:00234 - L-cysteine glutathione disulfide - - - PDBCC - CGL - cystine-glutathione - - - - CGL - - - natural - modified residue - disulfide bond 0291 @@ -9981,7 +9951,7 @@ (2R)-2-amino-6-[(2R,3R)-3-methyl-3,4-dihydro-2H-pyrrol-2-ylcarbonyl]aminohexanoic acid PDBCC - PYH + PYL N6-{[(2R,3R)-3-methyl-3,4-dihydro-2H-pyrrol-2-yl]carbonyl}-L-lysine @@ -9996,7 +9966,7 @@ - PYH + PYL natural @@ -10164,7 +10134,7 @@ modified residue - + 0306 A protein modification that effectively converts an L-tryptophan residue to a 2'-hydroxy-L-tryptophan. (2S)-2-amino-3-(2-hydroxy-1H-indol-3-yl)propanoic acid @@ -10192,7 +10162,7 @@ modified residue hydroxylation - + 0307 A protein modification that effectively converts an L-tryptophan residue to a 2'-oxo-L-tryptophan. (2S)-2-amino-3-[(3S)-2-oxo-2,3-dihydro-1H-indol-3-yl]propanoic acid @@ -10220,7 +10190,7 @@ modified residue - + 0308 The amino group of the following amino acid forms a thiopeptide bond. This is an amino(sulfanyl)methylidene in the tautomeric form. 5-hydroxy-2-(3-methylbutanoyl)-1,3-oxazole-4-carbothioic O-acid @@ -10249,7 +10219,7 @@ modified residue imidazolinone/oxazolinone ring - + 0309 The amino group of the following amino acid forms a thiopeptide bond. This is an amino(sulfanyl)methylidene in the tautomeric form 5-hydroxy-2-[(2S)-pyrrolidin-2-yl]-1,3-oxazole-4-carbothioic O-acid @@ -10278,7 +10248,7 @@ modified residue imidazolinone/oxazolinone ring - + 0310 A protein modification that effectively trioxygenates an L-cysteine residue to L-cysteine sulfonic acid. (2R)-2-amino-3-sulfopropanoic acid @@ -10330,7 +10300,7 @@ MET N - + FOR @@ -10368,7 +10338,7 @@ LYS - + FOR @@ -10381,68 +10351,68 @@ formylation - 0313 - A protein modification that effectively crosslinks an L-alanine residue and a glycine residue to form L-alanine 5-imidazolinone glycine. - (2-[(1S)-1-aminoethyl]-5-oxo-4,5-dihydro-1H-imidazol-1-yl)acetic acid - - RESID - AA0187 - L-alanine 5-imidazolinone glycine - - - PDBCC - AYG - [(4E)-2-[(1S)-1-aminoethyl]-4-(4-hydroxybenzylidene)-5-oxo-4,5-dihydro-1H-imidazol-1-yl]acetic acid - - - PDBCC - CRQ - [2-(3-carbamoyl-1-imino-propyl)-4-(4-hydroxy-benzylidene)-5-oxo-4,5-dihydro-imidazol-1-yl]-acetic acid - - - PDBCC - MDO - {2-[(1S)-1-aminoethyl]-4-methylidene-5-oxo-4,5-dihydro-1H-imidazol-1-yl}acetic acid - - - PDBCC - X9Q - {(2S)-2-[(1S)-1-aminoethyl]-4-benzyl-5-oxo-2,5-dihydro-1H-imidazol-1-yl}acetic acid - - - PSI-MOD - MOD:00195 - L-alanine 5-imidazolinone glycine - - + 0313 + A protein modification that effectively crosslinks an L-alanine residue and a glycine residue to form L-alanine 5-imidazolinone glycine. + (2-[(1S)-1-aminoethyl]-5-oxo-4,5-dihydro-1H-imidazol-1-yl)acetic acid + + RESID + AA0187 + L-alanine 5-imidazolinone glycine + + + PDBCC + AYG + [(4E)-2-[(1S)-1-aminoethyl]-4-(4-hydroxybenzylidene)-5-oxo-4,5-dihydro-1H-imidazol-1-yl]acetic acid + + + PDBCC + CRQ + [2-(3-carbamoyl-1-imino-propyl)-4-(4-hydroxy-benzylidene)-5-oxo-4,5-dihydro-imidazol-1-yl]-acetic acid + + + PDBCC + MDO + {2-[(1S)-1-aminoethyl]-4-methylidene-5-oxo-4,5-dihydro-1H-imidazol-1-yl}acetic acid + + + PDBCC + X9Q + {(2S)-2-[(1S)-1-aminoethyl]-4-benzyl-5-oxo-2,5-dihydro-1H-imidazol-1-yl}acetic acid + + + PSI-MOD + MOD:00195 + L-alanine 5-imidazolinone glycine + + AYG,CRQ,MDO,X9Q modified residue - natural - imidazolinone/oxazolinone ring - - - 0314 - A protein modification that effectively crosslinks an L-cysteine residue and a glycine residue to form L-cysteine 5-imidazolinone glycine. - (2-[(1R)-1-amino-2-sulfanylethyl]-5-oxo-4,5-dihydro-1H-imidazol-1-yl)acetic acid - - RESID - AA0188 - L-cysteine 5-imidazolinone glycine - - - PDBCC - GYC - [(4Z)-2-[(1R)-1-amino-2-mercaptoethyl]-4-(4-hydroxybenzylidene)-5-oxo-4,5-dihydro-1H-imidazol-1-yl]acetic acid - - - PSI-MOD - MOD:00196 - L-cysteine 5-imidazolinone glycine - - + natural + imidazolinone/oxazolinone ring + + + 0314 + A protein modification that effectively crosslinks an L-cysteine residue and a glycine residue to form L-cysteine 5-imidazolinone glycine. + (2-[(1R)-1-amino-2-sulfanylethyl]-5-oxo-4,5-dihydro-1H-imidazol-1-yl)acetic acid + + RESID + AA0188 + L-cysteine 5-imidazolinone glycine + + + PDBCC + GYC + [(4Z)-2-[(1R)-1-amino-2-mercaptoethyl]-4-(4-hydroxybenzylidene)-5-oxo-4,5-dihydro-1H-imidazol-1-yl]acetic acid + + + PSI-MOD + MOD:00196 + L-cysteine 5-imidazolinone glycine + + GYC @@ -10450,6 +10420,8 @@ modified residue natural imidazolinone/oxazolinone ring + from RCSB PDB + chromoprotein 0315 @@ -10471,10 +10443,11 @@ 1'-(phospho-5'-adenosine)-L-histidine + HIS - + AMP @@ -10484,32 +10457,32 @@ attachment natural - phosphoprotein - - - 0316 - a protein modification that effectively forms a O3-(N-acetylaminoglucosyl)serine - (2S)-2-amino-3-(2-acetamido-2-deoxy-beta-D-glucopyranosyloxy)propanoic acid - - RESID - AA0398 - O-(N-acetylamino)glucosyl-L-serine - - - PDBCC - NAG - N-acetyl-D-glucosamine - - - PSI-MOD - MOD:00805 - O-(N-acetylaminoglucosyl)-L-serine - - + phosphoprotein + + + 0316 + a protein modification that effectively forms a O3-(N-acetylaminoglucosyl)serine + (2S)-2-amino-3-(2-acetamido-2-deoxy-beta-D-glucopyranosyloxy)propanoic acid + + RESID + AA0398 + O-(N-acetylamino)glucosyl-L-serine + + + PDBCC + NAG + N-acetyl-D-glucosamine + + + PSI-MOD + MOD:00805 + O-(N-acetylaminoglucosyl)-L-serine + + SER - + NAG @@ -10519,32 +10492,32 @@ attachment natural - glycoprotein - - - 0317 - a protein modification that effectively forms a O3-(N-acetylaminoglucosyl)threonine - (2S,3R)-2-amino-3-(alpha-D-2-acetamido-2-deoxyglucopyranosyloxy)butanoic acid - - RESID - AA0399 - O-(N-acetylamino)glucosyl-L-threonine - - - PDBCC - NDG - 2-(acetylamino)-2-deoxy-A-D-glucopyranose - - - PSI-MOD - MOD:00806 - O-(N-acetylaminoglucosyl)-L-threonine - - + glycoprotein + + + 0317 + a protein modification that effectively forms a O3-(N-acetylaminoglucosyl)threonine + (2S,3R)-2-amino-3-(alpha-D-2-acetamido-2-deoxyglucopyranosyloxy)butanoic acid + + RESID + AA0399 + O-(N-acetylamino)glucosyl-L-threonine + + + PDBCC + NDG + 2-(acetylamino)-2-deoxy-A-D-glucopyranose + + + PSI-MOD + MOD:00806 + O-(N-acetylaminoglucosyl)-L-threonine + + THR - + NDG @@ -10553,36 +10526,39 @@ attachment - natural - glycoprotein - - - 0318 - A protein modification that effectively crosslinks an L-aspartic acid residue and a glycine residue to form 2-imino-alanine 5-imidazolinone glycine. - (2-ethanimidoyl-5-oxo-4,5-dihydro-1H-imidazol-1-yl)acetic acid - - RESID - AA0410 - 2-imino-alanine 5-imidazolinone glycine - - - PDBCC - XYG - [(4Z)-2-[(1Z)-ethanimidoyl]-4-(4-hydroxybenzylidene)-5-oxo-4,5-dihydro-1H-imidazol-1-yl]acetic acid - - - PSI-MOD - MOD:00820 - 2-imino-alanine 5-imidazolinone glycine - - + natural + glycoprotein + + + 0318 + A protein modification that effectively crosslinks an L-aspartic acid residue and a glycine residue to form 2-imino-alanine 5-imidazolinone glycine. + (2-ethanimidoyl-5-oxo-4,5-dihydro-1H-imidazol-1-yl)acetic acid + + RESID + AA0410 + 2-imino-alanine 5-imidazolinone glycine + + + PDBCC + XYG + [(4Z)-2-[(1Z)-ethanimidoyl]-4-(4-hydroxybenzylidene)-5-oxo-4,5-dihydro-1H-imidazol-1-yl]acetic acid + + + PSI-MOD + MOD:00820 + 2-imino-alanine 5-imidazolinone glycine + + XYG + modified residue natural imidazolinone/oxazolinone ring + RCSB PDB added keyword chromoprotein + chromoprotein 0319 @@ -10608,17 +10584,17 @@ SUI - modified residue - hypothetical - - + modified residue + hypothetical + + 320 Metal coordination - PDBCC - AG - silver ion - + PDBCC + AG + silver ion + * @@ -10639,10 +10615,10 @@ 321 Metal coordination - PDBCC - AL - aluminum ion - + PDBCC + AL + aluminum ion + * @@ -10663,10 +10639,10 @@ 322 Metal coordination - PDBCC - AU - gold ion - + PDBCC + AU + gold ion + * @@ -10687,10 +10663,10 @@ 323 Metal coordination - PDBCC - AU3 - gold 3+ ion - + PDBCC + AU3 + gold 3+ ion + * @@ -10711,10 +10687,10 @@ 324 Metal coordination - PDBCC - BA - barium ion - + PDBCC + BA + barium ion + * @@ -10735,10 +10711,10 @@ 325 Metal coordination - PDBCC - CA - calcium ion - + PDBCC + CA + calcium ion + * @@ -10759,10 +10735,10 @@ 326 Metal coordination - PDBCC - CD - cadmium ion - + PDBCC + CD + cadmium ion + * @@ -10783,10 +10759,10 @@ 327 Metal coordination - PDBCC - CE - cerium (III) ion - + PDBCC + CE + cerium (III) ion + * @@ -10807,10 +10783,10 @@ 328 Metal coordination - PDBCC - CO - cobat (II) ion - + PDBCC + CO + cobat (II) ion + * @@ -10831,10 +10807,10 @@ 329 Metal coordination - PDBCC - 3CO - cobat (III) ion - + PDBCC + 3CO + cobat (III) ion + * @@ -10855,10 +10831,10 @@ 330 Metal coordination - PDBCC - CR - chromium ion - + PDBCC + CR + chromium ion + * @@ -10879,10 +10855,10 @@ 331 Metal coordination - PDBCC - CS - cesium ion - + PDBCC + CS + cesium ion + * @@ -10903,10 +10879,10 @@ 332 Metal coordination - PDBCC - CU - copper (II) ion - + PDBCC + CU + copper (II) ion + * @@ -10927,10 +10903,10 @@ 333 Metal coordination - PDBCC - CU1 - copper (I) ion - + PDBCC + CU1 + copper (I) ion + * @@ -10951,10 +10927,10 @@ 334 Metal coordination - PDBCC - CU3 - copper (III) ion - + PDBCC + CU3 + copper (III) ion + * @@ -10975,10 +10951,10 @@ 335 Metal coordination - PDBCC - ER3 - erbium (III) ion - + PDBCC + ER3 + erbium (III) ion + * @@ -10995,14 +10971,14 @@ undefined Metal coordination - + 336 Metal coordination - PDBCC - EU - europium ion - + PDBCC + EU + europium ion + * @@ -11023,10 +10999,10 @@ 337 Metal coordination - PDBCC - EU3 - europium (III) ion - + PDBCC + EU3 + europium (III) ion + * @@ -11047,10 +11023,10 @@ 338 Metal coordination - PDBCC - FE - Fe (III) ion - + PDBCC + FE + Fe (III) ion + * @@ -11071,10 +11047,10 @@ 339 Metal coordination - PDBCC - FE2 - Fe (II) ion - + PDBCC + FE2 + Fe (II) ion + * @@ -11095,10 +11071,10 @@ 341 Metal coordination - PDBCC - GA - gallium (III) ion - + PDBCC + GA + gallium (III) ion + * @@ -11119,10 +11095,10 @@ 342 Metal coordination - PDBCC - GD - gadolinium ion - + PDBCC + GD + gadolinium ion + * @@ -11143,10 +11119,10 @@ 343 Metal coordination - PDBCC - GD3 - gadolinium (III) ion - + PDBCC + GD3 + gadolinium (III) ion + * @@ -11167,10 +11143,10 @@ 344 Metal coordination - PDBCC - HG - mercury (II) ion - + PDBCC + HG + mercury (II) ion + * @@ -11191,10 +11167,10 @@ 345 Metal coordination - PDBCC - HO - holmium ion - + PDBCC + HO + holmium ion + * @@ -11215,10 +11191,10 @@ 346 Metal coordination - PDBCC - HO3 - holmium (III) ion - + PDBCC + HO3 + holmium (III) ion + * @@ -11239,10 +11215,10 @@ 347 Metal coordination - PDBCC - IN - indium (III) ion - + PDBCC + IN + indium (III) ion + * @@ -11263,10 +11239,10 @@ 348 Metal coordination - PDBCC - IR - iridium ion - + PDBCC + IR + iridium ion + * @@ -11287,10 +11263,10 @@ 349 Metal coordination - PDBCC - IR3 - iridium (III) ion - + PDBCC + IR3 + iridium (III) ion + * @@ -11311,10 +11287,10 @@ 350 Metal coordination - PDBCC - K - potassium ion - + PDBCC + K + potassium ion + * @@ -11335,10 +11311,10 @@ 351 Metal coordination - PDBCC - LA - lanthanum (III) ion - + PDBCC + LA + lanthanum (III) ion + * @@ -11359,10 +11335,10 @@ 352 Metal coordination - PDBCC - LI - lithium ion - + PDBCC + LI + lithium ion + * @@ -11383,10 +11359,10 @@ 353 Metal coordination - PDBCC - LU - lutetium (III) ion - + PDBCC + LU + lutetium (III) ion + * @@ -11407,10 +11383,10 @@ 354 Metal coordination - PDBCC - MG - magnesium ion - + PDBCC + MG + magnesium ion + * @@ -11431,10 +11407,10 @@ 355 Metal coordination - PDBCC - MN - manganese (II) ion - + PDBCC + MN + manganese (II) ion + * @@ -11455,10 +11431,10 @@ 356 Metal coordination - PDBCC - MN3 - manganese (III) ion - + PDBCC + MN3 + manganese (III) ion + * @@ -11479,10 +11455,10 @@ 357 Metal coordination - PDBCC - MO - molybdenum ion - + PDBCC + MO + molybdenum ion + * @@ -11503,10 +11479,10 @@ 358 Metal coordination - PDBCC - 4MO - molybdenum (IV) ion - + PDBCC + 4MO + molybdenum (IV) ion + * @@ -11523,14 +11499,14 @@ undefined Metal coordination - + 359 Metal coordination - PDBCC - 6MO - molybdenum (VI) ion - + PDBCC + 6MO + molybdenum (VI) ion + * @@ -11551,10 +11527,10 @@ 360 Metal coordination - PDBCC - NA - sodium ion - + PDBCC + NA + sodium ion + * @@ -11575,10 +11551,10 @@ 361 Metal coordination - PDBCC - NI - nickel (II) ion - + PDBCC + NI + nickel (II) ion + * @@ -11599,10 +11575,10 @@ 362 Metal coordination - PDBCC - 3NI - nickel (III) ion - + PDBCC + 3NI + nickel (III) ion + * @@ -11623,10 +11599,10 @@ 363 Metal coordination - PDBCC - OS - osmium ion - + PDBCC + OS + osmium ion + * @@ -11647,10 +11623,10 @@ 364 Metal coordination - PDBCC - OS4 - osmium (IV) ion - + PDBCC + OS4 + osmium (IV) ion + * @@ -11671,10 +11647,10 @@ 365 Metal coordination - PDBCC - PB - lead (II) ion - + PDBCC + PB + lead (II) ion + * @@ -11695,10 +11671,10 @@ 366 Metal coordination - PDBCC - PD - palladium ion - + PDBCC + PD + palladium ion + * @@ -11719,10 +11695,10 @@ 367 Metal coordination - PDBCC - PR - praseodymium ion - + PDBCC + PR + praseodymium ion + * @@ -11743,10 +11719,10 @@ 368 Metal coordination - PDBCC - PT - platinum (II) ion - + PDBCC + PT + platinum (II) ion + * @@ -11767,10 +11743,10 @@ 369 Metal coordination - PDBCC - PT4 - platinum (IV) ion - + PDBCC + PT4 + platinum (IV) ion + * @@ -11791,10 +11767,10 @@ 370 Metal coordination - PDBCC - RB - rubidium ion - + PDBCC + RB + rubidium ion + * @@ -11815,10 +11791,10 @@ 371 Metal coordination - PDBCC - RE - rhenium ion - + PDBCC + RE + rhenium ion + * @@ -11835,14 +11811,14 @@ undefined Metal coordination - + 0252 Metal coordination - PDBCC - RH - rhodium ion - + PDBCC + RH + rhodium ion + * @@ -11863,10 +11839,10 @@ 372 Metal coordination - PDBCC - RH3 - rhodium (III) ion - + PDBCC + RH3 + rhodium (III) ion + * @@ -11887,10 +11863,10 @@ 373 Metal coordination - PDBCC - RU - ruthenium ion - + PDBCC + RU + ruthenium ion + * @@ -11911,10 +11887,10 @@ 374 Metal coordination - PDBCC - SM - samarium (III) ion - + PDBCC + SM + samarium (III) ion + * @@ -11935,10 +11911,10 @@ 375 Metal coordination - PDBCC - SR - strontium ion - + PDBCC + SR + strontium ion + * @@ -11959,10 +11935,10 @@ 376 Metal coordination - PDBCC - TB - terbium (III) ion - + PDBCC + TB + terbium (III) ion + * @@ -11983,10 +11959,10 @@ 377 Metal coordination - PDBCC - TL - thallium (I) ion - + PDBCC + TL + thallium (I) ion + * @@ -12007,10 +11983,10 @@ 378 Metal coordination - PDBCC - U1 - uranium ion - + PDBCC + U1 + uranium ion + * @@ -12027,14 +12003,14 @@ undefined Metal coordination - + 379 Metal coordination - PDBCC - V - vanadium ion - + PDBCC + V + vanadium ion + * @@ -12055,10 +12031,10 @@ 380 Metal coordination - PDBCC - W - tungsten ion - + PDBCC + W + tungsten ion + * @@ -12079,10 +12055,10 @@ 381 Metal coordination - PDBCC - Y1 - yttrium ion - + PDBCC + Y1 + yttrium ion + * @@ -12099,14 +12075,14 @@ undefined Metal coordination - + 382 Metal coordination - PDBCC - YT3 - yttrium (III) ion - + PDBCC + YT3 + yttrium (III) ion + * @@ -12127,10 +12103,10 @@ 383 Metal coordination - PDBCC - YB - ytterbium ion - + PDBCC + YB + ytterbium ion + * @@ -12151,10 +12127,10 @@ 384 Metal coordination - PDBCC - YB2 - ytterbium (II) ion - + PDBCC + YB2 + ytterbium (II) ion + * @@ -12175,10 +12151,10 @@ 385 Metal coordination - PDBCC - ZN - zinc ion - + PDBCC + ZN + zinc ion + * @@ -12217,7 +12193,7 @@ ASN - + NDG @@ -12252,7 +12228,7 @@ ASN - + A2G @@ -12287,7 +12263,7 @@ ASN - + NGA @@ -12322,7 +12298,7 @@ ASN - + BGC @@ -12357,7 +12333,7 @@ ASN - + GLC @@ -12392,7 +12368,7 @@ ARG - + BGC @@ -12427,7 +12403,7 @@ ARG - + GLC @@ -12462,7 +12438,7 @@ CYS - + NAG @@ -12498,7 +12474,7 @@ CYS - + NDG @@ -12534,7 +12510,7 @@ CYS - + BGC @@ -12570,7 +12546,7 @@ CYS - + GLC @@ -12607,7 +12583,7 @@ CYS - + GLA @@ -12644,7 +12620,7 @@ CYS - + GAL @@ -12659,29 +12635,29 @@ thioether bond - 0399 - a protein modification that effectively forms a O3-(N-acetylaminoglucosyl)serine - (2S)-2-amino-3-(2-acetamido-2-deoxy-beta-D-glucopyranosyloxy)propanoic acid - - RESID - AA0398 - O-(N-acetylamino)glucosyl-L-serine - - - PDBCC - NDG - 2-(acetylamino)-2-deoxy-alpha-D-glucopyranose - - - PSI-MOD - MOD:00805 - O-(N-acetylaminoglucosyl)-L-serine - - + 0399 + a protein modification that effectively forms a O3-(N-acetylaminoglucosyl)serine + (2S)-2-amino-3-(2-acetamido-2-deoxy-beta-D-glucopyranosyloxy)propanoic acid + + RESID + AA0398 + O-(N-acetylamino)glucosyl-L-serine + + + PDBCC + NDG + 2-(acetylamino)-2-deoxy-alpha-D-glucopyranose + + + PSI-MOD + MOD:00805 + O-(N-acetylaminoglucosyl)-L-serine + + SER - + NDG @@ -12691,9 +12667,9 @@ attachment natural - glycoprotein - - + glycoprotein + + 0400 A protein modification that effectively converts an L-serine residue to O3-beta-glucosylated L-serine. (S)-2-amino-3-(beta-D-glucopyranosyloxy)propanoic acid @@ -12715,7 +12691,7 @@ SER - + BGC @@ -12750,7 +12726,7 @@ SER - + GLC @@ -12785,7 +12761,7 @@ SER - + GLA @@ -12820,7 +12796,7 @@ SER - + GAL @@ -12855,7 +12831,7 @@ SER - + FCA @@ -12890,7 +12866,7 @@ SER - + FCB @@ -13101,7 +13077,7 @@ THR - + NAG @@ -13136,7 +13112,7 @@ THR - + NDG @@ -13161,7 +13137,7 @@ THR - + BGC @@ -13186,7 +13162,7 @@ THR - + GLC @@ -13221,7 +13197,7 @@ THR - + GLA @@ -13256,7 +13232,7 @@ THR - + GAL @@ -13291,7 +13267,7 @@ THR - + FCA @@ -13326,7 +13302,7 @@ THR - + FCB @@ -13431,7 +13407,7 @@ TYR - + BGC @@ -13466,7 +13442,7 @@ TYR - + GLC @@ -13491,7 +13467,7 @@ TYR - + GAL @@ -13516,7 +13492,7 @@ TYR - + GAL @@ -13541,7 +13517,7 @@ TYR - + GLA @@ -13694,4 +13670,1009 @@ attachment glycoprotein + + 0430 + A protein modification that effectively converts an L-lysine residue to N6-pyridoxal phosphate-L-lysine. + (S)-2-amino-6-[([3-hydroxy-2-methyl-5-phosphonooxymethylpyridin-4-yl]methylidene)amino]hexanoic acid + + PDBCC + PLP + 2-lysine(3-hydroxy-2-methyl-5-phosphonooxymethyl-pyridin-4-ylmethane) + + + RESID + AA0119 + N6-pyridoxal phosphate-L-lysine + + + PSI-MOD + MOD:00128 + N6-pyridoxal phosphate-L-lysine + + + + PLP + + + LYS + + + C4A + NZ + + + natural + attachment + phosphoprotein + pyridoxal phosphate + + + 0431 + A protein modification that effectively crosslinks an L-alanine and an L-lysine residue to form a chromophore. + (2S)-2,8-DIAMINOOCTANOIC ACID + + PDBCC + HHK + (2S)-2,8-DIAMINOOCTANOIC ACID + + + + HHK + + + natural + modified residue + from RCSB PBD + chromoprotein + + + 0432 + A protein modification that effectively crosslinks an L-alanine, L-phenylalanine, and a glycine residue to form a chromophore. + {(2S)-2-[(1S)-1-AMINOETHYL]-5-OXO-2,5-DIHYDRO-1H-IMIDAZOL-1-YL}ACETIC ACID + + PDBCC + CLV + {(2S)-2-[(1S)-1-AMINOETHYL]-5-OXO-2,5-DIHYDRO-1H-IMIDAZOL-1-YL}ACETIC ACID + + + + CLV + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0433 + A protein modification that effectively crosslinks an L-alanine, L-phenylalanine, and a glycine residue to form a chromophore. + {(2S)-2-[(1S)-1-AMINOETHYL]-4-BENZYL-5-OXO-2,5-DIHYDRO-1H-IMIDAZOL-1-YL}ACETIC ACID + + PDBCC + X9Q + {(2S)-2-[(1S)-1-AMINOETHYL]-4-BENZYL-5-OXO-2,5-DIHYDRO-1H-IMIDAZOL-1-YL}ACETIC ACID + + + + X9Q + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0434 + A protein modification that effectively crosslinks an L-alanine, L-serine, and a glycine residue to form a chromophore. + 3,5-DIHYDRO-5-METHYLIDENE-4H-IMIDAZOL-4-ON + + PDBCC + 175 + 3,5-DIHYDRO-5-METHYLIDENE-4H-IMIDAZOL-4-ON + + + + 175 + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0435 + A protein modification that effectively crosslinks an L-alanine, L-serine, and a glycine residue to form a chromophore. + [2-(1-AMINOETHYL)-4-METHYLENE-5-OXO-4,5-DIHYDRO-1H-IMIDAZOL-1-YL]ACETIC ACID + + PDBCC + CRW + [2-(1-AMINOETHYL)-4-METHYLENE-5-OXO-4,5-DIHYDRO-1H-IMIDAZOL-1-YL]ACETIC ACID + + + + CRW + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0436 + A protein modification that effectively crosslinks an L-alanine, L-serine, and a glycine residue to form a chromophore. + [2-(1-AMINOETHYL)-2-HYDROXY-4-METHYLENE-5-OXOIMIDAZOLIDIN-1-YL]ACETIC ACID + + PDBCC + CRX + [2-(1-AMINOETHYL)-2-HYDROXY-4-METHYLENE-5-OXOIMIDAZOLIDIN-1-YL]ACETIC ACID + + + + CRX + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0437 + A protein modification that effectively crosslinks an L-alanine, L-serine, and a glycine residue to form a chromophore. + {2-[(1S)-1-aminoethyl]-4-methylidene-5-oxo-4,5-dihydro-1H-imidazol-1-yl}acetic acid + + PDBCC + MDO + {2-[(1S)-1-aminoethyl]-4-methylidene-5-oxo-4,5-dihydro-1H-imidazol-1-yl}acetic acid + + + + MDO + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0438 + A protein modification that effectively crosslinks an L-alanine, L-tyrosine, and a glycine residue to form a chromophore. + [(4E)-2-[(1S)-1-AMINOETHYL]-4-(4-HYDROXYBENZYLIDENE)-5-OXO-4,5-DIHYDRO-1H-IMIDAZOL-1-YL]ACETIC ACID + + PDBCC + AYG + [(4E)-2-[(1S)-1-AMINOETHYL]-4-(4-HYDROXYBENZYLIDENE)-5-OXO-4,5-DIHYDRO-1H-IMIDAZOL-1-YL]ACETIC ACID + + + + AYG + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0439 + A protein modification that effectively crosslinks an L-alanine, L-tyrosine, and a glycine residue to form a chromophore. + [(4Z)-2-[(1S)-1-aminoethyl]-4-(4-hydroxybenzylidene)-5-oxo-4,5-dihydro-1H-imidazol-1-yl]acetic acid + + PDBCC + PIA + [(4Z)-2-[(1S)-1-aminoethyl]-4-(4-hydroxybenzylidene)-5-oxo-4,5-dihydro-1H-imidazol-1-yl]acetic acid + + + + PIA + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0441 + A protein modification that effectively crosslinks an L-aspartic acid and an L-cysteine residue to form a chromophore. + (2R)-2-[(3S)-3-amino-2,5-dioxopyrrolidin-1-yl]-3-sulfanylpropanoic acid + + PDBCC + SIC + (2R)-2-[(3S)-3-amino-2,5-dioxopyrrolidin-1-yl]-3-sulfanylpropanoic acid + + + + SIC + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0442 + A protein modification that effectively crosslinks an L-aspartic acid and a glycine residue to form a chromophore. + (3-AMINO-2,5-DIOXO-1-PYRROLIDINYL)ACETIC ACID + + PDBCC + SUI + (3-AMINO-2,5-DIOXO-1-PYRROLIDINYL)ACETIC ACID + + + + SUI + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0443 + A protein modification that effectively crosslinks an L-aspartic acid, L-tyrosine, and a glycine residue to form a chromophore. + (3S)-3-amino-3-[(4Z)-1-(carboxymethyl)-4-[(4-hydroxyphenyl)methylidene]-5-oxo-imidazol-2-yl]propanoic acid + + PDBCC + DYG + (3S)-3-amino-3-[(4Z)-1-(carboxymethyl)-4-[(4-hydroxyphenyl)methylidene]-5-oxo-imidazol-2-yl]propanoic acid + + + + DYG + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0445 + A protein modification that effectively crosslinks an L-cysteine, L-tyrosine, and a glycine residue to form a chromophore. + 2-(1-AMINO-2-MERCAPTO-ETHYL)-5-(4-HYDROXY-BENZYL)-3-(ETHANOYL)-3,5-DIHYDRO-IMIDAZOL-4-ONE + + PDBCC + CCY + 2-(1-AMINO-2-MERCAPTO-ETHYL)-5-(4-HYDROXY-BENZYL)-3-(ETHANOYL)-3,5-DIHYDRO-IMIDAZOL-4-ONE + + + + CCY + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0446 + A protein modification that effectively crosslinks an L-cysteine, L-tyrosine, and a glycine residue to form a chromophore. + [(4Z)-2-[(1R)-1-AMINO-2-MERCAPTOETHYL]-4-(4-HYDROXYBENZYLIDENE)-5-OXO-4,5-DIHYDRO-1H-IMIDAZOL-1-YL]ACETIC ACID + + PDBCC + GYC + [(4Z)-2-[(1R)-1-AMINO-2-MERCAPTOETHYL]-4-(4-HYDROXYBENZYLIDENE)-5-OXO-4,5-DIHYDRO-1H-IMIDAZOL-1-YL]ACETIC ACID + + + + GYC + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0447 + A protein modification that effectively crosslinks an L-glutamine, L-leucine, and a glycine residue to form a chromophore. + [(4Z)-2-[(1Z)-4-AMINO-4-OXOBUTANIMIDOYL]-4-(2-METHYLPROPYLIDENE)-5-OXO-4,5-DIHYDRO-1H-IMIDAZOL-1-YL]ACETIC ACID + + PDBCC + QLG + [(4Z)-2-[(1Z)-4-AMINO-4-OXOBUTANIMIDOYL]-4-(2-METHYLPROPYLIDENE)-5-OXO-4,5-DIHYDRO-1H-IMIDAZOL-1-YL]ACETIC ACID + + + + QLG + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0449 + A protein modification that effectively crosslinks an L-glutamine, L-phenylalanine, and a glycine residue to form a chromophore. + {(4E)-2-[(1E)-4-amino-4-oxobutanimidoyl]-4-benzylidene-5-oxo-4,5-dihydro-1H-imidazol-1-yl}acetic acid + + PDBCC + QFG + {(4E)-2-[(1E)-4-amino-4-oxobutanimidoyl]-4-benzylidene-5-oxo-4,5-dihydro-1H-imidazol-1-yl}acetic acid + + + + QFG + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0450 + A protein modification that effectively crosslinks a glycine, L-tyrosine, and a glycine residue to form a chromophore. + [2-(1-AMINO-2-HYDROXY-PROPYL)-4-(4-FLUORO-1H-INDOL-3-YLMETHYL)-5-HYDROXY-IMIDAZOL-1-YL]-ACETIC ACID + + PDBCC + 4F3 + [2-(1-AMINO-2-HYDROXY-PROPYL)-4-(4-FLUORO-1H-INDOL-3-YLMETHYL)-5-HYDROXY-IMIDAZOL-1-YL]-ACETIC ACID + + + + 4F3 + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0451 + A protein modification that effectively crosslinks a glycine, L-tyrosine, and a glycine residue to form a chromophore. + [(2R,4R)-2-[(1R,2R)-1-amino-2-hydroxypropyl]-4-(4-hydroxybenzyl)-5-oxoimidazolidin-1-yl]acetic acid + + PDBCC + CJO + [(2R,4R)-2-[(1R,2R)-1-amino-2-hydroxypropyl]-4-(4-hydroxybenzyl)-5-oxoimidazolidin-1-yl]acetic acid + + + + CJO + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0452 + A protein modification that effectively crosslinks a glycine, L-tyrosine, and a glycine residue to form a chromophore. + {(4Z)-4-(4-aminobenzylidene)-2-[(1R,2R)-1-amino-2-hydroxypropyl]-5-oxo-4,5-dihydro-1H-imidazol-1-yl}acetic acid + + PDBCC + CQ2 + {(4Z)-4-(4-aminobenzylidene)-2-[(1R,2R)-1-amino-2-hydroxypropyl]-5-oxo-4,5-dihydro-1H-imidazol-1-yl}acetic acid + + + + CQ2 + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0453 + A protein modification that effectively crosslinks a glycine, L-tyrosine, and a glycine residue to form a chromophore. + [(4Z)-2-(AMINOMETHYL)-4-(4-HYDROXYBENZYLIDENE)-5-OXO-4,5-DIHYDRO-1H-IMIDAZOL-1-YL]ACETIC ACID + + PDBCC + CQR + [(4Z)-2-(AMINOMETHYL)-4-(4-HYDROXYBENZYLIDENE)-5-OXO-4,5-DIHYDRO-1H-IMIDAZOL-1-YL]ACETIC ACID + + + + CQR + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0454 + A protein modification that effectively crosslinks a glycine, L-tyrosine, and a glycine residue to form a chromophore. + {(4Z)-2-(aminomethyl)-4-[(4-hydroxyphenyl)methylidene]-5-oxo-4,5-dihydro-1H-imidazol-1-yl}acetic acid + + PDBCC + CR2 + {(4Z)-2-(aminomethyl)-4-[(4-hydroxyphenyl)methylidene]-5-oxo-4,5-dihydro-1H-imidazol-1-yl}acetic acid + + + + CR2 + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0455 + A protein modification that effectively crosslinks a glycine, L-tyrosine, and a glycine residue to form a chromophore. + [(2R,4S)-2-[(1S,2R)-1-amino-2-hydroxypropyl]-2-hydroxy-4-(4-hydroxybenzyl)-5-oxoimidazolidin-1-yl]acetic acid + + PDBCC + CZO + [(2R,4S)-2-[(1S,2R)-1-amino-2-hydroxypropyl]-2-hydroxy-4-(4-hydroxybenzyl)-5-oxoimidazolidin-1-yl]acetic acid + + + + CZO + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0456 + A protein modification that effectively crosslinks a glycine, L-tyrosine, and a glycine residue to form a chromophore. + 5-[1-(3-FLUORO-4-HYDROXY-PHENYL)-METH-(Z)-YLIDENE]-3,5-DIHYDRO-IMIDAZOL-4-ONE + + PDBCC + MFC + 5-[1-(3-FLUORO-4-HYDROXY-PHENYL)-METH-(Z)-YLIDENE]-3,5-DIHYDRO-IMIDAZOL-4-ONE + + + + MFC + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0457 + A protein modification that effectively crosslinks a glycine, L-tyrosine, and a glycine residue to form a chromophore. + [(2R,4Z)-2-(aminomethyl)-2-hydroxy-4-(4-hydroxybenzylidene)-5-oxoimidazolidin-1-yl]acetic acid + + PDBCC + WCR + [(2R,4Z)-2-(aminomethyl)-2-hydroxy-4-(4-hydroxybenzylidene)-5-oxoimidazolidin-1-yl]acetic acid + + + + WCR + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0458 + A protein modification that effectively crosslinks an L-histidine, L-tyrosine, and a glycine residue to form a chromophore. + 2-[1-AMINO-2-(1H-IMIDAZOL-5-YL)ETHYL]-1-(CARBOXYMETHYL)-4-[(4-OXOCYCLOHEXA-2,5-DIEN-1-YLIDENE)METHYL]-1H-IMIDAZOL-5-OLATE + + PDBCC + CR8 + 2-[1-AMINO-2-(1H-IMIDAZOL-5-YL)ETHYL]-1-(CARBOXYMETHYL)-4-[(4-OXOCYCLOHEXA-2,5-DIEN-1-YLIDENE)METHYL]-1H-IMIDAZOL-5-OLATE + + + + CR8 + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0459 + A protein modification that effectively crosslinks an L-histidine, L-tyrosine, and a glycine residue to form a chromophore. + 2-((1E)-2-(5-IMIDAZOLYL)ETHENYL)-4-(P-HYDROXYBENZYLIDENE)-5-IMIDAZOLINONE + + PDBCC + IEY + 2-((1E)-2-(5-IMIDAZOLYL)ETHENYL)-4-(P-HYDROXYBENZYLIDENE)-5-IMIDAZOLINONE + + + + IEY + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0460 + A protein modification that effectively crosslinks an L-histidine, L-tyrosine, and a glycine residue to form a chromophore. + {(2R)-4-(4-HYDROXYBENZYL)-2-[2-(1H-IMIDAZOL-4-YL)ETHYL]-5-OXO-2,5-DIHYDRO-1H-IMIDAZOL-1-YL}ACETALDEHYDE + + PDBCC + RC7 + {(2R)-4-(4-HYDROXYBENZYL)-2-[2-(1H-IMIDAZOL-4-YL)ETHYL]-5-OXO-2,5-DIHYDRO-1H-IMIDAZOL-1-YL}ACETALDEHYDE + + + + RC7 + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0461 + A protein modification that effectively crosslinks an L-isoleucine, glycine, L-tyrosine, and a glycine residue to form a chromophore. + [(4Z)-2-{(2R,5R)-2-[(1S,2S)-1-amino-2-methylbutyl]-2-hydroxy-5-methyl-2,5-dihydro-1,3-oxazol-4-yl}-4-(4-hydroxybenzylidene)-5-oxo-4,5-dihydro-1H-imidazol-1-yl]acetic acid + + PDBCC + OIM + [(4Z)-2-{(2R,5R)-2-[(1S,2S)-1-amino-2-methylbutyl]-2-hydroxy-5-methyl-2,5-dihydro-1,3-oxazol-4-yl}-4-(4-hydroxybenzylidene)-5-oxo-4,5-dihydro-1H-imidazol-1-yl]acetic acid + + + + OIM + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0462 + A protein modification that effectively crosslinks an L-leucine, L-tyrosine, and a glycine residue to form a chromophore. + {4-[(4-hydroxyphenyl)methylidene]-2-[(1E)-3-methylbutanimidoyl]-5-oxo-4,5-dihydro-1H-imidazol-1-yl}acetic acid + + PDBCC + NRP + {4-[(4-hydroxyphenyl)methylidene]-2-[(1E)-3-methylbutanimidoyl]-5-oxo-4,5-dihydro-1H-imidazol-1-yl}acetic acid + + + + NRP + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0463 + A protein modification that effectively crosslinks an L-methionine, L-tyrosine, and a glycine residue to form a chromophore. + 4-{(Z)-[2-[3-(METHYLSULFANYL)PROPANOYL]-5-OXO-1-(2-OXOETHYL)-1,5-DIHYDRO-4H-IMIDAZOL-4-YLIDENE]METHYL}BENZENOLATE + + PDBCC + CRK + 4-{(Z)-[2-[3-(METHYLSULFANYL)PROPANOYL]-5-OXO-1-(2-OXOETHYL)-1,5-DIHYDRO-4H-IMIDAZOL-4-YLIDENE]METHYL}BENZENOLATE + + + + CRK + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0464 + A protein modification that effectively crosslinks an L-methionine, L-tyrosine, and a glycine residue to form a chromophore. + {(2R,4Z)-2-[(1R)-1-amino-3-(methylsulfanyl)propyl]-2-hydroxy-4-[(4-hydroxyphenyl)methylidene]-5-oxoimidazolidin-1-yl}acetic acid + + PDBCC + EYG + {(2R,4Z)-2-[(1R)-1-amino-3-(methylsulfanyl)propyl]-2-hydroxy-4-[(4-hydroxyphenyl)methylidene]-5-oxoimidazolidin-1-yl}acetic acid + + + + EYG + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0465 + A protein modification that effectively crosslinks an L-phenylalanine, L-cysteine, L-tyrosine, and a glycine residue to form a chromophore. + [(4Z)-2-{(2R)-2-[(1S)-1-amino-2-phenylethyl]-2-hydroxy-2,5-dihydro-1,3-thiazol-4-yl}-4-(4-hydroxybenzylidene)-5-oxo-4,5-dihydro-1H-imidazol-1-yl]acetic acid + + PDBCC + CFY + [(4Z)-2-{(2R)-2-[(1S)-1-amino-2-phenylethyl]-2-hydroxy-2,5-dihydro-1,3-thiazol-4-yl}-4-(4-hydroxybenzylidene)-5-oxo-4,5-dihydro-1H-imidazol-1-yl]acetic acid + + + + CFY + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0466 + A protein modification that effectively crosslinks an L-phenylalanine, glycine, L-tyrosine, and a glycine residue to form a chromophore. + [(4Z)-2-{(2R,5R)-2-[(1S)-1-amino-2-phenylethyl]-2-hydroxy-5-methyl-2,5-dihydro-1,3-oxazol-4-yl}-4-(4-hydroxybenzylidene)-5-oxo-4,5-dihydro-1H-imidazol-1-yl]acetic acid + + PDBCC + OFM + [(4Z)-2-{(2R,5R)-2-[(1S)-1-amino-2-phenylethyl]-2-hydroxy-5-methyl-2,5-dihydro-1,3-oxazol-4-yl}-4-(4-hydroxybenzylidene)-5-oxo-4,5-dihydro-1H-imidazol-1-yl]acetic acid + + + + OFM + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0467 + A protein modification that effectively crosslinks an L-serine, L-histidine, and a glycine residue to form a chromophore. + [2-(2-HYDROXY-1-METHYL-ETHYL)-4-(1H-IMIDAZOL-4-YLMETHYL)-5-OXO-IMIDAZOLIDIN-1-YL]-ACETIC ACID + + PDBCC + CSH + [2-(2-HYDROXY-1-METHYL-ETHYL)-4-(1H-IMIDAZOL-4-YLMETHYL)-5-OXO-IMIDAZOLIDIN-1-YL]-ACETIC ACID + + + + CSH + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0468 + A protein modification that effectively crosslinks an L-serine, L-histidine, and a glycine residue to form a chromophore. + 4-IMIDAZOLMETHYLENE-5-IMIDAZOLONE CHROMOPHORE + + PDBCC + IIC + 4-IMIDAZOLMETHYLENE-5-IMIDAZOLONE CHROMOPHORE + + + + IIC + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0469 + A protein modification that effectively crosslinks an L-serine, L-tryptophane, and a glycine residue to form a chromophore. + 2-[(4Z)-2-[(1R)-1-amino-2-hydroxy-ethyl]-4-(1H-indol-3-ylmethylidene)-5-oxo-imidazol-1-yl]ethanoic acid + + PDBCC + SWG + 2-[(4Z)-2-[(1R)-1-amino-2-hydroxy-ethyl]-4-(1H-indol-3-ylmethylidene)-5-oxo-imidazol-1-yl]ethanoic acid + + + + SWG + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0470 + A protein modification that effectively crosslinks an L-serine, L-tyrosine, and a glycine residue to form a chromophore. + [(4Z)-2-[(1R)-1-amino-2-hydroxyethyl]-4-(4-hydroxybenzylidene)-5-oxo-4,5-dihydro-1H-imidazol-1-yl]acetic acid + + PDBCC + CSY + [(4Z)-2-[(1R)-1-amino-2-hydroxyethyl]-4-(4-hydroxybenzylidene)-5-oxo-4,5-dihydro-1H-imidazol-1-yl]acetic acid + + + + CSY + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0471 + A protein modification that effectively crosslinks an L-serine, L-tyrosine, and a glycine residue to form a chromophore. + [(4Z)-2-(1-AMINO-2-HYDROXYETHYL)-4-(4-HYDROXYBENZYLIDENE)-5-OXO-4,5-DIHYDRO-1H-IMIDAZOL-1-YL]ACETIC ACID + + PDBCC + GYS + [(4Z)-2-(1-AMINO-2-HYDROXYETHYL)-4-(4-HYDROXYBENZYLIDENE)-5-OXO-4,5-DIHYDRO-1H-IMIDAZOL-1-YL]ACETIC ACID + + + + GYS + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0472 + A protein modification that effectively crosslinks an L-threonine, L-histidine, and a glycine residue to form a chromophore. + [2-(1-AMINO-2-HYDROXY-PROPYL)-4-(3H-IMIDAZOL-4-YLMETHYLENE)-5-OXO-4,5-DIHYDRO-IMIDAZOL-1-YL]-ACETIC ACID + + PDBCC + CRG + [2-(1-AMINO-2-HYDROXY-PROPYL)-4-(3H-IMIDAZOL-4-YLMETHYLENE)-5-OXO-4,5-DIHYDRO-IMIDAZOL-1-YL]-ACETIC ACID + + + + CRG + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0473 + A protein modification that effectively crosslinks an L-threonine, L-histidine, and a glycine residue to form a chromophore. + 2-[(1R,2R)-1-amino-2-hydroxypropyl]-1-(carboxymethyl)-4-(1H-imidazol-5-ylmethyl)-1H-imidazol-5-olate + + PDBCC + XXY + 2-[(1R,2R)-1-amino-2-hydroxypropyl]-1-(carboxymethyl)-4-(1H-imidazol-5-ylmethyl)-1H-imidazol-5-olate + + + + XXY + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0474 + A protein modification that effectively crosslinks an L-threonine, L-leucine, and a glycine residue to form a chromophore. + [2-(1-AMINO-2-HYDROXYPROPYL)-2-HYDROXY-4-ISOBUTYL-5-OXO-2,5-DIHYDRO-1H-IMIDAZOL-1-YL]ACETALDEHYDE + + PDBCC + CR0 + 2[2-(1-AMINO-2-HYDROXYPROPYL)-2-HYDROXY-4-ISOBUTYL-5-OXO-2,5-DIHYDRO-1H-IMIDAZOL-1-YL]ACETALDEHYDE + + + + CR0 + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0475 + A protein modification that effectively crosslinks an L-threonine, L-phenylalanine, and a glycine residue to form a chromophore. + {(2R)-2-[(1S,2R)-1-AMINO-2-HYDROXYPROPYL]-2-HYDROXY-4,5-DIOXOIMIDAZOLIDIN-1-YL}ACETIC ACID + + PDBCC + C99 + {(2R)-2-[(1S,2R)-1-AMINO-2-HYDROXYPROPYL]-2-HYDROXY-4,5-DIOXOIMIDAZOLIDIN-1-YL}ACETIC ACID + + + + C99 + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0476 + A protein modification that effectively crosslinks an L-threonine, L-serine, and a glycine residue to form a chromophore. + {2-[(1R,2R)-1-amino-2-hydroxypropyl]-4-methylidene-5-oxo-4,5-dihydro-1H-imidazol-1-yl}acetic acid + + PDBCC + KWS + {2-[(1R,2R)-1-amino-2-hydroxypropyl]-4-methylidene-5-oxo-4,5-dihydro-1H-imidazol-1-yl}acetic acid + + + + KWS + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0477 + A protein modification that effectively crosslinks an L-threonine, L-tryptophane, and a glycine residue to form a chromophore. + (5Z)-2-[(1S,2R)-1-AMINO-2-HYDROXYPROPYL]-5-[(4-AMINO-1H-INDOL-3-YL)METHYLENE]-3-(2-HYDROXYETHYL)-3,5-DIHYDRO-4H-IMIDAZOL-4-ONE + + PDBCC + 5ZA + (5Z)-2-[(1S,2R)-1-AMINO-2-HYDROXYPROPYL]-5-[(4-AMINO-1H-INDOL-3-YL)METHYLENE]-3-(2-HYDROXYETHYL)-3,5-DIHYDRO-4H-IMIDAZOL-4-ONE + + + + 5ZA + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0478 + A protein modification that effectively crosslinks an L-threonine, L-tryptophane, and a glycine residue to form a chromophore. + [(4Z)-2-[(1R,2R)-1-amino-2-hydroxypropyl]-4-(1H-indol-3-ylmethylidene)-5-oxo-4,5-dihydro-1H-imidazol-1-yl]acetic acid + + PDBCC + CRF + [(4Z)-2-[(1R,2R)-1-amino-2-hydroxypropyl]-4-(1H-indol-3-ylmethylidene)-5-oxo-4,5-dihydro-1H-imidazol-1-yl]acetic acid + + + + CRF + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0479 + A protein modification that effectively crosslinks an L-threonine, L-tryptophane, and a glycine residue to form a chromophore. + [(4E)-2-[(1R,2S)-1-AMINO-2-HYDROXYPROPYL]-4-(1H-INDOL-3-YLMETHYLENE)-5-OXO-4,5-DIHYDRO-1H-IMIDAZOL-1-YL]ACETIC ACID + + PDBCC + NYC + [(4E)-2-[(1R,2S)-1-AMINO-2-HYDROXYPROPYL]-4-(1H-INDOL-3-YLMETHYLENE)-5-OXO-4,5-DIHYDRO-1H-IMIDAZOL-1-YL]ACETIC ACID + + + + NYC + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0480 + A protein modification that effectively crosslinks an L-threonine, L-tyrosine, and a glycine residue to form a chromophore. + [(4Z)-2-[(1R,2R)-1-amino-2-hydroxypropyl]-4-(3-chloro-4-hydroxybenzylidene)-5-oxo-4,5-dihydro-1H-imidazol-1-yl]acetic acid + + PDBCC + 4NT + [(4Z)-2-[(1R,2R)-1-amino-2-hydroxypropyl]-4-(3-chloro-4-hydroxybenzylidene)-5-oxo-4,5-dihydro-1H-imidazol-1-yl]acetic acid + + + + 4NT + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0481 + A protein modification that effectively crosslinks an L-threonine, L-tyrosine, and a glycine residue to form a chromophore. + {(4Z)-2-[(1R,2R)-1-amino-2-hydroxypropyl]-4-[(3,5-dichloro-4-oxocyclohexa-2,5-dien-1-yl)methylidene]-5-oxo-4,5-dihydro-1H-imidazol-1-yl}acetic acid + + PDBCC + 4NU + {(4Z)-2-[(1R,2R)-1-amino-2-hydroxypropyl]-4-[(3,5-dichloro-4-oxocyclohexa-2,5-dien-1-yl)methylidene]-5-oxo-4,5-dihydro-1H-imidazol-1-yl}acetic acid + + + + 4NU + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0482 + A protein modification that effectively crosslinks an L-threonine, L-tyrosine, and a glycine residue to form a chromophore. + 2-(1-AMINO-2-HYDROXYPROPYL)-4-(4-HYDROXYBENZYL)-1-(2-OXOETHYL)-1H-IMIDAZOL-5-OLATE + + PDBCC + C12 + 2-(1-AMINO-2-HYDROXYPROPYL)-4-(4-HYDROXYBENZYL)-1-(2-OXOETHYL)-1H-IMIDAZOL-5-OLATE + + + + C12 + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0483 + A protein modification that effectively crosslinks an L-threonine, L-tyrosine, and a glycine residue to form a chromophore. + [(4Z)-2-[(1R,2R)-1-amino-2-hydroxypropyl]-4-(4-azidobenzylidene)-5-oxo-4,5-dihydro-1H-imidazol-1-yl]acetic acid + + PDBCC + CQ1 + [(4Z)-2-[(1R,2R)-1-amino-2-hydroxypropyl]-4-(4-azidobenzylidene)-5-oxo-4,5-dihydro-1H-imidazol-1-yl]acetic acid + + + + CQ1 + + + natural + modified residue + from RCSB PDB + chromoprotein + + + 0484 + A protein modification that effectively crosslinks an L-tyrosine and a glycine residue to form a chromophore. + N-[(2Z)-2-amino-3-(4-hydroxyphenyl)prop-2-enoyl]glycine + + PDBCC + 0YG + N-[(2Z)-2-amino-3-(4-hydroxyphenyl)prop-2-enoyl]glycine + + + + 0YG + + + natural + modified residue + from RCSB PDB + chromoprotein + \ No newline at end of file diff --git a/biojava-modfinder/src/test/java/org/biojava/nbio/protmod/structure/ModifiedCompoundSerializationTest.java b/biojava-modfinder/src/test/java/org/biojava/nbio/protmod/structure/ModifiedCompoundSerializationTest.java index bce30704ba..024bbc855a 100644 --- a/biojava-modfinder/src/test/java/org/biojava/nbio/protmod/structure/ModifiedCompoundSerializationTest.java +++ b/biojava-modfinder/src/test/java/org/biojava/nbio/protmod/structure/ModifiedCompoundSerializationTest.java @@ -164,6 +164,7 @@ public List testXMLSerialization(String pdbId){ } } } catch (Exception e){ + logger.error(e.getMessage(),e); logger.error("Error when serializing {}", pdbId); logger.error(currentMC.getDescription()); logger.error(xml, e); diff --git a/biojava-modfinder/src/test/java/org/biojava/nbio/protmod/structure/ProteinModificationParserTest.java b/biojava-modfinder/src/test/java/org/biojava/nbio/protmod/structure/ProteinModificationParserTest.java index 37bd8ec18c..d071a761f7 100644 --- a/biojava-modfinder/src/test/java/org/biojava/nbio/protmod/structure/ProteinModificationParserTest.java +++ b/biojava-modfinder/src/test/java/org/biojava/nbio/protmod/structure/ProteinModificationParserTest.java @@ -19,6 +19,7 @@ * * Created on Jun 8, 2010 * Author: Jianjiong Gao + * Author: Peter W. Rose * */ @@ -27,9 +28,7 @@ import junit.framework.TestCase; import org.biojava.nbio.protmod.ProteinModification; import org.biojava.nbio.protmod.ProteinModificationRegistry; -import org.biojava.nbio.structure.ResidueNumber; -import org.biojava.nbio.structure.Structure; -import org.biojava.nbio.structure.StructureException; +import org.biojava.nbio.structure.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -64,10 +63,12 @@ public static String[][] setUpShortTest() { // {"1ZNF", "AA0053"}, // ACE on THR {"1MCC", "AA0045"}, // ACE on GLU {"1SCY", "AA0089"}, // NH2 on HIS + {"5HNE", "AA0119"}, // PLP on LYS // Modified resdiues {"1UIS", "AA0183"}, // NRQ {"3MVJ", "AA0037"}, // SEP + {"5EUN", "AA0119"}, // LLP // remediation changed 1DOJ... //{"1DOJ", "AA0065"}, // MEA @@ -88,6 +89,33 @@ public static String[][] setUpShortTest() { {"3H8L", "AA0513"}, // CYS-S3H-CYS {"1CAD", null}, // FE and 4 Cys, cross-link4 + // Terbium cases + {"1NCZ", null}, + {"3LTQ",null}, // has metalc, + {"4ESQ",null}, + {"1TJB",null}, + {"2V15",null}, + {"2K61",null}, + + // iron bond to CYS + //{"1G20","AA0300"}, + + {"3CM6",null}, + {"1W6Z",null}, + //{"1Z2M",null}, distances are too big for the new cutoffs + {"2O6N",null}, + {"1GA7",null}, + {"1ACD","AA0262"}, // test for CSD + {"1AA6","AA0022"} , // test for SEC + + {"1WCT","AA0179"}, + {"2VH3","AA0459"}, + + // Chromophores + {"2HGD",null}, // X9Q + {"3LF4",null}, // 0YG + + }; return strucs; } @@ -109,7 +137,7 @@ public static String[][] setUpLongTest() { {"1EL5", "AA0143"}, // FAD on CYS {"1W1O", "AA0144"}, // FAD on HIS {"1DII", "AA0145"}, // FAD on TYR - {"2KJS", "AA0150"}, // PNS + {"2LML", "AA0150"}, // PNS {"1D7E", "AA0207"}, // HC4 {"2TMD", "AA0220"}, // FMN {"1VAO", "AA0221"}, // FAD on HIS @@ -157,7 +185,7 @@ public static String[][] setUpLongTest() { {"1DM3", "AA0056"}, // SCY // {"2NPP", "AA0061"}, // MAA {"1GK8", "AA0064"}, // MME - {"1DOJ", "AA0065"}, // MEA + {"2PIL", "AA0065"}, // MEA {"1DOJ", "AA0172"}, // TYS {"1G42", "AA0067"}, // 2MR {"2B2U", "AA0068"}, // DA2 @@ -210,7 +238,7 @@ public static String[][] setUpLongTest() { {"1HBM", "AA0273"}, // MGN {"1FFU", "AA0277"}, // CSZ {"3H5R", "AA0302"}, // SNN, note: SNN is not at C-terminal in some structures, e.g. 3I4W - {"1JQ7", "AA0311"}, // DMH + {"1NKK", "AA0311"}, // DMH {"1J6Z", "AA0317"}, // HIC {"1B80", "AA0322"}, // HTR {"1CWM", "AA0336"}, // IML @@ -224,7 +252,6 @@ public static String[][] setUpLongTest() { {"2IUW", "AA0444"}, // LED {"1K83", "AA0449"}, // ILX {"2VH3", "AA0458"}, // FGL - {"2AOC", "AA0464"}, // OLT {"1DSR", "AA0478"}, // AHB {"1AIQ", "AA0493"}, // CXM {"1CF0", "AA0509"}, // IYR @@ -283,6 +310,21 @@ public static String[][] setUpLongTest() { {"3EE4", "AA0490"}, // VAL-TYR {"3H8L", "AA0513"}, // CYS-S3H-CYS {"1CAD", null}, // FE and 4 Cys, cross-link4 + + // Terbium + {"1NCZ", null}, + {"3LTQ",null}, + {"4ESQ",null}, + {"1TJB",null}, + {"2V15",null}, + {"2K61",null}, + + + // Chromophores + {"2HGD",null}, // X9Q + {"3LF4",null}, // 0YG + + }; return strucs; } @@ -291,15 +333,11 @@ public void testParser() throws IOException, StructureException { multiTest(); } - public void multiTest() { + public void multiTest() throws IOException, StructureException { for ( String[] name : strucs){ - try { -// parserTest(name[0], (String)null); - parserTest(name[0], name[1]); - } catch (Exception e){ - logger.error("Exception: ", e); - fail(e.getMessage()); - } + parserTest(name[0], (String)null); + parserTest(name[0], name[1]); + } } @@ -316,18 +354,39 @@ private void parserTest(String pdbId, String residId) throws IOException, Struct private void parserTest(String pdbId, Set mods) throws IOException, StructureException { Structure struc = TmpAtomCache.cache.getStructure(pdbId); +/* + //needed for testing 1G20 + if ( pdbId.equalsIgnoreCase("1G20")) { + Structure n = new StructureImpl(); + + n.addChain(struc.getPolyChainByPDB("A")); + n.addChain(struc.getPolyChainByPDB("B")); + for (Chain c : struc.getNonPolyChainsByPDB("A")) + n.addChain(c); + + for (Chain c : struc.getNonPolyChainsByPDB("B")) + n.addChain(c); + + + struc = n; + } + */ ProteinModificationIdentifier parser = new ProteinModificationIdentifier(); boolean recordUnidentifiable = false; parser.setRecordUnidentifiableCompounds(recordUnidentifiable); -// parser.setbondLengthTolerance(2); + //parser.setbondLengthTolerance(2); assertFalse(mods.isEmpty()); parser.identify(struc, mods); - if (! parser.getIdentifiedModifiedCompound().isEmpty() ){ - logger.warn("Did not identify any modified compounds for {}", pdbId); + //System.out.println(parser.getUnidentifiableModifiedResidues()); + + if ( parser.getIdentifiedModifiedCompound().isEmpty() ){ + String msg = "Did not identify any modified compounds for " + pdbId; + logger.warn(msg); + fail(msg); } assertFalse("Did not identify any modified compounds for " + pdbId , @@ -352,7 +411,7 @@ private void printResult(String pdbId, ProteinModificationIdentifier parser, boo sb.append("Modification #"); sb.append(++i); sb.append(":\n"); - sb.append(mc); + sb.append(mc.getAtomLinkages()); sb.append('\n'); } diff --git a/biojava-modfinder/src/test/java/org/biojava/nbio/protmod/structure/TmpAtomCache.java b/biojava-modfinder/src/test/java/org/biojava/nbio/protmod/structure/TmpAtomCache.java index 211c5b3ec8..8d757a74a8 100644 --- a/biojava-modfinder/src/test/java/org/biojava/nbio/protmod/structure/TmpAtomCache.java +++ b/biojava-modfinder/src/test/java/org/biojava/nbio/protmod/structure/TmpAtomCache.java @@ -36,6 +36,7 @@ public class TmpAtomCache FileParsingParameters params = new FileParsingParameters(); params.setAlignSeqRes(true); params.setParseSecStruc(false); + params.setCreateAtomBonds(true); cache.setFetchBehavior(FetchBehavior.FETCH_REMEDIATED); cache.setFileParsingParams(params); } diff --git a/biojava-ontology/pom.xml b/biojava-ontology/pom.xml index d6558f3875..84879a63eb 100644 --- a/biojava-ontology/pom.xml +++ b/biojava-ontology/pom.xml @@ -4,7 +4,7 @@ org.biojava biojava - 4.2.1 + 4.2.2 biojava-ontology diff --git a/biojava-phylo/pom.xml b/biojava-phylo/pom.xml index 650a14d4f6..4ed6efe7f7 100644 --- a/biojava-phylo/pom.xml +++ b/biojava-phylo/pom.xml @@ -3,7 +3,7 @@ biojava org.biojava - 4.2.1 + 4.2.2 4.0.0 biojava-phylo @@ -44,7 +44,7 @@ org.biojava biojava-core - 4.2.1 + 4.2.2 compile diff --git a/biojava-protein-disorder/pom.xml b/biojava-protein-disorder/pom.xml index 5a1283acba..f8fe1d4bae 100644 --- a/biojava-protein-disorder/pom.xml +++ b/biojava-protein-disorder/pom.xml @@ -3,7 +3,7 @@ biojava org.biojava - 4.2.1 + 4.2.2 biojava-protein-disorder jar @@ -63,7 +63,7 @@ org.biojava biojava-core - 4.2.1 + 4.2.2 diff --git a/biojava-sequencing/pom.xml b/biojava-sequencing/pom.xml index 16f7b04040..99eaee0097 100644 --- a/biojava-sequencing/pom.xml +++ b/biojava-sequencing/pom.xml @@ -3,7 +3,7 @@ biojava org.biojava - 4.2.1 + 4.2.2 4.0.0 biojava-sequencing @@ -47,7 +47,7 @@ org.biojava biojava-core - 4.2.1 + 4.2.2 compile diff --git a/biojava-structure-gui/pom.xml b/biojava-structure-gui/pom.xml index cb01913352..e6c6de96e1 100644 --- a/biojava-structure-gui/pom.xml +++ b/biojava-structure-gui/pom.xml @@ -3,7 +3,7 @@ biojava org.biojava - 4.2.1 + 4.2.2 4.0.0 biojava-structure-gui @@ -25,13 +25,13 @@ org.biojava biojava-structure - 4.2.1 + 4.2.2 compile org.biojava biojava-core - 4.2.1 + 4.2.2 compile diff --git a/biojava-structure-gui/src/main/java/org/biojava/nbio/structure/align/gui/jmol/MultipleAlignmentJmol.java b/biojava-structure-gui/src/main/java/org/biojava/nbio/structure/align/gui/jmol/MultipleAlignmentJmol.java index 114e3c377d..949f17afb8 100644 --- a/biojava-structure-gui/src/main/java/org/biojava/nbio/structure/align/gui/jmol/MultipleAlignmentJmol.java +++ b/biojava-structure-gui/src/main/java/org/biojava/nbio/structure/align/gui/jmol/MultipleAlignmentJmol.java @@ -48,8 +48,8 @@ import org.biojava.nbio.structure.StructureException; import org.biojava.nbio.structure.StructureIdentifier; import org.biojava.nbio.structure.align.gui.MenuCreator; -import org.biojava.nbio.structure.align.gui.MultipleAlignmentJmolDisplay; import org.biojava.nbio.structure.align.gui.MultipleAlignmentGUI; +import org.biojava.nbio.structure.align.gui.MultipleAlignmentJmolDisplay; import org.biojava.nbio.structure.align.multiple.Block; import org.biojava.nbio.structure.align.multiple.BlockSet; import org.biojava.nbio.structure.align.multiple.MultipleAlignment; @@ -78,8 +78,7 @@ public class MultipleAlignmentJmol extends AbstractAlignmentJmol { private JCheckBox colorByBlocks; private List selectedStructures; - private static final String LIGAND_DISPLAY_SCRIPT = - "select ligand; wireframe 40; spacefill 120; color CPK;"; + private static final String LIGAND_DISPLAY_SCRIPT = "select ligand; wireframe 40; spacefill 120; color CPK;"; private static final Logger logger = LoggerFactory .getLogger(MultipleAlignmentJmol.class); @@ -162,17 +161,19 @@ public void windowClosing(WindowEvent e) { // / STRUCTURE SELECTION if (multAln != null) { - Box hBox0 = Box.createHorizontalBox(); - hBox0.setMaximumSize(new Dimension(Short.MAX_VALUE, 30)); + Box hBox00 = Box.createHorizontalBox(); + hBox00.setMaximumSize(new Dimension(Short.MAX_VALUE, 30)); + JButton show = new JButton("Show Only: "); show.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jmolPanel.evalString("save selection;"); - String cmd = getJmolString(multAln, transformedAtoms, - colorPalette, colorByBlocks.isSelected()); + String cmd = getJmolString(multAln, + transformedAtoms, colorPalette, + colorByBlocks.isSelected()); cmd += "; restrict "; for (int st = 0; st < multAln.size(); st++) { if (selectedStructures.get(st).isSelected()) { @@ -183,21 +184,28 @@ public void actionPerformed(ActionEvent e) { jmolPanel.executeCmd(cmd + " restore selection;"); } }); + hBox00.add(show); + hBox00.add(Box.createGlue()); + vBox.add(hBox00); + + // A line of structures of maximum 5 + for (int line = 0; line < 1 + (multAln.size() / 5); line++) { + Box hBox0 = Box.createHorizontalBox(); + hBox0.setMaximumSize(new Dimension(Short.MAX_VALUE, 30)); + + for (int str = line * 5; str < Math.min((line + 1) * 5, + multAln.size()); str++) { + JCheckBox structureSelection = new JCheckBox(multAln + .getEnsemble().getStructureIdentifiers().get(str) + .getIdentifier()); + hBox0.add(structureSelection); + hBox0.add(Box.createGlue()); + structureSelection.setSelected(true); + selectedStructures.add(structureSelection); + } - hBox0.add(show); - hBox0.add(Box.createGlue()); - - for (int str = 0; str < multAln.size(); str++) { - JCheckBox structureSelection = new JCheckBox(multAln - .getEnsemble().getStructureIdentifiers().get(str) - .getIdentifier()); - hBox0.add(structureSelection); - hBox0.add(Box.createGlue()); - structureSelection.setSelected(true); - selectedStructures.add(structureSelection); + vBox.add(hBox0); } - - vBox.add(hBox0); } // / COMBO BOXES @@ -260,7 +268,6 @@ public void actionPerformed(ActionEvent e) { // / CHECK BOXES Box hBox2 = Box.createHorizontalBox(); - hBox2.setMaximumSize(new Dimension(Short.MAX_VALUE, 30)); JButton resetDisplay = new JButton("Reset Display"); resetDisplay.addActionListener(new ActionListener() { @@ -414,12 +421,12 @@ public void actionPerformed(ActionEvent ae) { // Kimura, Structural and Fractional Dissimilarity Score Phylogeny kimura = MultipleAlignmentTools .getKimuraTree(multAln); - Phylogeny sdm = MultipleAlignmentTools - .getHSDMTree(multAln); + Phylogeny sdm = MultipleAlignmentTools.getHSDMTree(multAln); // Phylogeny structural = MultipleAlignmentTools - // .getStructuralTree(multAln); + // .getStructuralTree(multAln); - Archaeopteryx.createApplication(new Phylogeny[] { kimura, sdm }); + Archaeopteryx + .createApplication(new Phylogeny[] { kimura, sdm }); } } catch (Exception e) { logger.error("Could not complete display option.", e); diff --git a/biojava-structure-gui/src/main/java/org/biojava/nbio/structure/symmetry/gui/SymmetryCalc.java b/biojava-structure-gui/src/main/java/org/biojava/nbio/structure/symmetry/gui/SymmetryCalc.java index af55e230e4..e6840a2410 100644 --- a/biojava-structure-gui/src/main/java/org/biojava/nbio/structure/symmetry/gui/SymmetryCalc.java +++ b/biojava-structure-gui/src/main/java/org/biojava/nbio/structure/symmetry/gui/SymmetryCalc.java @@ -23,19 +23,18 @@ import org.biojava.nbio.structure.Atom; import org.biojava.nbio.structure.Structure; import org.biojava.nbio.structure.StructureException; -import org.biojava.nbio.structure.StructureTools; import org.biojava.nbio.structure.align.gui.AlignmentCalculationRunnable; import org.biojava.nbio.structure.symmetry.internal.CESymmParameters; import org.biojava.nbio.structure.symmetry.internal.CeSymm; import org.biojava.nbio.structure.symmetry.internal.CeSymmResult; +import org.biojava.nbio.structure.symmetry.utils.SymmetryTools; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * Calculates a symmetry analysis and displays the results. - * Linked to the SymmetryGUI. - * Does not generalize, uses CeSymm class directly to allow - * for the symmetry axis recovery. + * Calculates a symmetry analysis and displays the results. Linked to the + * SymmetryGUI. Does not generalize, uses CeSymm class directly to allow for the + * symmetry axis recovery. * * @author Aleix Lafita * @since 4.2.0 @@ -43,15 +42,16 @@ */ public class SymmetryCalc implements AlignmentCalculationRunnable { - private static final Logger logger = - LoggerFactory.getLogger(SymmetryCalc.class); + private static final Logger logger = LoggerFactory + .getLogger(SymmetryCalc.class); boolean interrupted = false; private Structure structure; private SymmetryGui parent; - /** Requests for a structure to analyze. + /** + * Requests for a structure to analyze. */ public SymmetryCalc(SymmetryGui p, Structure s) { parent = p; @@ -65,11 +65,12 @@ public void run() { try { - Atom[] atoms = StructureTools.getRepresentativeAtomArray(structure); + Atom[] atoms = SymmetryTools.getRepresentativeAtoms(structure); + CeSymmResult result = CeSymm.analyze(atoms, params); SymmetryDisplay.display(result); - } catch (StructureException e){ + } catch (StructureException e) { logger.warn(e.getMessage()); } parent.notifyCalcFinished(); @@ -89,5 +90,6 @@ public void cleanup() { } @Override - public void setNrCPUs(int useNrCPUs) {} + public void setNrCPUs(int useNrCPUs) { + } } diff --git a/biojava-structure-gui/src/main/java/org/biojava/nbio/structure/symmetry/gui/SymmetryDisplay.java b/biojava-structure-gui/src/main/java/org/biojava/nbio/structure/symmetry/gui/SymmetryDisplay.java index 06fabcf20a..175875df83 100644 --- a/biojava-structure-gui/src/main/java/org/biojava/nbio/structure/symmetry/gui/SymmetryDisplay.java +++ b/biojava-structure-gui/src/main/java/org/biojava/nbio/structure/symmetry/gui/SymmetryDisplay.java @@ -24,20 +24,17 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Set; -import java.util.TreeSet; - import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; -import javax.vecmath.Matrix4d; import org.biojava.nbio.structure.Atom; +import org.biojava.nbio.structure.Group; import org.biojava.nbio.structure.StructureException; import org.biojava.nbio.structure.StructureTools; +import org.biojava.nbio.structure.align.gui.MultipleAlignmentJmolDisplay; import org.biojava.nbio.structure.align.gui.StructureAlignmentDisplay; import org.biojava.nbio.structure.align.gui.jmol.AbstractAlignmentJmol; -import org.biojava.nbio.structure.align.gui.MultipleAlignmentJmolDisplay; import org.biojava.nbio.structure.align.gui.jmol.MultipleAlignmentJmol; import org.biojava.nbio.structure.align.multiple.MultipleAlignment; import org.biojava.nbio.structure.align.util.RotationAxis; @@ -45,6 +42,7 @@ import org.biojava.nbio.structure.symmetry.core.QuatSymmetryResults; import org.biojava.nbio.structure.symmetry.internal.CeSymmResult; import org.biojava.nbio.structure.symmetry.internal.SymmetryAxes; +import org.biojava.nbio.structure.symmetry.internal.SymmetryAxes.Axis; import org.biojava.nbio.structure.symmetry.jmolScript.JmolSymmetryScriptGenerator; import org.biojava.nbio.structure.symmetry.jmolScript.JmolSymmetryScriptGeneratorPointGroup; import org.biojava.nbio.structure.symmetry.utils.SymmetryTools; @@ -60,7 +58,7 @@ * */ public class SymmetryDisplay { - + private static final Logger logger = LoggerFactory .getLogger(SymmetryDisplay.class); @@ -75,7 +73,8 @@ public static MultipleAlignmentJmol displayRepeats(CeSymmResult symm) throws StructureException { MultipleAlignment repeats = SymmetryTools.toRepeatsAlignment(symm); - MultipleAlignmentJmol jmol = MultipleAlignmentJmolDisplay.display(repeats); + MultipleAlignmentJmol jmol = MultipleAlignmentJmolDisplay + .display(repeats); jmol.setTitle(getSymmTitle(symm)); return jmol; } @@ -112,9 +111,22 @@ public static AbstractAlignmentJmol display(CeSymmResult symmResult) throws StructureException { if (symmResult.isSignificant() && symmResult.isRefined()) { - // Show the structure colored by repeat + // Show the structure colored by repeat (do not rotate) MultipleAlignment msa = symmResult.getMultipleAlignment(); List atoms = msa.getAtomArrays(); + + // Add non polymer protein groups + Atom[] allAtoms = atoms.get(0); + List hetatms = StructureTools.getUnalignedGroups(allAtoms); + allAtoms = Arrays + .copyOf(allAtoms, allAtoms.length + hetatms.size()); + for (int h = 0; h < hetatms.size(); h++) { + int index = (allAtoms.length - hetatms.size()) + h; + allAtoms[index] = hetatms.get(h).getAtom(0); + } + for (int s = 0; s < msa.size(); s++) + atoms.set(s, allAtoms); + MultipleAlignmentJmol jmol = new MultipleAlignmentJmol(msa, atoms); jmol.setTitle(jmol.getStructure().getPDBHeader().getTitle()); addSymmetryMenu(jmol, symmResult); @@ -186,28 +198,53 @@ private static void addSymmetryMenu(MultipleAlignmentJmol jmol, /** * Generates a String that displays the symmetry axes of a structure. * - * @param symm CeSymmResult + * @param symm + * CeSymmResult + * @return + * @throws StructureException + */ + public static String printSymmetryAxes(CeSymmResult symm) + throws StructureException { + return printSymmetryAxes(symm,true); + } + + /** + * Generates a String that displays the symmetry axes of a structure. + * + * @param symm + * CeSymmResult + * @param allAxes Indicates whether all axes should be displayed or just + * the elemenatary ones * @return - * @throws StructureException + * @throws StructureException */ - public static String printSymmetryAxes(CeSymmResult symm) + public static String printSymmetryAxes(CeSymmResult symm,boolean allAxes) throws StructureException { int id = 0; String script = ""; SymmetryAxes axes = symm.getAxes(); - List repeats = SymmetryTools.toRepeatsAlignment(symm).getAtomArrays(); + List repeats = SymmetryTools.toRepeatsAlignment(symm) + .getAtomArrays(); - List symmAxes = axes.getElementaryAxes(); - for (int a = 0; a < symmAxes.size(); a++) { - RotationAxis rot = new RotationAxis(symmAxes.get(a)); - Set repIndex = new TreeSet(axes.getRepeatRelation(a).get(0)); - repIndex.addAll(axes.getRepeatRelation(a).get(1)); + List symmAxes; + if(allAxes) { + symmAxes = axes.getSymmetryAxes(); + } else { + symmAxes= axes.getElementaryAxesObjects(); + } + for (Axis a : symmAxes) { + RotationAxis rot = a.getRotationAxis(); + List> cyclicForm = axes.getRepeatsCyclicForm(a); List repAtoms = new ArrayList(); - for (Integer r : repIndex) - repAtoms.addAll(Arrays.asList(repeats.get(r))); - - script += rot.getJmolScript(repAtoms.toArray(new Atom[repAtoms.size()]), id); + for(List cycle : cyclicForm) { + for(Integer repeat : cycle) { + repAtoms.addAll(Arrays.asList(repeats.get(repeat))); + } + } + + script += rot.getJmolScript( + repAtoms.toArray(new Atom[repAtoms.size()]), id); id++; } @@ -225,9 +262,11 @@ public static String printSymmetryAxes(CeSymmResult symm) * @return * @throws StructureException */ - public static String printSymmetryGroup(CeSymmResult symm) throws StructureException { + public static String printSymmetryGroup(CeSymmResult symm) + throws StructureException { - QuatSymmetryResults gSymmetry = SymmetryTools.getQuaternarySymmetry(symm); + QuatSymmetryResults gSymmetry = SymmetryTools + .getQuaternarySymmetry(symm); AxisAligner axes = AxisAligner.getInstance(gSymmetry); diff --git a/biojava-structure-gui/src/main/java/org/biojava/nbio/structure/symmetry/gui/SymmetryListener.java b/biojava-structure-gui/src/main/java/org/biojava/nbio/structure/symmetry/gui/SymmetryListener.java index e47cacf2af..b9acb97492 100644 --- a/biojava-structure-gui/src/main/java/org/biojava/nbio/structure/symmetry/gui/SymmetryListener.java +++ b/biojava-structure-gui/src/main/java/org/biojava/nbio/structure/symmetry/gui/SymmetryListener.java @@ -66,7 +66,7 @@ public void actionPerformed(ActionEvent ae) { try { if (cmd.equals("Repeats Superposition")) { MultipleAlignmentJmol j = SymmetryDisplay.displayRepeats(symm); - String s = SymmetryDisplay.printSymmetryAxes(symm); + String s = SymmetryDisplay.printSymmetryAxes(symm, false); j.evalString(s); } else if (cmd.equals("Multiple Structure Alignment")) { diff --git a/biojava-structure/pom.xml b/biojava-structure/pom.xml index 31c3cddc03..4b3f63ee6f 100644 --- a/biojava-structure/pom.xml +++ b/biojava-structure/pom.xml @@ -4,7 +4,7 @@ biojava org.biojava - 4.2.1 + 4.2.2 biojava-structure biojava-structure @@ -22,13 +22,13 @@ org.biojava biojava-alignment - 4.2.1 + 4.2.2 compile org.biojava biojava-core - 4.2.1 + 4.2.2 compile @@ -123,7 +123,7 @@ false **/*.cif.gz - **/*.pdb + **/*.pdb.gz **/*.mat **/*.xml diff --git a/biojava-structure/src/main/java/org/biojava/nbio/structure/Atom.java b/biojava-structure/src/main/java/org/biojava/nbio/structure/Atom.java index b6b9229679..a98494ec3a 100644 --- a/biojava-structure/src/main/java/org/biojava/nbio/structure/Atom.java +++ b/biojava-structure/src/main/java/org/biojava/nbio/structure/Atom.java @@ -225,6 +225,14 @@ public interface Atom extends Cloneable, PDBRecord { */ public void setBonds(List bonds); + + /** Test if another atom has a bond to this atom + * + * @param other + * @return + */ + public boolean hasBond(Atom other); + /** * Get the charge of this atom * diff --git a/biojava-structure/src/main/java/org/biojava/nbio/structure/AtomImpl.java b/biojava-structure/src/main/java/org/biojava/nbio/structure/AtomImpl.java index 277972c887..e51722349e 100644 --- a/biojava-structure/src/main/java/org/biojava/nbio/structure/AtomImpl.java +++ b/biojava-structure/src/main/java/org/biojava/nbio/structure/AtomImpl.java @@ -266,6 +266,21 @@ public List getBonds() { return bonds; } + /** + * {@inheritDoc} + */ + @Override + public boolean hasBond(Atom other){ + if ( bonds == null) + return false; + + for (Bond b : bonds){ + if ( b.getAtomA().equals(other) || b.getAtomB().equals(other)) + return true; + } + return false; + } + /** * {@inheritDoc} */ diff --git a/biojava-structure/src/main/java/org/biojava/nbio/structure/BioAssemblyIdentifier.java b/biojava-structure/src/main/java/org/biojava/nbio/structure/BioAssemblyIdentifier.java index 4ecd0df85d..c47df92357 100644 --- a/biojava-structure/src/main/java/org/biojava/nbio/structure/BioAssemblyIdentifier.java +++ b/biojava-structure/src/main/java/org/biojava/nbio/structure/BioAssemblyIdentifier.java @@ -72,8 +72,7 @@ public Structure loadStructure(AtomCache cache) throws StructureException, @Override public SubstructureIdentifier toCanonical() throws StructureException { - // null pdbCode indicates that the structure can't be loaded by AtomCache - return new SubstructureIdentifier(null, new ArrayList()); + return new SubstructureIdentifier(pdbCode, new ArrayList()); } @Override diff --git a/biojava-structure/src/main/java/org/biojava/nbio/structure/StandardAminoAcid.java b/biojava-structure/src/main/java/org/biojava/nbio/structure/StandardAminoAcid.java index 20c929a125..a79d192d8c 100644 --- a/biojava-structure/src/main/java/org/biojava/nbio/structure/StandardAminoAcid.java +++ b/biojava-structure/src/main/java/org/biojava/nbio/structure/StandardAminoAcid.java @@ -27,6 +27,7 @@ import java.io.InputStream; import java.util.HashMap; import java.util.Map; +import java.util.zip.GZIPInputStream; /** A class that provides a set of standard amino acids. @@ -40,7 +41,7 @@ */ public final class StandardAminoAcid { - private static final String STANDARD_AMINOS_FILE = "org/biojava/nbio/structure/standardaminos.pdb"; + private static final String STANDARD_AMINOS_FILE = "org/biojava/nbio/structure/standardaminos.pdb.gz"; static private Map aminoAcids; @@ -72,9 +73,12 @@ private StandardAminoAcid() { throw new RuntimeException("Could not find resource "+STANDARD_AMINOS_FILE+". This probably means that your biojava.jar file is corrupt or incorrectly built."); } + + try { + GZIPInputStream gzipIS = new GZIPInputStream(fileStream); PDBFileParser parser = new PDBFileParser(); - Structure s = parser.parsePDBFile(fileStream); + Structure s = parser.parsePDBFile(gzipIS); GroupIterator iter = new GroupIterator(s); diff --git a/biojava-structure/src/main/java/org/biojava/nbio/structure/align/multiple/util/MultipleAlignmentDisplay.java b/biojava-structure/src/main/java/org/biojava/nbio/structure/align/multiple/util/MultipleAlignmentDisplay.java index bf04eaacb2..91e939c29f 100644 --- a/biojava-structure/src/main/java/org/biojava/nbio/structure/align/multiple/util/MultipleAlignmentDisplay.java +++ b/biojava-structure/src/main/java/org/biojava/nbio/structure/align/multiple/util/MultipleAlignmentDisplay.java @@ -56,7 +56,6 @@ public class MultipleAlignmentDisplay { * @return list of transformed AtomArrays * @throws StructureException */ - public static List getRotatedAtoms(MultipleAlignment multAln) throws StructureException { @@ -96,12 +95,15 @@ public static List getRotatedAtoms(MultipleAlignment multAln) // Assume all atoms are from the same structure Structure displayS = atomArrays.get(i)[0].getGroup().getChain() .getStructure().clone(); + // Get all the atoms and include ligands and hetatoms Atom[] rotCA = StructureTools.getRepresentativeAtomArray(displayS); List hetatms = StructureTools.getUnalignedGroups(rotCA); + int index = rotCA.length; + rotCA = Arrays.copyOf(rotCA, rotCA.length + hetatms.size()); for (Group g : hetatms) { - rotCA = Arrays.copyOf(rotCA, rotCA.length + 1); - rotCA[rotCA.length - 1] = g.getAtom(0); + rotCA[index] = g.getAtom(0); + index++; } // Transform the structure to ensure a full rotation in the display diff --git a/biojava-structure/src/main/java/org/biojava/nbio/structure/align/util/RotationAxis.java b/biojava-structure/src/main/java/org/biojava/nbio/structure/align/util/RotationAxis.java index 02889a49cf..779e78be6c 100644 --- a/biojava-structure/src/main/java/org/biojava/nbio/structure/align/util/RotationAxis.java +++ b/biojava-structure/src/main/java/org/biojava/nbio/structure/align/util/RotationAxis.java @@ -25,6 +25,7 @@ import org.biojava.nbio.structure.Calc; import org.biojava.nbio.structure.StructureException; import org.biojava.nbio.structure.align.model.AFPChain; +import org.biojava.nbio.structure.contact.Pair; import org.biojava.nbio.structure.jama.Matrix; import javax.vecmath.AxisAngle4d; @@ -112,6 +113,10 @@ public Atom getScrewTranslation() { public Vector3d getVector3dScrewTranslation() { return new Vector3d(screwTranslation.getX(),screwTranslation.getY(),screwTranslation.getZ()); } + + public double getTranslation() { + return Calc.amount(screwTranslation); + } /** * Get the component of translation perpendicular to the axis of rotation. @@ -385,27 +390,17 @@ public String getJmolScript(Atom[] atoms){ } /** - * Returns a Jmol script which will display the axis of rotation. This - * consists of a cyan arrow along the axis, plus an arc showing the angle - * of rotation. + * Find a segment of the axis that covers the specified set of atoms. *

- * As the rotation angle gets smaller, the axis of rotation becomes poorly - * defined and would need to get farther and farther away from the protein. - * This is not particularly useful, so we arbitrarily draw it parallel to - * the translation and omit the arc. - * @param atoms Some atoms from the protein, used for determining the bounds - * of the axis. - * @param axisID in case of representing more than one axis in the same jmol - * panel, indicate the ID number. - * - * @return The Jmol script, suitable for calls to - * {@link org.biojava.nbio.structure.align.gui.jmol.StructureAlignmentJmol#evalString() jmol.evalString()} + * Projects the input atoms onto the rotation axis and returns the bounding + * points. + *

+ * In the case of a pure translational axis, the axis location is undefined + * so the center of mass will be used instead. + * @param atoms + * @return two points defining the axis segment */ - public String getJmolScript(Atom[] atoms, int axisID){ - final double width=.5;// width of JMol object - final String axisColor = "yellow"; //axis color - final String screwColor = "orange"; //screw translation color - + public Pair getAxisEnds(Atom[] atoms) { // Project each Atom onto the rotation axis to determine limits double min, max; min = max = Calc.scalarProduct(rotationAxis,atoms[0]); @@ -417,7 +412,7 @@ public String getJmolScript(Atom[] atoms, int axisID){ double uLen = Calc.scalarProduct(rotationAxis,rotationAxis);// Should be 1, but double check min/=uLen; max/=uLen; - + // Project the origin onto the axis. If the axis is undefined, use the center of mass Atom axialPt; if(rotationPos == null) { @@ -439,6 +434,34 @@ public String getJmolScript(Atom[] atoms, int axisID){ Atom axisMax = (Atom) axialPt.clone(); Calc.scaleAdd(max, rotationAxis, axisMax); + return new Pair<>(axisMin, axisMax); + } + /** + * Returns a Jmol script which will display the axis of rotation. This + * consists of a cyan arrow along the axis, plus an arc showing the angle + * of rotation. + *

+ * As the rotation angle gets smaller, the axis of rotation becomes poorly + * defined and would need to get farther and farther away from the protein. + * This is not particularly useful, so we arbitrarily draw it parallel to + * the translation and omit the arc. + * @param atoms Some atoms from the protein, used for determining the bounds + * of the axis. + * @param axisID in case of representing more than one axis in the same jmol + * panel, indicate the ID number. + * + * @return The Jmol script, suitable for calls to + * {@link org.biojava.nbio.structure.align.gui.jmol.StructureAlignmentJmol#evalString() jmol.evalString()} + */ + public String getJmolScript(Atom[] atoms, int axisID){ + final double width=.5;// width of JMol object + final String axisColor = "yellow"; //axis color + final String screwColor = "orange"; //screw translation color + + Pair endPoints = getAxisEnds(atoms); + Atom axisMin = endPoints.getFirst(); + Atom axisMax = endPoints.getSecond(); + StringWriter result = new StringWriter(); // set arrow heads to a reasonable length diff --git a/biojava-structure/src/main/java/org/biojava/nbio/structure/io/mmcif/MetalBondConsumer.java b/biojava-structure/src/main/java/org/biojava/nbio/structure/io/mmcif/MetalBondConsumer.java new file mode 100644 index 0000000000..34f85b6614 --- /dev/null +++ b/biojava-structure/src/main/java/org/biojava/nbio/structure/io/mmcif/MetalBondConsumer.java @@ -0,0 +1,253 @@ +package org.biojava.nbio.structure.io.mmcif; + +import org.biojava.nbio.structure.io.FileParsingParameters; +import org.biojava.nbio.structure.io.mmcif.chem.MetalBondDistance; +import org.biojava.nbio.structure.io.mmcif.model.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by andreas on 6/9/16. + */ +public class MetalBondConsumer implements MMcifConsumer{ + + + Map> definitions = new HashMap(); + + @Override + public void documentStart() { + definitions.clear(); + } + + @Override + public void documentEnd() { + + // minimize memory consumption + + for (List d : definitions.values()){ + ArrayList a = (ArrayList)d; + + a.trimToSize(); + } + + } + + @Override + public void newAtomSite(AtomSite atom) { + + } + + @Override + public void newEntity(Entity entity) { + + } + + + @Override + public void newEntityPolySeq(EntityPolySeq epolseq) { + + } + + @Override + public void newStructAsym(StructAsym sasym) { + + } + + @Override + public void setStruct(Struct struct) { + + } + + @Override + public void newDatabasePDBrev(DatabasePDBrev dbrev) { + + } + + @Override + public void newDatabasePDBrevRecord(DatabasePdbrevRecord dbrev) { + + } + + @Override + public void newDatabasePDBremark(DatabasePDBremark remark) { + + } + + @Override + public void newExptl(Exptl exptl) { + + } + + @Override + public void newCell(Cell cell) { + + } + + @Override + public void newSymmetry(Symmetry symmetry) { + + } + + @Override + public void newStructNcsOper(StructNcsOper sNcsOper) { + + } + + @Override + public void newStructRef(StructRef sref) { + + } + + @Override + public void newStructRefSeq(StructRefSeq sref) { + + } + + @Override + public void newStructRefSeqDif(StructRefSeqDif sref) { + + } + + @Override + public void newStructSite(StructSite sref) { + + } + + @Override + public void newStructSiteGen(StructSiteGen sref) { + + } + + @Override + public void newPdbxPolySeqScheme(PdbxPolySeqScheme ppss) { + + } + + @Override + public void newPdbxNonPolyScheme(PdbxNonPolyScheme ppss) { + + } + + @Override + public void newPdbxEntityNonPoly(PdbxEntityNonPoly pen) { + + } + + @Override + public void newStructKeywords(StructKeywords kw) { + + } + + @Override + public void newRefine(Refine r) { + + } + + @Override + public void newChemComp(ChemComp c) { + + } + + @Override + public void newChemCompDescriptor(ChemCompDescriptor ccd) { + + } + + @Override + public void newPdbxStructOperList(PdbxStructOperList structOper) { + + } + + @Override + public void newPdbxStrucAssembly(PdbxStructAssembly strucAssembly) { + + } + + @Override + public void newPdbxStrucAssemblyGen(PdbxStructAssemblyGen strucAssembly) { + + } + + @Override + public void newChemCompAtom(ChemCompAtom atom) { + + } + + @Override + public void newPdbxChemCompIndentifier(PdbxChemCompIdentifier id) { + + } + + @Override + public void newChemCompBond(ChemCompBond bond) { + + } + + @Override + public void newPdbxChemCompDescriptor(PdbxChemCompDescriptor desc) { + + } + + @Override + public void newEntitySrcGen(EntitySrcGen entitySrcGen) { + + } + + @Override + public void newEntitySrcNat(EntitySrcNat entitySrcNat) { + + } + + @Override + public void newEntitySrcSyn(EntitySrcSyn entitySrcSyn) { + + } + + @Override + public void newStructConn(StructConn structConn) { + + } + + @Override + public void newAuditAuthor(AuditAuthor aa) { + + } + + @Override + public void newGenericData(String category, List loopFields, List lineData) { + + MetalBondDistance d = new MetalBondDistance(); + + d.setAtomType1(lineData.get(0)); + d.setAtomType2(lineData.get(1)); + d.setLowerLimit(Float.parseFloat(lineData.get(2))); + d.setUpperLimit(Float.parseFloat(lineData.get(3))); + + List defs = definitions.get(d.getAtomType1()); + + if ( defs == null){ + defs = new ArrayList<>(); + definitions.put(d.getAtomType1(),defs); + } + + defs.add(d); + + } + + @Override + public void setFileParsingParameters(FileParsingParameters params) { + + } + + @Override + public FileParsingParameters getFileParsingParameters() { + return null; + } + + public Map> getDefinitions(){ + return definitions; + } +} diff --git a/biojava-structure/src/main/java/org/biojava/nbio/structure/io/mmcif/MetalBondParser.java b/biojava-structure/src/main/java/org/biojava/nbio/structure/io/mmcif/MetalBondParser.java new file mode 100644 index 0000000000..2a4853d935 --- /dev/null +++ b/biojava-structure/src/main/java/org/biojava/nbio/structure/io/mmcif/MetalBondParser.java @@ -0,0 +1,66 @@ +package org.biojava.nbio.structure.io.mmcif; + +import org.biojava.nbio.structure.io.mmcif.chem.MetalBondDistance; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.InputStream; +import java.util.*; + +import java.util.zip.GZIPInputStream; + +/** + * Created by andreas on 6/6/16. + */ +public class MetalBondParser { + + private static final Logger logger = LoggerFactory.getLogger(MetalBondParser.class); + + private static final String BONDS_FILE = "org/biojava/nbio/structure/bond_distance_limits.cif.gz"; + + + static Map> definitions; + + static { + definitions = init(); + } + + + public static Map> getMetalBondDefinitions(){ + return definitions; + + } + + + private static Map> init(){ + + InputStream inputStream = MetalBondParser.class.getClassLoader().getResourceAsStream(BONDS_FILE); + + if (inputStream == null) { + throw new RuntimeException("Could not find resource "+BONDS_FILE+". This probably means that your biojava.jar file is corrupt or incorrectly built."); + } + + try { + GZIPInputStream gzIS = new GZIPInputStream(inputStream); + + SimpleMMcifParser parser = new SimpleMMcifParser(); + + MetalBondConsumer consumer = new MetalBondConsumer(); + parser.addMMcifConsumer(consumer); + + parser.parse(gzIS); + + Map> defs = consumer.getDefinitions(); + + return defs; + + } catch ( Exception e){ + logger.error(e.getMessage(),e); + + } + return null; + } + + + +} diff --git a/biojava-structure/src/main/java/org/biojava/nbio/structure/io/mmcif/chem/MetalBondDistance.java b/biojava-structure/src/main/java/org/biojava/nbio/structure/io/mmcif/chem/MetalBondDistance.java new file mode 100644 index 0000000000..4d96521f6b --- /dev/null +++ b/biojava-structure/src/main/java/org/biojava/nbio/structure/io/mmcif/chem/MetalBondDistance.java @@ -0,0 +1,56 @@ +package org.biojava.nbio.structure.io.mmcif.chem; + +/** A bean that contains cutoffs for correctly detecting metal bonds. + * Definitions are in file bond_distance_limits.cif.gz + * + * Created by andreas on 6/9/16. + */ +public class MetalBondDistance { + + private String atomType1; + private String atomType2; + private float lowerLimit; + private float upperLimit; + + public String getAtomType1() { + return atomType1; + } + + public void setAtomType1(String atomType1) { + this.atomType1 = atomType1; + } + + public String getAtomType2() { + return atomType2; + } + + public void setAtomType2(String atomType2) { + this.atomType2 = atomType2; + } + + public float getLowerLimit() { + return lowerLimit; + } + + public void setLowerLimit(float lowerLimit) { + this.lowerLimit = lowerLimit; + } + + public float getUpperLimit() { + return upperLimit; + } + + public void setUpperLimit(float upperLimit) { + this.upperLimit = upperLimit; + } + + @Override + public String toString() { + return "MetalBindDistance{" + + "atomType1='" + atomType1 + '\'' + + ", atomType2='" + atomType2 + '\'' + + ", lowerLimit=" + lowerLimit + + ", upperLimit=" + upperLimit + + '}'; + } +} diff --git a/biojava-structure/src/main/java/org/biojava/nbio/structure/symmetry/internal/CeSymm.java b/biojava-structure/src/main/java/org/biojava/nbio/structure/symmetry/internal/CeSymm.java index 908d20d5f1..4e3841235b 100644 --- a/biojava-structure/src/main/java/org/biojava/nbio/structure/symmetry/internal/CeSymm.java +++ b/biojava-structure/src/main/java/org/biojava/nbio/structure/symmetry/internal/CeSymm.java @@ -250,20 +250,20 @@ protected static CeSymmResult align(Atom[] atoms, CESymmParameters params) result.setStructureId(id); // Determine the symmetry Type or get the one in params - if (params.getSymmType() == SymmetryType.AUTO) { + SymmetryType type = params.getSymmType(); + if (type == SymmetryType.AUTO) { if (result.getSelfAlignment().getBlockNum() == 1) { - result.setType(SymmetryType.OPEN); + type = SymmetryType.OPEN; logger.info("Open Symmetry detected"); } else { - result.setType(SymmetryType.CLOSED); + type = SymmetryType.CLOSED; logger.info("Close Symmetry detected"); } - } else - result.setType(params.getSymmType()); + } // Do not try the refinement if the self-alignment is not significant if (optimalAFP.getTMScore() < params.getUnrefinedScoreThreshold()){ - result.setSymmOrder(1); + result.setNumRepeats(1); return result; } @@ -278,7 +278,7 @@ protected static CeSymmResult align(Atom[] atoms, CESymmParameters params) break; case SEQUENCE_FUNCTION: // Does not work for OPEN alignments - if (result.getType() == SymmetryType.CLOSED) { + if (type == SymmetryType.CLOSED) { orderDetector = new SequenceFunctionOrderDetector( params.getMaxSymmOrder(), 0.4f); order = orderDetector.calculateOrder( @@ -287,7 +287,7 @@ protected static CeSymmResult align(Atom[] atoms, CESymmParameters params) } case ANGLE: // Does not work for OPEN alignments - if (result.getType() == SymmetryType.CLOSED) { + if (type == SymmetryType.CLOSED) { orderDetector = new AngleOrderDetectorPlus( params.getMaxSymmOrder()); order = orderDetector.calculateOrder( @@ -300,7 +300,7 @@ protected static CeSymmResult align(Atom[] atoms, CESymmParameters params) atoms); break; } - result.setSymmOrder(order); + result.setNumRepeats(order); // REFINEMENT SymmetryRefiner refiner = null; @@ -309,7 +309,7 @@ protected static CeSymmResult align(Atom[] atoms, CESymmParameters params) return result; case SEQUENCE_FUNCTION: // Does not work for OPEN alignments - if (result.getType() == SymmetryType.CLOSED) { + if (type == SymmetryType.CLOSED) { refiner = new SequenceFunctionRefiner(); break; } @@ -323,7 +323,7 @@ protected static CeSymmResult align(Atom[] atoms, CESymmParameters params) // Refinement succeeded, store results result.setMultipleAlignment(msa); - result.setSymmOrder(msa.size()); + result.setNumRepeats(msa.size()); result.setRefined(true); } catch (RefinerFailedException e) { @@ -331,41 +331,13 @@ protected static CeSymmResult align(Atom[] atoms, CESymmParameters params) return result; } - // STEP 4: determine the symmetry axis and its repeat dependencies + // STEP 4: symmetry axes SymmetryAxes axes = new SymmetryAxes(); int order = result.getMultipleAlignment().size(); Matrix4d axis = result.getMultipleAlignment().getBlockSet(0) .getTransformations().get(1); - - List> superposition = new ArrayList>(); - List chain1 = new ArrayList(); - List chain2 = new ArrayList(); - superposition.add(chain1); - superposition.add(chain2); - List repeatTrans = new ArrayList(); - - switch (result.getType()) { - case CLOSED: - - for (int bk = 0; bk < order; bk++) { - chain1.add(bk); - chain2.add((bk + 1) % order); - repeatTrans.add(bk); - } - axes.addAxis(axis, superposition, repeatTrans, order); - break; - - default: // case OPEN: - - repeatTrans.add(0); - for (int bk = 0; bk < order - 1; bk++) { - chain1.add(bk); - chain2.add(bk + 1); - repeatTrans.add(bk + 1); - } - axes.addAxis(axis, superposition, repeatTrans, order); - break; - } + axes.addAxis(axis, order, type); + result.setAxes(axes); return result; } diff --git a/biojava-structure/src/main/java/org/biojava/nbio/structure/symmetry/internal/CeSymmIterative.java b/biojava-structure/src/main/java/org/biojava/nbio/structure/symmetry/internal/CeSymmIterative.java index 0a55d6d2f1..669cefcfe4 100644 --- a/biojava-structure/src/main/java/org/biojava/nbio/structure/symmetry/internal/CeSymmIterative.java +++ b/biojava-structure/src/main/java/org/biojava/nbio/structure/symmetry/internal/CeSymmIterative.java @@ -29,6 +29,7 @@ import javax.vecmath.Matrix4d; import org.biojava.nbio.structure.Atom; +import org.biojava.nbio.structure.ResidueNumber; import org.biojava.nbio.structure.StructureException; import org.biojava.nbio.structure.StructureIdentifier; import org.biojava.nbio.structure.align.multiple.Block; @@ -42,6 +43,7 @@ import org.biojava.nbio.structure.secstruc.SecStrucTools; import org.biojava.nbio.structure.secstruc.SecStrucType; import org.biojava.nbio.structure.symmetry.internal.CESymmParameters.RefineMethod; +import org.biojava.nbio.structure.symmetry.internal.CESymmParameters.SymmetryType; import org.biojava.nbio.structure.symmetry.utils.SymmetryTools; import org.jgrapht.UndirectedGraph; import org.jgrapht.alg.ConnectivityInspector; @@ -51,8 +53,8 @@ import org.slf4j.LoggerFactory; /** - * Iterative version of CeSymm that aims at identifying all symmetry axis - * (internal or quaternary) of a particular structure. + * Iterative version of CeSymm that aims at identifying all symmetry axis of a + * structure. *

* Works in the following way: *

    @@ -61,7 +63,6 @@ *
  • Run CeSymm on one of the symmetric units to find further symmetries. *
  • Repeat the last two steps until no more significant results are found. *
  • Map back all residues in a multiple alignment of the repeats. - *
  • Run a final optimization of all symmetric units correctly superimposed. *
* * @@ -75,10 +76,8 @@ public class CeSymmIterative { .getLogger(CeSymmIterative.class); private CESymmParameters params; - private Atom[] allAtoms; - private UndirectedGraph alignGraph; // alignment graph - private List levels; // msa at each level - private CeSymmResult result; + private UndirectedGraph alignGraph; // cumulative + private List levels; // symmetry at each level /** * For the iterative algorithm to work properly the refinement and @@ -91,7 +90,7 @@ public class CeSymmIterative { public CeSymmIterative(CESymmParameters param) { params = param; alignGraph = new SimpleGraph(DefaultEdge.class); - levels = new ArrayList(); + levels = new ArrayList(); } /** @@ -107,29 +106,10 @@ public CeSymmIterative(CESymmParameters param) { */ public CeSymmResult execute(Atom[] atoms) throws StructureException { - allAtoms = atoms; + // First iterate through all levels and then reconstruct all repeats + iterate(atoms); + return reconstructSymmResult(atoms); - // True if symmetry found - boolean symm = iterate(atoms); - - if (symm) { - if (!buildAlignment()) - return result; - - recoverAxes(); - - // Set the transformations and scores of the final alignment - MultipleAlignment msa = result.getMultipleAlignment(); - SymmetryTools.updateSymmetryTransformation(result.getAxes(), msa, - atoms); - double tmScore = MultipleAlignmentScorer.getAvgTMScore(msa) - * msa.size(); - double rmsd = MultipleAlignmentScorer.getRMSD(msa); - msa.putScore(MultipleAlignmentScorer.AVGTM_SCORE, tmScore); - msa.putScore(MultipleAlignmentScorer.RMSD, rmsd); - } - - return result; } /** @@ -141,60 +121,62 @@ public CeSymmResult execute(Atom[] atoms) throws StructureException { * @return true if any symmetry was found, false if asymmetric * @throws StructureException */ - private boolean iterate(Atom[] atoms) throws StructureException { + private void iterate(Atom[] atoms) throws StructureException { logger.debug("Starting new iteration..."); // Return if the Atom array is too short - if (atoms.length <= params.getWinSize() - || atoms.length <= params.getMinCoreLength()) { - if (result != null) { - logger.debug("Aborting iteration due to insufficient Atom " - + "array length: %d", atoms.length); - return !levels.isEmpty(); - } + if ((atoms.length <= params.getWinSize() + || atoms.length <= params.getMinCoreLength()) + && !levels.isEmpty()) { + logger.debug("Aborting iteration due to insufficient Atom " + + "array length: %d", atoms.length); + return; } // Return if the maximum levels of symmetry have been reached if (params.getSymmLevels() > 0) { if (levels.size() == params.getSymmLevels()) - return true; + return; } // Perform one level CeSymm alignment - CeSymmResult r = CeSymm.analyzeLevel(atoms, params); - if (result == null) - result = r; + CeSymmResult result = CeSymm.analyzeLevel(atoms, params); - if (params.getRefineMethod() == RefineMethod.NOT_REFINED) - return false; - else if (!r.isSignificant()) - return !levels.isEmpty(); + if (params.getRefineMethod() == RefineMethod.NOT_REFINED + || !result.isSignificant()) { + if (levels.isEmpty()) + levels.add(result); + return; + } // Generate the Atoms of one of the symmetric repeat Integer start = null; int it = 0; while (start == null) { - start = r.getMultipleAlignment().getBlocks().get(0).getAlignRes() - .get(0).get(it); + start = result.getMultipleAlignment().getBlocks().get(0) + .getAlignRes().get(0).get(it); it++; } Integer end = null; - it = r.getMultipleAlignment().getBlocks().get(0).getAlignRes().get(0) - .size() - 1; + it = result.getMultipleAlignment().getBlocks().get(0).getAlignRes() + .get(0).size() - 1; while (end == null) { - end = r.getMultipleAlignment().getBlocks().get(0).getAlignRes() - .get(0).get(it); + end = result.getMultipleAlignment().getBlocks().get(0) + .getAlignRes().get(0).get(it); it--; } Atom[] atomsR = Arrays.copyOfRange(atoms, start, end + 1); // Check the SSE requirement - if (countHelixStrandSSE(atomsR) < params.getSSEThreshold()) - return !levels.isEmpty(); + if (countHelixStrandSSE(atomsR) < params.getSSEThreshold()) { + if (levels.isEmpty()) + levels.add(result); + return; + } // If symmetric store the residue dependencies in alignment graph - Block b = r.getMultipleAlignment().getBlock(0); + Block b = result.getMultipleAlignment().getBlock(0); for (int pos = 0; pos < b.length(); pos++) { for (int su = 0; su < b.size() - 1; su++) { Integer pos1 = b.getAlignRes().get(su).get(pos); @@ -209,26 +191,32 @@ else if (!r.isSignificant()) } // Iterate further on those Atoms (of the first repeat only) - levels.add(r.getMultipleAlignment()); - return iterate(atomsR); + levels.add(result); + iterate(atomsR); } /** - * After all the analysis iteratives have finished, the final - * MultipleAlignment object is constructed using the alignment graph. + * After all the analysis iterations have finished, the final Result object + * is reconstructed using the cumulative alignment graph. * - * @return true if the MultipleAlignment could be reconstructed, false - * otherwise + * @param atoms + * the original structure atoms + * @return CeSymmResult reconstructed symmetry result * @throws StructureException */ - private boolean buildAlignment() throws StructureException { - - // If one level, nothing to build - if (levels.size() == 1) { - result.setSymmLevels(1); - return false; - } + private CeSymmResult reconstructSymmResult(Atom[] atoms) + throws StructureException { + + // If one level, nothing to build or calculate + if (levels.size() == 1) + return levels.get(0); + CeSymmResult result = new CeSymmResult(); + result.setSelfAlignment(levels.get(0).getSelfAlignment()); + result.setStructureId(levels.get(0).getStructureId()); + result.setAtoms(levels.get(0).getAtoms()); + result.setParams(levels.get(0).getParams()); + // Initialize a new multiple alignment MultipleAlignment msa = new MultipleAlignmentImpl(); msa.getEnsemble().setAtomArrays(new ArrayList()); @@ -249,10 +237,10 @@ private boolean buildAlignment() throws StructureException { for (Set comp : comps) groups.add(new ResidueGroup(comp)); - // Calculate thr order of symmetry from levels + // Calculate the total number of repeats int order = 1; - for (MultipleAlignment m : levels) - order *= m.size(); + for (CeSymmResult sr : levels) + order *= sr.getMultipleAlignment().size(); for (int su = 0; su < order; su++) b.getAlignRes().add(new ArrayList()); @@ -262,71 +250,57 @@ private boolean buildAlignment() throws StructureException { continue; group.combineWith(b.getAlignRes()); } + + // The reconstruction failed, so the top level is returned if (b.length() == 0) - return false; + return levels.get(0); for (int su = 0; su < order; su++) { Collections.sort(b.getAlignRes().get(su)); - msa.getEnsemble().getAtomArrays().add(allAtoms); + msa.getEnsemble().getAtomArrays().add(atoms); msa.getEnsemble().getStructureIdentifiers() .add(result.getStructureId()); } result.setMultipleAlignment(msa); result.setRefined(true); - result.setSymmOrder(order); - result.setSymmLevels(levels.size()); + result.setNumRepeats(order); + + SymmetryAxes axes = recoverAxes(result); + result.setAxes(axes); - return true; + // Set the transformations and scores of the final alignment + SymmetryTools + .updateSymmetryTransformation(result.getAxes(), msa); + double tmScore = MultipleAlignmentScorer.getAvgTMScore(msa) + * msa.size(); + double rmsd = MultipleAlignmentScorer.getRMSD(msa); + msa.putScore(MultipleAlignmentScorer.AVGTM_SCORE, tmScore); + msa.putScore(MultipleAlignmentScorer.RMSD, rmsd); + + return result; } /** * The symmetry axes of each level are recovered after the symmetry analysis * iterations have finished, using the stored MultipleAlignment at each * symmetry level. + * @return SymmetryAxes */ - private void recoverAxes() { + private SymmetryAxes recoverAxes(CeSymmResult result) { SymmetryAxes axes = new SymmetryAxes(); - int size = result.getMultipleAlignment().size(); - int parents = 1; - for (int m = 0; m < levels.size(); m++) { - MultipleAlignment align = levels.get(m); + MultipleAlignment align = levels.get(m).getMultipleAlignment(); Matrix4d axis = align.getBlockSet(0).getTransformations().get(1); + SymmetryType type = levels.get(m).getAxes().getElementaryAxis(0).getSymmType(); + int order = align.size(); - int subsize = align.size(); - parents *= subsize; - size /= subsize; - - List repeatTransform = new ArrayList(); - for (int i = 0; i < size * parents; i++) { - repeatTransform.add(0); - } - - List> superpose = new ArrayList>(); - superpose.add(new ArrayList()); - superpose.add(new ArrayList()); - - for (int su = 0; su < subsize - 1; su++) { - for (int s = 0; s < size; s++) { - Integer subIndex1 = su * size + s; - Integer subIndex2 = (su + 1) * size + s; - superpose.get(0).add(subIndex1); - superpose.get(1).add(subIndex2); - } - } - - for (int p = 0; p < parents; p++) { - for (int s = 0; s < size; s++) { - repeatTransform.set(p * size + s, p % subsize); - } - } - axes.addAxis(axis, superpose, repeatTransform, subsize); + axes.addAxis(axis, order, type); } - result.setAxes(axes); + return axes; } /** @@ -341,11 +315,27 @@ private static int countHelixStrandSSE(Atom[] atoms) { List sses = SecStrucTools .getSecStrucElements(SymmetryTools.getGroups(atoms)); int count = 0; + + //keep track of different helix types + boolean helix = false; + int hEnd = 0; + for (SecStrucElement sse : sses) { SecStrucType t = sse.getType(); - if (t.isBetaStrand() || t.isHelixType()) { + if (t.isBetaStrand()) { + helix = false; count++; - } + } else if (t.isHelixType()){ + if (helix){ + // If this helix is contiguous to the previous + if (sse.getRange().getStart().getSeqNum() + 1 == hEnd) + hEnd = sse.getRange().getEnd().getSeqNum(); + else + count++; + } else + count++; + } else + helix = false; } return count; } diff --git a/biojava-structure/src/main/java/org/biojava/nbio/structure/symmetry/internal/CeSymmResult.java b/biojava-structure/src/main/java/org/biojava/nbio/structure/symmetry/internal/CeSymmResult.java index 27647c341a..8574c2e984 100644 --- a/biojava-structure/src/main/java/org/biojava/nbio/structure/symmetry/internal/CeSymmResult.java +++ b/biojava-structure/src/main/java/org/biojava/nbio/structure/symmetry/internal/CeSymmResult.java @@ -56,24 +56,22 @@ public class CeSymmResult { private Atom[] atoms; private CESymmParameters params; - private SymmetryAxes axes; + private SymmetryAxes axes = new SymmetryAxes(); private String symmGroup; - private int symmOrder; - private int symmLevels; + private int numRepeats; private boolean refined; - private SymmetryType type; /** - * Conditions checked are: score above the threshold, order higher than 1 - * and refinement succeeded. + * Conditions checked are: score above the threshold, number of repeats + * higher than 1 and refinement succeeded. * * @return true if significant, false otherwise */ public boolean isSignificant() { // In any case if the order is 1 it is asymmetric - if (symmOrder < 2) + if (numRepeats < 2) return false; // If the TM-Score before refinement is below the threshold @@ -108,12 +106,12 @@ public List getRepeatsID() throws StructureException { return null; List repeats = new ArrayList( - symmOrder); + numRepeats); String pdbId = structureId.toCanonical().getPdbId(); Block align = multipleAlignment.getBlocks().get(0); - for (int su = 0; su < symmOrder; su++) { + for (int su = 0; su < numRepeats; su++) { // Get the start and end residues of the repeat ResidueNumber res1 = atoms[align.getStartResidue(su)].getGroup() .getResidueNumber(); @@ -131,9 +129,9 @@ public List getRepeatsID() throws StructureException { @Override public String toString() { - return structureId + ", symmGroup=" + getSymmGroup() + ", symmOrder=" - + symmOrder + ", symmLevels=" + symmLevels + ", refined=" - + refined + ", type=" + type + " | " + params; + return structureId + ", symmGroup=" + getSymmGroup() + ", numRepeats=" + + numRepeats + ", symmLevels=" + axes.getNumLevels() + + ", refined=" + refined + " | " + params; } public MultipleAlignment getMultipleAlignment() { @@ -174,15 +172,15 @@ public void setAxes(SymmetryAxes axes) { * * @return the order of symmetry if the result is significant */ - public int getSymmOrder() { + public int getNumRepeats() { if (isSignificant()) - return symmOrder; + return numRepeats; else return 1; } - public void setSymmOrder(int symmOrder) { - this.symmOrder = symmOrder; + public void setNumRepeats(int symmOrder) { + this.numRepeats = symmOrder; } public boolean isRefined() { @@ -208,8 +206,9 @@ public String getSymmGroup() { symmGroup = "R"; // could not find group } else { // in case significant but not refined - if (type.equals(SymmetryType.CLOSED)) - symmGroup = "C" + symmOrder; + if (axes.getElementaryAxis(0).getSymmType() + .equals(SymmetryType.CLOSED)) + symmGroup = "C" + numRepeats; else symmGroup = "R"; } @@ -224,14 +223,6 @@ public void setSymmGroup(String symmGroup) { this.symmGroup = symmGroup; } - public SymmetryType getType() { - return type; - } - - public void setType(SymmetryType type) { - this.type = type; - } - public Atom[] getAtoms() { return atoms; } @@ -241,11 +232,7 @@ public void setAtoms(Atom[] atoms) { } public int getSymmLevels() { - return symmLevels; - } - - public void setSymmLevels(int symmLevels) { - this.symmLevels = symmLevels; + return axes.getNumLevels(); } public StructureIdentifier getStructureId() { @@ -257,8 +244,8 @@ public void setStructureId(StructureIdentifier structureId) { } /** - * Return a String describing the reasons for the CE-Symm final decision - * in this particular result. + * Return a String describing the reasons for the CE-Symm final decision in + * this particular result. * * @return String decision reason */ @@ -270,8 +257,9 @@ public String getReason() { return String.format("Insignificant self-alignment (TM=%.2f)", tm); } // 2. Asymmetric because order detector returned 1 - if (symmOrder == 1) { - return String.format("Order detector found asymmetric alignment (TM=%.2f)", tm); + if (numRepeats == 1) { + return String.format( + "Order detector found asymmetric alignment (TM=%.2f)", tm); } // Check that the user requested refinement @@ -280,8 +268,8 @@ public String getReason() { if (!refined) { return "Refinement failed"; } - tm = multipleAlignment.getScore( - MultipleAlignmentScorer.AVGTM_SCORE); + tm = multipleAlignment + .getScore(MultipleAlignmentScorer.AVGTM_SCORE); // 4. Asymmetric because refinement & optimization were not // significant if (!isSignificant()) { @@ -297,15 +285,15 @@ public String getReason() { } String hierarchical = ""; - if (symmLevels > 1) { + if (axes.getNumLevels() > 1) { hierarchical = String.format("; Contains %d levels of symmetry", - symmLevels); + axes.getNumLevels()); } // 5. Symmetric. // a. Open. Give # repeats (1n0r.A) - if (type == SymmetryType.OPEN) { + if (axes.getElementaryAxis(0).getSymmType() == SymmetryType.OPEN) { return String.format("Contains %d open repeats (TM=%.2f)%s", - getSymmOrder(), tm, hierarchical); + getNumRepeats(), tm, hierarchical); } // b. Closed, non-hierarchical (1itb.A) // c. Closed, heirarchical (4gcr) diff --git a/biojava-structure/src/main/java/org/biojava/nbio/structure/symmetry/internal/SymmOptimizer.java b/biojava-structure/src/main/java/org/biojava/nbio/structure/symmetry/internal/SymmOptimizer.java index b10e41a00b..6f24fefa6d 100644 --- a/biojava-structure/src/main/java/org/biojava/nbio/structure/symmetry/internal/SymmOptimizer.java +++ b/biojava-structure/src/main/java/org/biojava/nbio/structure/symmetry/internal/SymmOptimizer.java @@ -351,7 +351,7 @@ private void updateMultipleAlignment() throws StructureException, throw new RefinerFailedException( "Optimization converged to length 0"); - SymmetryTools.updateSymmetryTransformation(axes, msa, atoms); + SymmetryTools.updateSymmetryTransformation(axes, msa); } /** diff --git a/biojava-structure/src/main/java/org/biojava/nbio/structure/symmetry/internal/SymmetryAxes.java b/biojava-structure/src/main/java/org/biojava/nbio/structure/symmetry/internal/SymmetryAxes.java index fc0af1f14e..1f09fd2f70 100644 --- a/biojava-structure/src/main/java/org/biojava/nbio/structure/symmetry/internal/SymmetryAxes.java +++ b/biojava-structure/src/main/java/org/biojava/nbio/structure/symmetry/internal/SymmetryAxes.java @@ -21,19 +21,33 @@ package org.biojava.nbio.structure.symmetry.internal; import java.util.ArrayList; -import java.util.HashMap; +import java.util.Arrays; +import java.util.Iterator; import java.util.List; -import java.util.Map; import javax.vecmath.Matrix4d; -import org.biojava.nbio.structure.symmetry.utils.SymmetryTools; +import org.biojava.nbio.structure.align.multiple.MultipleAlignment; +import org.biojava.nbio.structure.align.util.RotationAxis; +import org.biojava.nbio.structure.symmetry.internal.CESymmParameters.SymmetryType; /** * Data Structure that stores all the symmetry axis that describe * the symmetry of a structure. Generalizes to all types of symmetry, * the classic ones (Cn, Dn) and any hierarchical or local symmetries. *

+ * Hierarchical symmetry can be visualized as a tree, where each level + * has a fixed branching factor. Each level of the tree is associated + * with a transformation operator, whose order determines the degree of + * nodes at that level of the tree. Leaves of the tree implicitly + * represent aligned repeats (indexed 0 to n-1), so care must be taken to + * keep external references to the repeats (e.g. rows of a + * {@link MultipleAlignment} in the same order implied by the tree. + *

+ * Each node of the tree specifies an alignment between those repeats + * below each of its children. It is also associated with a symmetry axis, + * which is calculated based on the associated operator as well as any parent + * operators. * It also stores the parts of the structure (symmetric units) involved * in each axis, in addition to the way to calculate them. *

@@ -47,49 +61,138 @@ * */ public class SymmetryAxes { - - /** - * List of all symmetry axis. They are sorted from higher to lower - * in the symmetry hierarchy, where higher means that they apply - * more globally and lower means that they apply to a local region - * of the higher axis division. + /* + * Implementation note: The tree is a nice explanation and a good image + * for developing algorithms, but it is not constructed explicitly. + * Instead, we just store one elementary axis for each level and reconstruct + * which operators apply to a particular leaf based on that leaf's index. */ - private List axes; - + /** - * Tree of the symmetry axes hierarchy of a structure. Every index - * is the axis index and the integer stored means the number of parts - * this axis divides the structure in. + * Represents an axis of symmetry + * @author Spencer Bliven + * */ - private List tree; + public static class Axis { + private Matrix4d operator; + private int order; + private SymmetryType symmType; + private int level; + //private int indexInLevel; + private int firstRepeat; + private RotationAxis rotAxis; - /** - * Matrix of size [repeats][axes]. The first index of the matrix - * indicates which repeat is considered, and the second index - * indicates which axis. The integer stored means how many times - * the transformation has to be applied to the repeat, and a value - * of 0 means that this repeat is not affected by the axis. - */ - private List> repeatTransforms; + public Axis(Matrix4d operator, int order, SymmetryType type, int level, int firstRepeat) { + if (order < 2) { + throw new IllegalArgumentException("A symmetry axis should divide a structure in > 2 parts"); + } + if(type != SymmetryType.OPEN && type != SymmetryType.CLOSED) { + throw new IllegalArgumentException("Invalid symmetry type. Only OPEN and CLOSED are allowed"); + } + this.operator = operator; + this.order = order; + this.symmType = type; + setLevel(level); + setFirstRepeat(firstRepeat); + rotAxis = null; + } + /** + * Get the transformation operator for this axis as an homogeneous matrix + * @return the transformation operator + */ + public Matrix4d getOperator() { + return operator; + } + public void setOperator(Matrix4d op) { + this.operator = op; + } + /** + * Get the order of this axis (closed symm) or the number of repeats + * (open symm) + * @return the order + */ + public int getOrder() { + return order; + } + /** + * @return the symmType (OPEN or CLOSED only) + */ + public SymmetryType getSymmType() { + return symmType; + } + + /** + * Get the transformation operator as a rotation axis. For open + * symmetry this will have a non-zero screw component. + * @return a RotationAxis for this Axis + */ + public RotationAxis getRotationAxis() { + if( rotAxis == null) { + rotAxis = new RotationAxis(operator); + } + return rotAxis; + } + /** + * @return The level of this axis within it's parent hierarchy, or -1 if unset + */ + public int getLevel() { + return level; + } + /** + * + * @param level The level of this axis within it's parent hierarchy. Must be positive + */ + public void setLevel(int level) { + if(level < 0) throw new IndexOutOfBoundsException("Level must be positive"); + this.level = level; + } +// /** +// * Each level can contain multiple equivalent axes. This index is +// * used to distinguish them. +// * @return the index of this axis relative to others at the same level +// */ +// public int getIndexInLevel() { +// return indexInLevel; +// } +// /** +// * +// * @param indexInLevel the index of this axis relative to others at the same level +// */ +// public void setIndexInLevel(int indexInLevel) { +// if( indexInLevel < 0 || getOrder() <= indexInLevel ) +// throw new IndexOutOfBoundsException("Invalid index for order "+getOrder()); +// this.indexInLevel = indexInLevel; +// } + /** + * Get the index of the first repeat used by this axis + * @return the firstRepeat + */ + public int getFirstRepeat() { + return firstRepeat; + } + /** + * @param firstRepeat the index of the first repeat used by this axis + */ + public void setFirstRepeat(int firstRepeat) { + this.firstRepeat = firstRepeat; + } + } + /** - * The list of integers defines which repeats are involved in this axis - * and how the axis transformation is computed. The list has size 2 for - * the first index and any size for the second index. Describes that all - * repeats in the first list superimposed to all repeats of the second - * list should generate the axis transformation. + * List of all symmetry axis. They are sorted from higher to lower + * in the symmetry hierarchy, where higher means that they apply + * more globally and lower means that they apply to a local region + * of the higher axis division. */ - private Map>> mapAxisRepeats; + private final List axes; /** * Constructor. * Initializes variables only. */ public SymmetryAxes(){ - axes = new ArrayList(); - mapAxisRepeats = new HashMap>>(); - repeatTransforms = new ArrayList>(); - tree = new ArrayList(); + axes = new ArrayList<>(); } /** @@ -105,7 +208,10 @@ public SymmetryAxes(){ * * @throws IllegalArgumentException if the repeat relation is in the * wrong format: should be double List of equal sizes. + * @deprecated Use {@link #addAxis(Matrix4d, int, SymmetryType)} instead. + * Repeats and Superposition are now inferred automatically. */ + @Deprecated public void addAxis(Matrix4d axis, List> superposition, List repeats, Integer division) { @@ -117,41 +223,65 @@ public void addAxis(Matrix4d axis, List> superposition, throw new IllegalArgumentException( "Wrong superposition format: not equal List sizes."); } - if (division < 2) throw new IllegalArgumentException( - "A symmetry axis should divide a structure in > 2 parts"); - - axes.add(axis); - tree.add(division); - - //Extend the double List by the necessary rows - while (repeatTransforms.size() < repeats.size()){ - List list = new ArrayList(); - for (int a=0; a superPos1 = superposition.get(1); + if(superPos1.get(0) > superPos1.get(superPos1.size()-1)) { + type = SymmetryType.CLOSED; + } else { + type = SymmetryType.OPEN; } + this.addAxis(axis,division,type); + } + /** + * Adds a new axis of symmetry to the bottom level of the tree + * + * @param axis the new axis of symmetry found + * @param order number of parts that this axis divides the structure in + * @param type indicates whether the axis has OPEN or CLOSED symmetry + */ + public void addAxis(Matrix4d axis, int order, SymmetryType type) { + axes.add(new Axis(axis,order,type,axes.size(),0)); + } - //Check that the repeat indices match - for (int c=0; c<2; c++){ - for (int p=0; prepeatTransforms.size()){ - throw new IllegalArgumentException( - "Repeat indicex in superposition out of bounds"); - } - } + /** + * Return a list giving the number of times each axis must be applied + * to generate the given repeat. + *

+ * For instance, for a D3 case getAxisCounts(4) would return [2,0], + * indicating that repeat 4 is generated by two applications of the 3-fold + * axis followed by 0 applications of the two-fold axis. + * + * @param repeat Index of the desired repeat + * @return array of the same length as axes giving the number of times + * to apply each axis. + */ + private int[] getAxisCounts(int repeat) { + int[] counts = new int[getNumLevels()]; + + for(int i = counts.length-1; i >= 0; i--) { + int d = axes.get(i).getOrder(); + counts[i] = repeat % d; + repeat /= d; } - mapAxisRepeats.put(axes.size()-1, superposition); + assert repeat == 0 : "Invalid repeat index"; + return counts; } +// /** +// * Inverse of {@link #getAxisCounts(int)}; Calculates the repeat for a +// * particular number of applications of each axis +// * @param counts Number of times to apply each axis +// * @return Repeat index +// */ +// private int getRepeatIndex(int[] counts) { +// int repeat = 0; +// for(int i = 0; i< counts.length; i++) { +// repeat += counts[i]*axes.get(i).getOrder(); +// } +// return repeat; +// } /** * Updates an axis of symmetry, after the superposition changed. * @@ -159,62 +289,194 @@ public void addAxis(Matrix4d axis, List> superposition, * @param newAxis */ public void updateAxis(Integer index, Matrix4d newAxis){ - axes.set(index, newAxis); + axes.get(index).setOperator(newAxis); } /** - * Return all elementary axes of symmetry of the structure, that is, + * Return the operator for all elementary axes of symmetry of the structure, that is, * the axes stored in the List as unique and from which all the symmetry * axes are constructed. * * @return axes elementary axes of symmetry. */ public List getElementaryAxes(){ + List ops = new ArrayList(getNumLevels()); + for(Axis axis : axes) { + ops.add(axis.getOperator()); + } + return ops; + } + + /** + * Return all elementary axes of symmetry of the structure, that is, + * the axes stored in the List as unique and from which all the symmetry + * axes are constructed. + * + * @return axes elementary axes of symmetry. + */ + public List getElementaryAxesObjects() { return axes; } /** - * Return the repeat superposition relation needed to obtain the - * axis of symmetry (which repeats and in which order have to be - * superimposed to obtain the axis). + * Get the indices of participating repeats in Cauchy two-line form. + *

+ * Returns two lists of the same length. + * The first gives a list of all repeat indices which are aligned + * at the specified level of symmetry (e.g. 0 through the degree of this level). + * The second list gives the corresponding repeats after applying the + * operator once. * - * @param index the axis index + * @param level the axis index * @return the double List of repeat relations, or null if the - * axis is not already stored. + * level is invalid + * @see #getRepeatsCyclicForm(int, int) for an equivalent specification with half the memory */ - public List> getRepeatRelation(Integer index){ - return mapAxisRepeats.get(index); + public List> getRepeatRelation(int level){ + return getRepeatRelation(level,0); } + public List> getRepeatRelation(Axis axis){ + return getRepeatRelation(axis.getLevel(),axis.getFirstRepeat()); + } + + public List> getRepeatRelation(int level, int firstRepeat) { + Axis axis = axes.get(level); + int m = getNumRepeats(level+1);//size of the children + int d = axis.getOrder(); // degree of this node + int n = m*d; // number of repeats included + if(firstRepeat % n != 0) + throw new IllegalArgumentException(String.format("Repeat %d cannot start a block at level %s of this tree",firstRepeat,level)); + if(axis.getSymmType() == SymmetryType.OPEN) { + n -= m; // leave off last child for open symm + } + List repeats = new ArrayList<>(n); + List equiv = new ArrayList<>(n); + for(int i=0;i + * Each inner list gives a set of equivalent repeats and should have length + * equal to the order of the axis' operator. + * @param level + * @param firstRepeat + * @return + */ + public List> getRepeatsCyclicForm(int level, int firstRepeat) { + Axis axis = axes.get(level); + int m = getNumRepeats(level+1);//size of the children + int d = axis.getOrder(); // degree of this node + int n = m*d; // number of repeats included + if(firstRepeat % n != 0) { + throw new IllegalArgumentException(String.format("Repeat %d cannot start a block at level %s of this tree",firstRepeat,level)); + } + if(axis.getSymmType() == SymmetryType.OPEN) { + n -= m; // leave off last child for open symm + } + + List> repeats = new ArrayList<>(m); + for(int i=0;i cycle = new ArrayList<>(d); + for(int j=0;j> getRepeatsCyclicForm(Axis axis) { + return getRepeatsCyclicForm(axis.getLevel(),axis.getFirstRepeat()); + } + public List> getRepeatsCyclicForm(int level) { + return getRepeatsCyclicForm(level,0); + } + public String getRepeatsCyclicForm(Axis axis, List repeats) { + if(repeats.size() != getNumRepeats()) { + throw new IllegalArgumentException("Mismatch in the number of repeats"); + } + return getRepeatsCyclicForm(getRepeatsCyclicForm(axis), repeats); + } + public static String getRepeatsCyclicForm(List> cycleForm, List repeats) { + StringBuilder str = new StringBuilder(); + for(List cycle : cycleForm) { + str.append("("); + Iterator cycleIt = cycle.iterator(); + str.append(repeats.get(cycleIt.next())); //should be at least one + while(cycleIt.hasNext()) { + str.append(";") + .append(repeats.get( cycleIt.next() )); + } + str.append(")"); + } + return str.toString(); + } + + /** + * Return the transformation that needs to be applied to a + * repeat in order to superimpose onto repeat 0. * * @param repeat the repeat index * @return transformation matrix for the repeat */ public Matrix4d getRepeatTransform(int repeat){ - List allTransforms = new ArrayList(); Matrix4d transform = new Matrix4d(); transform.setIdentity(); - for (int a=0; a=0; t--) { + if( counts[t] == 0 ) + continue; + Matrix4d axis = new Matrix4d(axes.get(t).getOperator()); + for(int i=0;i0) allTransforms.add(clone); - } - //Multiply the matrices in the inverse order as they have to be applied - //for (int t=0; t=0; t--){ - transform.mul(allTransforms.get(t)); } + return transform; + } + + /** + * Return the transformation that needs to be applied to + * repeat x in order to superimpose onto repeat y. + * + * @param x the first repeat index (transformed) + * @param y the second repeat index (fixed) + * @return transformation matrix for the repeat x + */ + public Matrix4d getRepeatTransform(int x, int y){ + Matrix4d transform = new Matrix4d(); + transform.setIdentity(); + + int[] iCounts = getAxisCounts(x); + int[] jCounts = getAxisCounts(y); + + int[] counts = new int[iCounts.length]; + for (int k = 0; k < iCounts.length; k++) + counts[k] = iCounts[k] - jCounts[k]; + + for(int t = counts.length-1; t>=0; t--) { + if(counts[t] == 0) + continue; + if (counts[t] > 0) { + Matrix4d axis = new Matrix4d(axes.get(t).getOperator()); + for(int i=0;i getSymmetryAxes(){ + public List getSymmetryAxes(){ - List symmAxes = new ArrayList(); + List symmAxes = new ArrayList<>(); - //For every repeat do - for (int su=0; su symmAxes, Matrix4d prior, int level, int firstRepeat) { + if(level >= getNumLevels() ) { + return; + } - //Consider all the axes, in the inverse order - for (int t=repeatTransforms.get(su).size()-1; t>=0; t--){ - int repeats = repeatTransforms.get(su).get(t); - Matrix4d clone = (Matrix4d) axes.get(t).clone(); - Matrix4d invert = (Matrix4d) clone.clone(); - invert.invert(); + Axis elem = axes.get(level); + Matrix4d elemOp = elem.getOperator(); - //Do for every repeat - for (int n=0; n A + // prior maps I -> A and J -> B + // want J -> I = J -> B -> A <- I= inv(prior) * elementary * prior + Matrix4d currAxisOp = new Matrix4d(prior); + currAxisOp.invert(); + currAxisOp.mul(elemOp); + currAxisOp.mul(prior); + Axis currAxis = new Axis(currAxisOp,elem.getOrder(),elem.getSymmType(),level,firstRepeat); + symmAxes.add(currAxis); + + //Remember that all degrees are at least 2 + getSymmetryAxes(symmAxes,prior,level+1,firstRepeat); + //New prior is elementary^d*prior + Matrix4d newPrior = new Matrix4d(elemOp); + newPrior.mul(prior); + int childSize = getNumRepeats(level+1); + getSymmetryAxes(symmAxes,newPrior,level+1,firstRepeat+childSize); + for(int d=2;d= degrees.get(level-1) ) +// throw new IndexOutOfBoundsException("Axis number out of bounds"); +// // Convert axisNum into a count of +// +// } + /** + * Get the number of repeats. This is equal to the product of all degrees. + * @return Number of repeats (leaves of the tree). + */ + public int getNumRepeats() { + return getNumRepeats(0); + } - //Ensure the axis are not equivalent - for (int a=0; a getFirstRepeats(int level) { + List firstRepeats = new ArrayList(); + int m = getNumRepeats(level+1); //size of the level + int d = axes.get(level).getOrder(); //degree of this level + int n = m*d; // number of repeats included in each axis + for (int firstRepeat = 0; firstRepeat < getNumRepeats(); firstRepeat+=n) + firstRepeats.add(firstRepeat); + return firstRepeats; + } + + public Axis getElementaryAxis(int level) { + return axes.get(level); + } + + public int getNumLevels() { + return axes.size(); + } + } diff --git a/biojava-structure/src/main/java/org/biojava/nbio/structure/symmetry/utils/SymmetryTools.java b/biojava-structure/src/main/java/org/biojava/nbio/structure/symmetry/utils/SymmetryTools.java index 697533690f..417a7dde95 100644 --- a/biojava-structure/src/main/java/org/biojava/nbio/structure/symmetry/utils/SymmetryTools.java +++ b/biojava-structure/src/main/java/org/biojava/nbio/structure/symmetry/utils/SymmetryTools.java @@ -30,6 +30,7 @@ import javax.vecmath.Point3d; import org.biojava.nbio.structure.Atom; +import org.biojava.nbio.structure.Calc; import org.biojava.nbio.structure.Chain; import org.biojava.nbio.structure.ChainImpl; import org.biojava.nbio.structure.Group; @@ -493,32 +494,31 @@ public static UndirectedGraph buildSymmetryGraph( /** * Method that converts the symmetric units of a structure into different - * chains, so that internal symmetry can be translated into quaternary. - *

- * Application: obtain the internal symmetry axis with the quaternary - * symmetry code in biojava or calculate independent repeat properties. + * structures, so that they can be individually visualized. * * @param symmetry * CeSymmResult - * @return Structure with different chains for every symmetric unit + * @throws StructureException + * @result List of structures, by repeat index sequentially + * */ - public static Structure getQuaternaryStructure(CeSymmResult symmetry) { + public static List divideStructure(CeSymmResult symmetry) + throws StructureException { if (!symmetry.isRefined()) throw new IllegalArgumentException("The symmetry result " + "is not refined, repeats cannot be defined"); - Atom[] atoms = symmetry.getAtoms(); - - Structure symm = new StructureImpl(); - symm.setStructureIdentifier(symmetry.getStructureId()); - symm.setChains(new ArrayList()); - char chainID = 'A'; + int order = symmetry.getMultipleAlignment().size(); + Atom[] atoms = StructureTools.cloneAtomArray(symmetry.getAtoms()); + List repeatsId = symmetry.getRepeatsID(); + List repeats = new ArrayList(order); // Create new structure containing the repeat atoms - for (int i = 0; i < symmetry.getMultipleAlignment().size(); i++) { + for (int i = 0; i < order; i++) { - Chain newCh = new ChainImpl(); + Structure s = new StructureImpl(); + s.setStructureIdentifier(repeatsId.get(i)); Block align = symmetry.getMultipleAlignment().getBlock(0); @@ -528,16 +528,17 @@ public static Structure getQuaternaryStructure(CeSymmResult symmetry) { Atom[] repeat = Arrays.copyOfRange(atoms, res1, res2 + 1); + Chain newCh = new ChainImpl(); + newCh.setChainID(repeat[0].getGroup().getChainId()); + for (int k = 0; k < repeat.length; k++) { Group g = (Group) repeat[k].getGroup().clone(); newCh.addGroup(g); } - newCh.setChainID(chainID + ""); - chainID++; - symm.addChain(newCh); - + s.addChain(newCh); + repeats.add(s); } - return symm; + return repeats; } /** @@ -593,22 +594,16 @@ public static MultipleAlignment toRepeatsAlignment(CeSymmResult result) MultipleAlignment msa = result.getMultipleAlignment(); MultipleAlignmentEnsemble newEnsemble = msa.getEnsemble().clone(); - newEnsemble.setStructureIdentifiers(result.getRepeatsID()); - // Modify atom arrays to include the repeat atoms only - List atomArrays = new ArrayList(); - Structure divided = SymmetryTools.getQuaternaryStructure(result); + List repSt = SymmetryTools.divideStructure(result); MultipleAlignment repeats = newEnsemble.getMultipleAlignment(0); Block block = repeats.getBlock(0); + List atomArrays = new ArrayList(); + + for (Structure s : repSt) + atomArrays.add(StructureTools.getRepresentativeAtomArray(s)); - for (int i = 0; i < result.getMultipleAlignment().size(); i++) { - Structure newStr = new StructureImpl(); - Chain newCh = divided.getChain(i); - newStr.addChain(newCh); - Atom[] repeat = StructureTools.getRepresentativeAtomArray(newCh); - atomArrays.add(repeat); - } newEnsemble.setAtomArrays(atomArrays); for (int su = 0; su < block.size(); su++) { @@ -695,6 +690,7 @@ public static MultipleAlignment fromAFP(AFPChain symm, Atom[] atoms) * error allowed in the axis comparison * @return true if equivalent, false otherwise */ + @Deprecated public static boolean equivalentAxes(Matrix4d axis1, Matrix4d axis2, double epsilon) { @@ -735,10 +731,10 @@ public static QuatSymmetryResults getQuaternarySymmetry(CeSymmResult result) throws StructureException { // Obtain the clusters of aligned Atoms and repeat variables - MultipleAlignment repeats = SymmetryTools.toRepeatsAlignment(result); - List alignedCA = repeats.getAtomArrays(); - List corePos = MultipleAlignmentTools.getCorePositions(repeats - .getBlock(0)); + List alignedCA = result.getMultipleAlignment().getAtomArrays(); + MultipleAlignment msa = result.getMultipleAlignment(); + List corePos = MultipleAlignmentTools.getCorePositions(result + .getMultipleAlignment().getBlock(0)); List caCoords = new ArrayList(); List folds = new ArrayList(); @@ -753,8 +749,7 @@ public static QuatSymmetryResults getQuaternarySymmetry(CeSymmResult result) for (int str = 0; str < alignedCA.size(); str++) { Atom[] array = alignedCA.get(str); List points = new ArrayList(); - List alignedRes = repeats.getBlock(0).getAlignRes() - .get(str); + List alignedRes = msa.getBlock(0).getAlignRes().get(str); for (int pos = 0; pos < alignedRes.size(); pos++) { Integer residue = alignedRes.get(pos); if (residue == null) @@ -802,6 +797,7 @@ else if (!corePos.contains(pos)) * the symmetry alignment * @return true if the alignment is refined */ + @Deprecated public static boolean isRefined(MultipleAlignment symm) { if (symm.getBlocks().size() > 1) { @@ -841,6 +837,7 @@ public static boolean isRefined(MultipleAlignment symm) { * @return * @throws StructureException */ + @Deprecated public static boolean isSignificant(MultipleAlignment msa, double symmetryThreshold) throws StructureException { @@ -899,36 +896,42 @@ public static List getGroups(Atom[] rAtoms) { * SymmetryAxes object. It will be modified. * @param msa * MultipleAlignment. It will be modified. - * @param atoms - * Atom array of the structure */ public static void updateSymmetryTransformation(SymmetryAxes axes, - MultipleAlignment msa, Atom[] atoms) throws StructureException { + MultipleAlignment msa) throws StructureException { List> block = msa.getBlocks().get(0).getAlignRes(); int length = block.get(0).size(); if (axes != null) { - for (int t = 0; t < axes.getElementaryAxes().size(); t++) { + for (int level = 0; level < axes.getNumLevels(); level++) { - Matrix4d axis = axes.getElementaryAxes().get(t); - List chain1 = axes.getRepeatRelation(t).get(0); - List chain2 = axes.getRepeatRelation(t).get(1); - - // Calculate the aligned atom arrays + // Calculate the aligned atom arrays to superimpose List list1 = new ArrayList(); List list2 = new ArrayList(); - for (int pair = 0; pair < chain1.size(); pair++) { - int p1 = chain1.get(pair); - int p2 = chain2.get(pair); - - for (int k = 0; k < length; k++) { - Integer pos1 = block.get(p1).get(k); - Integer pos2 = block.get(p2).get(k); - if (pos1 != null && pos2 != null) { - list1.add(atoms[pos1]); - list2.add(atoms[pos2]); + for (int firstRepeat : axes.getFirstRepeats(level)) { + + Matrix4d transform = axes.getRepeatTransform(firstRepeat); + + List> relation = axes.getRepeatRelation( + level, firstRepeat); + + for (int index = 0; index < relation.get(0).size(); index++) { + int p1 = relation.get(0).get(index); + int p2 = relation.get(1).get(index); + + for (int k = 0; k < length; k++) { + Integer pos1 = block.get(p1).get(k); + Integer pos2 = block.get(p2).get(k); + if (pos1 != null && pos2 != null) { + Atom a = (Atom) msa.getAtomArrays().get(p1)[pos1].clone(); + Atom b = (Atom) msa.getAtomArrays().get(p2)[pos2].clone(); + Calc.transform(a, transform); + Calc.transform(b, transform); + list1.add(a); + list2.add(b); + } } } } @@ -939,8 +942,8 @@ public static void updateSymmetryTransformation(SymmetryAxes axes, // Calculate the new transformation information if (arr1.length > 0 && arr2.length > 0) { SVDSuperimposer svd = new SVDSuperimposer(arr1, arr2); - axis = svd.getTransformation(); - axes.updateAxis(t, axis); + Matrix4d axis = svd.getTransformation(); + axes.updateAxis(level, axis); } // Get the transformations from the SymmetryAxes @@ -977,4 +980,31 @@ public static void updateSymmetryScores(MultipleAlignment symm) symm.putScore(MultipleAlignmentScorer.RMSD, rmsd); } + /** + * Returns the representative Atom Array of the first model, if the + * structure is NMR, or the Array for each model, if it is a biological + * assembly with multiple models. + * + * @param structure + * @return representative Atom[] + */ + public static Atom[] getRepresentativeAtoms(Structure structure) { + + if (structure.isNmr()) + return StructureTools.getRepresentativeAtomArray(structure); + + else { + + // Get Atoms of all models + List atomList = new ArrayList(); + for (int m = 0; m < structure.nrModels(); m++) { + for (Chain c : structure.getModel(m)) + atomList.addAll(Arrays.asList(StructureTools + .getRepresentativeAtomArray(c))); + } + return atomList.toArray(new Atom[0]); + } + + } + } diff --git a/biojava-structure/src/main/resources/org/biojava/nbio/structure/bond_distance_limits.cif.gz b/biojava-structure/src/main/resources/org/biojava/nbio/structure/bond_distance_limits.cif.gz new file mode 100644 index 0000000000..1401654e26 Binary files /dev/null and b/biojava-structure/src/main/resources/org/biojava/nbio/structure/bond_distance_limits.cif.gz differ diff --git a/biojava-structure/src/main/resources/org/biojava/nbio/structure/standardaminos.pdb b/biojava-structure/src/main/resources/org/biojava/nbio/structure/standardaminos.pdb deleted file mode 100644 index 78f8524785..0000000000 --- a/biojava-structure/src/main/resources/org/biojava/nbio/structure/standardaminos.pdb +++ /dev/null @@ -1,167 +0,0 @@ -ATOM 1 N ALA 1 0.494 1.023 2.147 1 24.49 -ATOM 2 CA ALA 1 0.525 1.231 0.716 1 23.9 -ATOM 3 C ALA 1 -0.304 2.448 0.321 1 25.03 -ATOM 4 O ALA 1 -1.387 2.694 0.877 1 24.08 -ATOM 5 CB ALA 1 0.000 0.000 0.000 1 21.78 -ATOM 1 N ARG 2 0.925 -2.028 1.045 1 22.4 -ATOM 2 CA ARG 2 1.051 -1.110 -0.098 1 26.71 -ATOM 3 C ARG 2 2.426 -0.479 -0.387 1 27.34 -ATOM 4 O ARG 2 2.847 -0.401 -1.545 1 28.25 -ATOM 5 CB ARG 2 0.000 0.000 0.000 1 28.07 -ATOM 6 CG ARG 2 -0.504 0.455 -1.363 1 34.03 -ATOM 7 CD ARG 2 -0.933 1.930 -1.348 1 38.88 -ATOM 8 NE ARG 2 -2.373 2.147 -1.237 1 41.65 -ATOM 9 CZ ARG 2 -3.061 2.912 -2.079 1 45.41 -ATOM 10 NH1 ARG 2 -2.438 3.516 -3.083 1 45.25 -ATOM 11 NH2 ARG 2 -4.371 3.066 -1.933 1 48.63 -ATOM 1 N ASN 3 1.486 -0.416 1.992 1 48.91 -ATOM 2 CA ASN 3 1.423 0.110 0.619 1 49.54 -ATOM 3 C ASN 3 1.842 1.587 0.732 1 49.06 -ATOM 4 O ASN 3 2.799 1.859 1.507 1 49.25 -ATOM 5 CB ASN 3 0.000 0.000 0.000 1 49.64 -ATOM 6 CG ASN 3 0.014 0.096 -1.537 1 50.26 -ATOM 7 OD1 ASN 3 1.082 0.141 -2.156 1 51.27 -ATOM 8 ND2 ASN 3 -1.172 0.096 -2.154 1 50.95 -ATOM 1 N ASP 4 -0.024 2.139 1.216 1 31.73 -ATOM 2 CA ASP 4 0.796 0.984 0.867 1 32.49 -ATOM 3 C ASP 4 2.073 1.394 0.128 1 31.55 -ATOM 4 O ASP 4 2.317 0.937 -0.988 1 33.23 -ATOM 5 CB ASP 4 0.000 0.000 0.000 1 35 -ATOM 6 CG ASP 4 -1.157 -0.643 0.738 1 38.92 -ATOM 7 OD1 ASP 4 -1.115 -0.722 1.992 1 39.91 -ATOM 8 OD2 ASP 4 -2.111 -1.080 0.053 1 41.36 -ATOM 1 N CYS 5 0.553 1.877 1.446 1 21.01 -ATOM 2 CA CYS 5 0.356 1.481 0.057 1 22.79 -ATOM 3 C CYS 5 -0.764 2.272 -0.622 1 25.08 -ATOM 4 O CYS 5 -1.065 2.042 -1.802 1 24.55 -ATOM 5 CB CYS 5 0.000 0.000 0.000 1 25.21 -ATOM 6 SG CYS 5 -1.474 -0.396 0.997 1 21.67 -ATOM 1 N GLN 6 2.420 -0.279 0.030 1 24.67 -ATOM 2 CA GLN 6 1.330 0.521 -0.519 1 26.3 -ATOM 3 C GLN 6 1.458 1.986 -0.138 1 26.72 -ATOM 4 O GLN 6 1.693 2.319 1.035 1 24.44 -ATOM 5 CB GLN 6 0.000 0.000 0.000 1 31.06 -ATOM 6 CG GLN 6 -1.209 0.562 -0.709 1 37.02 -ATOM 7 CD GLN 6 -1.535 -0.211 -1.959 1 41.56 -ATOM 8 OE1 GLN 6 -1.658 0.360 -3.038 1 44.84 -ATOM 9 NE2 GLN 6 -1.692 -1.525 -1.821 1 44.22 -ATOM 1 N GLU 7 1.408 -2.006 -0.385 1 40.19 -ATOM 2 CA GLU 7 0.232 -1.252 -0.876 1 44.66 -ATOM 3 C GLU 7 0.028 -0.871 -2.343 1 46.61 -ATOM 4 O GLU 7 -0.799 -1.486 -3.026 1 48.2 -ATOM 5 CB GLU 7 0.000 0.000 0.000 1 44.57 -ATOM 6 CG GLU 7 1.190 0.964 0.119 1 45.57 -ATOM 7 CD GLU 7 1.024 1.925 1.283 1 47.38 -ATOM 8 OE1 GLU 7 -0.068 2.466 1.505 1 48.84 -ATOM 9 OE2 GLU 7 2.106 2.154 2.031 1 46.92 -ATOM 1 N GLY 8 47.669 21.580 -36.546 1 21.01 -ATOM 2 CA GLY 8 46.339 21.191 -36.982 1 19.83 -ATOM 3 C GLY 8 46.235 20.890 -38.469 1 21.21 -ATOM 4 O GLY 8 46.924 21.503 -39.280 1 23.09 -ATOM 1 N HIS 9 -0.346 2.373 -0.412 1 13.88 -ATOM 2 CA HIS 9 -0.784 1.040 -0.785 1 14.13 -ATOM 3 C HIS 9 -2.270 0.972 -0.435 1 15.38 -ATOM 4 O HIS 9 -2.641 1.020 0.748 1 16.86 -ATOM 5 CB HIS 9 0.000 0.000 0.000 1 13.14 -ATOM 6 CG HIS 9 1.456 -0.006 -0.327 1 17.5 -ATOM 7 ND1 HIS 9 1.931 -0.575 -1.488 1 17.25 -ATOM 8 CD2 HIS 9 2.493 0.500 0.384 1 17.69 -ATOM 9 CE1 HIS 9 3.239 -0.400 -1.454 1 17.77 -ATOM 10 NE2 HIS 9 3.631 0.244 -0.345 1 17.75 -ATOM 1 N ILE 10 -0.417 -2.192 1.096 1 27.83 -ATOM 2 CA ILE 10 -0.325 -0.750 1.314 1 29.53 -ATOM 3 C ILE 10 -1.665 -0.275 1.884 1 30.09 -ATOM 4 O ILE 10 -2.727 -0.689 1.415 1 28.53 -ATOM 5 CB ILE 10 0.000 0.000 0.000 1 31.6 -ATOM 6 CG1 ILE 10 1.331 -0.514 -0.578 1 33.16 -ATOM 7 CG2 ILE 10 0.112 1.496 0.269 1 33.17 -ATOM 8 CD1 ILE 10 1.778 0.187 -1.868 1 29.72 -ATOM 1 N LEU 11 0.768 -1.147 -2.027 1 32.16 -ATOM 2 CA LEU 11 -0.420 -0.644 -1.333 1 34.34 -ATOM 3 C LEU 11 -1.389 0.304 -2.047 1 36.35 -ATOM 4 O LEU 11 -0.972 1.222 -2.760 1 36.15 -ATOM 5 CB LEU 11 0.000 0.000 0.000 1 33.58 -ATOM 6 CG LEU 11 0.686 -0.899 1.040 1 33.51 -ATOM 7 CD1 LEU 11 1.216 -0.065 2.194 1 34.43 -ATOM 8 CD2 LEU 11 -0.295 -1.940 1.540 1 33.17 -ATOM 1 N LYS 12 1.245 -0.586 -2.092 1 26.29 -ATOM 2 CA LYS 12 0.174 0.249 -1.517 1 27.52 -ATOM 3 C LYS 12 0.425 1.736 -1.757 1 26.38 -ATOM 4 O LYS 12 -0.516 2.509 -1.859 1 25.33 -ATOM 5 CB LYS 12 0.000 0.000 0.000 1 27.61 -ATOM 6 CG LYS 12 -0.549 -1.378 0.339 1 29.49 -ATOM 7 CD LYS 12 -1.376 -1.393 1.617 1 31.39 -ATOM 8 CE LYS 12 -0.556 -1.734 2.857 1 35.62 -ATOM 9 NZ LYS 12 0.535 -0.759 3.199 1 38.15 -ATOM 1 N MET 13 -0.112 -1.808 1.638 1 23.36 -ATOM 2 CA MET 13 -0.811 -0.634 1.147 1 22.77 -ATOM 3 C MET 13 -2.170 -1.118 0.657 1 21.54 -ATOM 4 O MET 13 -2.270 -2.218 0.112 1 21.32 -ATOM 5 CB MET 13 0.000 0.000 0.000 1 23.08 -ATOM 6 CG MET 13 -0.745 1.066 -0.782 1 25.23 -ATOM 7 SD MET 13 0.221 1.816 -2.120 1 25.75 -ATOM 8 CE MET 13 1.111 3.085 -1.200 1 24 -ATOM 1 N PHE 14 0.105 1.537 -1.930 1 14.86 -ATOM 2 CA PHE 14 0.834 1.043 -0.752 1 16.7 -ATOM 3 C PHE 14 2.160 0.325 -1.063 1 17.28 -ATOM 4 O PHE 14 2.348 -0.241 -2.141 1 17.93 -ATOM 5 CB PHE 14 0.000 0.000 0.000 1 16.18 -ATOM 6 CG PHE 14 -1.184 0.543 0.739 1 14.73 -ATOM 7 CD1 PHE 14 -1.016 1.241 1.930 1 13.41 -ATOM 8 CD2 PHE 14 -2.474 0.302 0.272 1 12.61 -ATOM 9 CE1 PHE 14 -2.132 1.689 2.651 1 14.44 -ATOM 10 CE2 PHE 14 -3.596 0.750 0.978 1 15.3 -ATOM 11 CZ PHE 14 -3.422 1.442 2.171 1 11.23 -ATOM 1 N PRO 15 2.003 0.020 1.242 1 15.52 -ATOM 2 CA PRO 15 0.545 -0.046 1.435 1 15.69 -ATOM 3 C PRO 15 0.034 -1.273 2.208 1 17.62 -ATOM 4 O PRO 15 -1.034 -1.211 2.839 1 18.07 -ATOM 5 CB PRO 15 0.000 0.000 0.000 1 19.34 -ATOM 6 CG PRO 15 1.118 0.656 -0.790 1 18.17 -ATOM 7 CD PRO 15 2.342 0.017 -0.191 1 15.87 -ATOM 1 N SER 16 -0.873 2.106 0.865 1 25.64 -ATOM 2 CA SER 16 -0.070 0.936 1.201 1 25.41 -ATOM 3 C SER 16 1.330 1.207 1.719 1 25.19 -ATOM 4 O SER 16 2.139 0.284 1.812 1 26.74 -ATOM 5 CB SER 16 0.000 0.000 0.000 1 24.96 -ATOM 6 OG SER 16 -1.312 -0.288 -0.461 1 27.94 -ATOM 1 N THR 17 -1.248 1.785 -1.139 1 26.68 -ATOM 2 CA THR 17 -0.956 1.197 0.166 1 26.57 -ATOM 3 C THR 17 -0.398 2.109 1.258 1 27.97 -ATOM 4 O THR 17 -0.107 1.647 2.365 1 31.7 -ATOM 5 CB THR 17 0.000 0.000 0.000 1 25.88 -ATOM 6 OG1 THR 17 1.179 0.416 -0.706 1 27.09 -ATOM 7 CG2 THR 17 -0.679 -1.099 -0.789 1 26.06 -ATOM 1 N TRP 18 -2.343 0.032 -0.696 1 18.87 -ATOM 2 CA TRP 18 -1.106 -0.700 -0.785 1 22.26 -ATOM 3 C TRP 18 -1.492 -1.984 -0.056 1 24.88 -ATOM 4 O TRP 18 -1.876 -1.925 1.105 1 25.15 -ATOM 5 CB TRP 18 0.000 0.000 0.000 1 24.8 -ATOM 6 CG TRP 18 1.349 -0.707 -0.051 1 30.99 -ATOM 7 CD1 TRP 18 2.377 -0.468 -0.933 1 30.98 -ATOM 8 CD2 TRP 18 1.820 -1.727 0.848 1 33.1 -ATOM 9 NE1 TRP 18 3.460 -1.268 -0.628 1 33.72 -ATOM 10 CE2 TRP 18 3.144 -2.047 0.460 1 34.08 -ATOM 11 CE3 TRP 18 1.255 -2.394 1.941 1 34.23 -ATOM 12 CZ2 TRP 18 3.916 -3.016 1.136 1 36.51 -ATOM 13 CZ3 TRP 18 2.022 -3.364 2.618 1 36.78 -ATOM 14 CH2 TRP 18 3.335 -3.659 2.212 1 38.2 -ATOM 1 N TYR 19 0.795 -2.206 0.735 1 22.33 -ATOM 2 CA TYR 19 -0.396 -1.400 0.492 1 20.17 -ATOM 3 C TYR 19 -1.258 -2.073 -0.559 1 21.55 -ATOM 4 O TYR 19 -0.744 -2.545 -1.569 1 22.81 -ATOM 5 CB TYR 19 0.000 0.000 0.000 1 20.33 -ATOM 6 CG TYR 19 0.498 0.934 1.084 1 16.84 -ATOM 7 CD1 TYR 19 -0.398 1.570 1.947 1 15.4 -ATOM 8 CD2 TYR 19 1.854 1.200 1.237 1 16.24 -ATOM 9 CE1 TYR 19 0.048 2.439 2.924 1 16.13 -ATOM 10 CE2 TYR 19 2.310 2.072 2.215 1 18.35 -ATOM 11 CZ TYR 19 1.398 2.690 3.058 1 18.09 -ATOM 12 OH TYR 19 1.835 3.555 4.042 1 18.05 -ATOM 1 N VAL 20 -0.471 2.212 1.093 1 25.64 -ATOM 2 CA VAL 20 -0.282 1.529 -0.188 1 24.65 -ATOM 3 C VAL 20 -1.485 1.721 -1.109 1 26.31 -ATOM 4 O VAL 20 -2.612 1.916 -0.639 1 25.36 -ATOM 5 CB VAL 20 0.000 0.000 0.000 1 22.87 -ATOM 6 CG1 VAL 20 1.274 -0.205 0.796 1 24.53 -ATOM 7 CG2 VAL 20 -1.148 -0.679 0.715 1 21.34 diff --git a/biojava-structure/src/main/resources/org/biojava/nbio/structure/standardaminos.pdb.gz b/biojava-structure/src/main/resources/org/biojava/nbio/structure/standardaminos.pdb.gz new file mode 100644 index 0000000000..992ef78592 Binary files /dev/null and b/biojava-structure/src/main/resources/org/biojava/nbio/structure/standardaminos.pdb.gz differ diff --git a/biojava-structure/src/test/java/org/biojava/nbio/structure/symmetry/internal/TestCeSymm.java b/biojava-structure/src/test/java/org/biojava/nbio/structure/symmetry/internal/TestCeSymm.java index 830e593d40..f9d829b5c3 100644 --- a/biojava-structure/src/test/java/org/biojava/nbio/structure/symmetry/internal/TestCeSymm.java +++ b/biojava-structure/src/test/java/org/biojava/nbio/structure/symmetry/internal/TestCeSymm.java @@ -55,7 +55,7 @@ public void testEasyCases() throws IOException, StructureException { CeSymmResult result = CeSymm.analyze(atoms); assertTrue(result.isSignificant()); - assertEquals(result.getSymmOrder(), orders[i]); + assertEquals(result.getNumRepeats(), orders[i]); } } } diff --git a/biojava-structure/src/test/java/org/biojava/nbio/structure/symmetry/internal/TestSymmetryAxes.java b/biojava-structure/src/test/java/org/biojava/nbio/structure/symmetry/internal/TestSymmetryAxes.java new file mode 100644 index 0000000000..779185479b --- /dev/null +++ b/biojava-structure/src/test/java/org/biojava/nbio/structure/symmetry/internal/TestSymmetryAxes.java @@ -0,0 +1,370 @@ +package org.biojava.nbio.structure.symmetry.internal; + +import static org.junit.Assert.*; + +import java.util.Arrays; +import java.util.List; + +import javax.vecmath.AxisAngle4d; +import javax.vecmath.Matrix4d; +import javax.vecmath.Point3d; +import javax.vecmath.Vector3d; + +import org.biojava.nbio.structure.symmetry.internal.CESymmParameters.SymmetryType; +import org.biojava.nbio.structure.symmetry.internal.SymmetryAxes.Axis; +import org.junit.Test; + + +public class TestSymmetryAxes { + + @Test + public void testClosedCase() { + // D4 case + SymmetryAxes axes = new SymmetryAxes(); + + // Level 1 is C4 along Z + Matrix4d r90 = new Matrix4d(); + r90.set(new AxisAngle4d(0, 0, 1, -Math.PI/2)); + axes.addAxis(r90, 4, SymmetryType.CLOSED); + + // Level 2 is C2 along X + Matrix4d r180 = new Matrix4d(); + r180.set(new AxisAngle4d(1, 0, 0, Math.PI)); + axes.addAxis(r180, 2, SymmetryType.CLOSED); + + assertEquals(2,axes.getElementaryAxes().size()); + + Matrix4d expectedEven = new Matrix4d(); + expectedEven.setIdentity(); + Matrix4d expectedOdd = new Matrix4d(r180); + assertEquals(expectedEven, axes.getRepeatTransform(0)); + assertEquals(expectedOdd, axes.getRepeatTransform(1)); + expectedEven.mul(r90); + expectedOdd.mul(r180,expectedEven); + assertEquals(expectedEven, axes.getRepeatTransform(2)); + assertEquals(expectedOdd, axes.getRepeatTransform(3)); + expectedEven.mul(r90); + expectedOdd.mul(r180,expectedEven); + assertEquals(expectedEven, axes.getRepeatTransform(4)); + assertEquals(expectedOdd, axes.getRepeatTransform(5)); + expectedEven.mul(r90); + expectedOdd.mul(r180,expectedEven); + assertEquals(expectedEven, axes.getRepeatTransform(6)); + assertEquals(expectedOdd, axes.getRepeatTransform(7)); + + // Test Cauchy Form + List> relation = Arrays.asList( + Arrays.asList(0,1,2,3,4,5,6,7), + Arrays.asList(2,3,4,5,6,7,0,1) + ); + assertEquals(relation,axes.getRepeatRelation(0)); + relation = Arrays.asList( + Arrays.asList(0,1), + Arrays.asList(1,0) + ); + assertEquals(relation,axes.getRepeatRelation(1)); + relation = Arrays.asList( + Arrays.asList(2,3), + Arrays.asList(3,2) + ); + assertEquals(relation,axes.getRepeatRelation(1,2)); + try { + axes.getRepeatRelation(2); + fail("Invalid level"); + } catch(IndexOutOfBoundsException e) {} + try { + axes.getRepeatRelation(1,1); + fail("Invalid firstRepeat"); + } catch(IllegalArgumentException e) {} + + // Test Cyclic Form + relation = Arrays.asList( + Arrays.asList(0,2,4,6), + Arrays.asList(1,3,5,7) + ); + assertEquals(relation,axes.getRepeatsCyclicForm(0)); + relation = Arrays.asList( + Arrays.asList(0,1) + ); + assertEquals(relation,axes.getRepeatsCyclicForm(1)); + relation = Arrays.asList( + Arrays.asList(2,3) + ); + assertEquals(relation,axes.getRepeatsCyclicForm(1,2)); + try { + axes.getRepeatsCyclicForm(2); + fail("Invalid level"); + } catch(IndexOutOfBoundsException e) {} + try { + axes.getRepeatsCyclicForm(1,1); + fail("Invalid firstRepeat"); + } catch(IllegalArgumentException e) {} + + + // Expected location of each repeat + Point3d[] repeats = new Point3d[] { + new Point3d(1,1,1), + new Point3d(1,-1,-1), + new Point3d(-1,1,1), + new Point3d(1,1,-1), + new Point3d(-1,-1,1), + new Point3d(-1,1,-1), + new Point3d(1,-1,1), + new Point3d(-1,-1,-1) + }; + // Inverse of (1,1,1) should give above points + for(int i=0;i<8;i++) { + Matrix4d m = axes.getRepeatTransform(i); + m.invert(); + Point3d x = new Point3d(repeats[0]); + m.transform(x); + assertTrue("Transformation "+i+"^-1 of "+repeats[0]+ "="+x+" not "+repeats[i],x.epsilonEquals(repeats[i], 1e-5)); + } + // Forward should map the above points onto the first one + for(int i=0;i<8;i++) { + Matrix4d m = axes.getRepeatTransform(i); + Point3d x = new Point3d(repeats[i]); + m.transform(x); + assertTrue("Transformation "+i+" of "+repeats[i]+ "="+x+" not 1,1,1",x.epsilonEquals(repeats[0], 1e-5)); + } + + Point3d x; + + List symmetryAxes = axes.getSymmetryAxes(); + assertEquals(5,symmetryAxes.size()); + int axisNum = 0; + // Repeat 2 -> 0 (90 deg around z) + x = new Point3d(repeats[2]); + symmetryAxes.get(axisNum).getOperator().transform(x); + assertTrue(String.format("SymmAxis %d of %s=%s not %s",axisNum,round(repeats[2]),round(x),round(repeats[0])),x.epsilonEquals(repeats[0], 1e-5)); + assertEquals(0,symmetryAxes.get(axisNum).getFirstRepeat()); + axisNum++; + // Repeat 1 -> 0 (180 deg around x) + x = new Point3d(repeats[1]); + symmetryAxes.get(axisNum).getOperator().transform(x); + assertTrue(String.format("SymmAxis %d of %s=%s not %s",axisNum,round(repeats[1]),round(x),round(repeats[0])),x.epsilonEquals(repeats[0], 1e-5)); + assertEquals(0,symmetryAxes.get(axisNum).getFirstRepeat()); + axisNum++; + // Repeat 3 -> 2 (180 deg around y) + x = new Point3d(repeats[3]); + symmetryAxes.get(axisNum).getOperator().transform(x); + assertTrue(String.format("SymmAxis %d of %s=%s not %s",axisNum,round(repeats[3]),round(x),round(repeats[2])),x.epsilonEquals(repeats[2], 1e-5)); + assertEquals(2,symmetryAxes.get(axisNum).getFirstRepeat()); + axisNum++; + // Repeat 5 -> 4 (180 deg around x) + x = new Point3d(repeats[5]); + symmetryAxes.get(axisNum).getOperator().transform(x); + assertTrue(String.format("SymmAxis %d of %s=%s not %s",axisNum,round(repeats[5]),round(x),round(repeats[4])),x.epsilonEquals(repeats[4], 1e-5)); + assertEquals(4,symmetryAxes.get(axisNum).getFirstRepeat()); + axisNum++; + // Repeat 7 -> 6 (180 deg around y) + x = new Point3d(repeats[7]); + symmetryAxes.get(axisNum).getOperator().transform(x); + assertTrue(String.format("SymmAxis %d of %s=%s not %s",axisNum,round(repeats[7]),round(x),round(repeats[6])),x.epsilonEquals(repeats[6], 1e-5)); + assertEquals(6,symmetryAxes.get(axisNum).getFirstRepeat()); + axisNum++; + } + private static Point3d round(Point3d p) { + return new Point3d(Math.round(p.x*100)/100.,Math.round(p.y*100)/100.,Math.round(p.z*100)/100.); + } + + @Test + public void testOpenCase() { + // D4 case + SymmetryAxes axes = new SymmetryAxes(); + + // Level 1 is R4 along X + Matrix4d t10 = new Matrix4d(); + t10.set(1,new Vector3d(-10,0,0)); + axes.addAxis(t10, 4, SymmetryType.OPEN); + + // Level 2 is C2 along X + Matrix4d r180 = new Matrix4d(); + r180.set(new AxisAngle4d(1, 0, 0, Math.PI)); + axes.addAxis(r180, 2, SymmetryType.CLOSED); + + assertEquals(2,axes.getElementaryAxes().size()); + + Matrix4d expectedEven = new Matrix4d(); + expectedEven.setIdentity(); + Matrix4d expectedOdd = new Matrix4d(r180); + assertEquals(expectedEven, axes.getRepeatTransform(0)); + assertEquals(expectedOdd, axes.getRepeatTransform(1)); + expectedEven.mul(t10); + expectedOdd.mul(r180,expectedEven); + assertEquals(expectedEven, axes.getRepeatTransform(2)); + assertEquals(expectedOdd, axes.getRepeatTransform(3)); + expectedEven.mul(t10); + expectedOdd.mul(r180,expectedEven); + assertEquals(expectedEven, axes.getRepeatTransform(4)); + assertEquals(expectedOdd, axes.getRepeatTransform(5)); + expectedEven.mul(t10); + expectedOdd.mul(r180,expectedEven); + assertEquals(expectedEven, axes.getRepeatTransform(6)); + assertEquals(expectedOdd, axes.getRepeatTransform(7)); + + // Test Cauchy Form + List> relation = Arrays.asList( + Arrays.asList(0,1,2,3,4,5), + Arrays.asList(2,3,4,5,6,7) + ); + assertEquals(relation,axes.getRepeatRelation(0)); + relation = Arrays.asList( + Arrays.asList(0,1), + Arrays.asList(1,0) + ); + assertEquals(relation,axes.getRepeatRelation(1)); + try { + axes.getRepeatRelation(2); + fail("Invalid level"); + } catch(IndexOutOfBoundsException e) {} + + // Test Cyclic Form + relation = Arrays.asList( + Arrays.asList(0,2,4,6), + Arrays.asList(1,3,5,7) + ); + assertEquals(relation,axes.getRepeatsCyclicForm(0)); + relation = Arrays.asList( + Arrays.asList(0,1) + ); + assertEquals(relation,axes.getRepeatsCyclicForm(1)); + relation = Arrays.asList( + Arrays.asList(2,3) + ); + assertEquals(relation,axes.getRepeatsCyclicForm(1,2)); + try { + axes.getRepeatsCyclicForm(2); + fail("Invalid level"); + } catch(IndexOutOfBoundsException e) {} + try { + axes.getRepeatsCyclicForm(1,1); + fail("Invalid firstRepeat"); + } catch(IllegalArgumentException e) {} + + + // Expected location of each repeat + Point3d[] repeats = new Point3d[] { + new Point3d(-15,1,1), + new Point3d(-15,-1,-1), + new Point3d( -5,1,1), + new Point3d( -5,-1,-1), + new Point3d( 5,1,1), + new Point3d( 5,-1,-1), + new Point3d( 15,1,1), + new Point3d( 15,-1,-1), + + }; + // Inverse of first point should give above points + for(int i=0;i<8;i++) { + Matrix4d m = axes.getRepeatTransform(i); + m.invert(); + Point3d x = new Point3d(repeats[0]); + m.transform(x); + assertTrue("Transformation "+i+"^-1 of "+repeats[0]+ "="+x+" not "+repeats[i],x.epsilonEquals(repeats[i], 1e-5)); + } + // Forward should map the above points onto the first one + for(int i=0;i<8;i++) { + Matrix4d m = axes.getRepeatTransform(i); + Point3d x = new Point3d(repeats[i]); + m.transform(x); + assertTrue("Transformation "+i+" of "+repeats[i]+ "="+x+" not "+repeats[0],x.epsilonEquals(repeats[0], 1e-5)); + } + + Point3d x; + + List symmetryAxes = axes.getSymmetryAxes(); + assertEquals(5,symmetryAxes.size()); + int axisNum = 0; + // Repeat 2 -> 0 (shift 1) + x = new Point3d(repeats[2]); + symmetryAxes.get(axisNum).getOperator().transform(x); + assertTrue(String.format("SymmAxis %d of %s=%s not %s",axisNum,round(repeats[2]),round(x),round(repeats[0])),x.epsilonEquals(repeats[0], 1e-5)); + axisNum++; + // All of these are actually equivalent + // Repeat 1 -> 0 (180 deg around x) + x = new Point3d(repeats[1]); + symmetryAxes.get(axisNum).getOperator().transform(x); + assertTrue(String.format("SymmAxis %d of %s=%s not %s",axisNum,round(repeats[1]),round(x),round(repeats[0])),x.epsilonEquals(repeats[0], 1e-5)); + axisNum++; + // Repeat 3 -> 2 (180 deg around x) + x = new Point3d(repeats[3]); + symmetryAxes.get(axisNum).getOperator().transform(x); + assertTrue(String.format("SymmAxis %d of %s=%s not %s",axisNum,round(repeats[3]),round(x),round(repeats[2])),x.epsilonEquals(repeats[2], 1e-5)); + axisNum++; + // Repeat 5 -> 4 (180 deg around x) + x = new Point3d(repeats[5]); + symmetryAxes.get(axisNum).getOperator().transform(x); + assertTrue(String.format("SymmAxis %d of %s=%s not %s",axisNum,round(repeats[5]),round(x),round(repeats[4])),x.epsilonEquals(repeats[4], 1e-5)); + axisNum++; + // Repeat 7 -> 6 (180 deg around x) + x = new Point3d(repeats[7]); + symmetryAxes.get(axisNum).getOperator().transform(x); + assertTrue(String.format("SymmAxis %d of %s=%s not %s",axisNum,round(repeats[7]),round(x),round(repeats[6])),x.epsilonEquals(repeats[6], 1e-5)); + axisNum++; + } + /** + * Test that the deprecated addAxis still works + */ + @SuppressWarnings("deprecation") + @Test + public void testOpenCaseOld() { + // D4 case + SymmetryAxes axes = new SymmetryAxes(); + + // Level 1 is R4 along X + Matrix4d t10 = new Matrix4d(); + t10.set(1,new Vector3d(1,0,0)); + List repeats = Arrays.asList(0,0,1,1,2,2,3,3); + List> superposition = Arrays.asList( + Arrays.asList(0,1,2,3,4,5), + Arrays.asList(2,3,4,5,6,7)); + axes.addAxis(t10, superposition, repeats, 4); + + // Level 2 is C2 along X + Matrix4d r180 = new Matrix4d(); + r180.set(new AxisAngle4d(1, 0, 0, Math.PI)); + repeats = Arrays.asList(0,1,0,1,0,1,0,1); + superposition = Arrays.asList( + Arrays.asList(0,1), + Arrays.asList(1,0)); + axes.addAxis(r180, superposition, repeats, 2); + + + assertEquals(2,axes.getElementaryAxes().size()); + + Matrix4d expectedEven = new Matrix4d(); + expectedEven.setIdentity(); + Matrix4d expectedOdd = new Matrix4d(r180); + assertEquals(expectedEven, axes.getRepeatTransform(0)); + assertEquals(expectedOdd, axes.getRepeatTransform(1)); + expectedEven.mul(t10); + expectedOdd.mul(r180,expectedEven); + assertEquals(expectedEven, axes.getRepeatTransform(2)); + assertEquals(expectedOdd, axes.getRepeatTransform(3)); + expectedEven.mul(t10); + expectedOdd.mul(r180,expectedEven); + assertEquals(expectedEven, axes.getRepeatTransform(4)); + assertEquals(expectedOdd, axes.getRepeatTransform(5)); + expectedEven.mul(t10); + expectedOdd.mul(r180,expectedEven); + assertEquals(expectedEven, axes.getRepeatTransform(6)); + assertEquals(expectedOdd, axes.getRepeatTransform(7)); + + List> relation = Arrays.asList( + Arrays.asList(0,1,2,3,4,5), + Arrays.asList(2,3,4,5,6,7) + ); + assertEquals(relation,axes.getRepeatRelation(0)); + relation = Arrays.asList( + Arrays.asList(0,1), + Arrays.asList(1,0) + ); + assertEquals(relation,axes.getRepeatRelation(1)); + try { + axes.getRepeatRelation(2); + fail("Invalid level"); + } catch(IndexOutOfBoundsException e) {} + + } +} diff --git a/biojava-survival/pom.xml b/biojava-survival/pom.xml index 5bffa2139e..3b57f7242f 100644 --- a/biojava-survival/pom.xml +++ b/biojava-survival/pom.xml @@ -4,7 +4,7 @@ org.biojava biojava - 4.2.1 + 4.2.2 biojava-survival diff --git a/biojava-ws/pom.xml b/biojava-ws/pom.xml index 9d643a2368..fb469e0d69 100644 --- a/biojava-ws/pom.xml +++ b/biojava-ws/pom.xml @@ -3,7 +3,7 @@ biojava org.biojava - 4.2.1 + 4.2.2 biojava-ws biojava-ws @@ -19,7 +19,7 @@ org.biojava biojava-core - 4.2.1 + 4.2.2 compile diff --git a/pom.xml b/pom.xml index 330c0798a3..864b9d9ff4 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ org.biojava biojava pom - 4.2.1 + 4.2.2 biojava BioJava is an open-source project dedicated to providing a Java framework for processing biological data. It provides analytical and statistical routines, parsers for common file formats and allows the @@ -44,7 +44,7 @@ scm:git:git@github.com:biojava/biojava.git https://github.com/biojava/biojava - biojava-4.2.1 + biojava-4.2.2 forked-path + + + true + -Pgpg-release