From 51ff7ec3b6914f3c69b35e91e69d10c88aaf5270 Mon Sep 17 00:00:00 2001 From: Jim Procter Date: Mon, 17 Oct 2022 12:18:22 +0100 Subject: [PATCH] JAL-2349 JAL-3855 Integrate pAE retrieval in StructureFile so it can be transferred as reference annotation --- src/jalview/analysis/AlignmentUtils.java | 16 +++++++--- src/jalview/datamodel/Alignment.java | 35 ++++++++++++++++++++-- src/jalview/datamodel/ContactMapHolder.java | 13 ++++++++ src/jalview/datamodel/ContactMapHolderI.java | 4 +++ src/jalview/datamodel/Sequence.java | 23 +++++++++++++- src/jalview/datamodel/SequenceGroup.java | 14 +++++++++ src/jalview/datamodel/SequenceI.java | 3 ++ src/jalview/ext/jmol/JmolParser.java | 7 +++++ src/jalview/ws/dbsources/EBIAlfaFold.java | 11 ++++--- src/mc_view/PDBChain.java | 13 +++++++- test/jalview/analysis/AlignmentUtilsTests.java | 31 +++++++++++++++++++ test/jalview/ws/seqfetcher/DbRefFetcherTest.java | 32 ++++++++++---------- 12 files changed, 172 insertions(+), 30 deletions(-) diff --git a/src/jalview/analysis/AlignmentUtils.java b/src/jalview/analysis/AlignmentUtils.java index fdc74e2..a1a7fef 100644 --- a/src/jalview/analysis/AlignmentUtils.java +++ b/src/jalview/analysis/AlignmentUtils.java @@ -20,8 +20,6 @@ */ package jalview.analysis; -import java.util.Locale; - import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -31,6 +29,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.NoSuchElementException; @@ -46,6 +45,7 @@ import jalview.datamodel.AlignedCodonFrame.SequenceToSequenceMapping; import jalview.datamodel.Alignment; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.AlignmentI; +import jalview.datamodel.ContactMatrixI; import jalview.datamodel.DBRefEntry; import jalview.datamodel.GeneLociI; import jalview.datamodel.IncompleteCodonException; @@ -1471,7 +1471,8 @@ public class AlignmentUtils */ final Iterable matchedAlignmentAnnotations = al .findAnnotations(seq, dsann.getCalcId(), dsann.label); - if (!matchedAlignmentAnnotations.iterator().hasNext()) + if (matchedAlignmentAnnotations == null + || !matchedAlignmentAnnotations.iterator().hasNext()) { result.add(dsann); if (labelForCalcId != null) @@ -1517,7 +1518,7 @@ public class AlignmentUtils startRes = selectionGroup.getStartRes(); endRes = selectionGroup.getEndRes(); } - copyAnn.restrict(startRes, endRes); + copyAnn.restrict(startRes, endRes + 0); /* * Add to the sequence (sets copyAnn.datasetSequence), unless the @@ -1525,6 +1526,12 @@ public class AlignmentUtils */ if (!seq.hasAnnotation(ann)) { + ContactMatrixI cm = seq.getDatasetSequence() + .getContactMatrixFor(ann); + if (cm != null) + { + seq.addContactListFor(copyAnn, cm); + } seq.addAlignmentAnnotation(copyAnn); } // adjust for gaps @@ -1534,6 +1541,7 @@ public class AlignmentUtils copyAnn.visible = true; } } + } /** diff --git a/src/jalview/datamodel/Alignment.java b/src/jalview/datamodel/Alignment.java index e1c87a9..3ae6831 100755 --- a/src/jalview/datamodel/Alignment.java +++ b/src/jalview/datamodel/Alignment.java @@ -1653,8 +1653,10 @@ public class Alignment implements AlignmentI, AutoCloseable public Iterable findAnnotations(SequenceI seq, String calcId, String label) { - return AlignmentAnnotation.findAnnotations( - Arrays.asList(getAlignmentAnnotation()), seq, calcId, label); + return annotations == null ? null + : AlignmentAnnotation.findAnnotations( + Arrays.asList(getAlignmentAnnotation()), seq, calcId, + label); } @Override @@ -2045,9 +2047,28 @@ public class Alignment implements AlignmentI, AutoCloseable } @Override + public ContactMatrixI getContactMatrixFor(AlignmentAnnotation ann) + { + return cmholder.getContactMatrixFor(ann); + } + + @Override public ContactListI getContactListFor(AlignmentAnnotation _aa, int column) { - return cmholder.getContactListFor(_aa, column); + ContactListI cl = cmholder.getContactListFor(_aa, column); + if (cl == null && _aa.groupRef != null) + { + cl = _aa.groupRef.getContactListFor(_aa, column); + } + if (cl == null && _aa.sequenceRef != null) + { + cl = _aa.sequenceRef.getContactListFor(_aa, column); + if (cl == null && _aa.sequenceRef.getDatasetSequence() != null) + { + _aa.sequenceRef.getDatasetSequence().getContactListFor(_aa, column); + } + } + return cl; } @Override @@ -2065,4 +2086,12 @@ public class Alignment implements AlignmentI, AutoCloseable addAnnotation(aa); return aa; } + + @Override + public void addContactListFor(AlignmentAnnotation annotation, + ContactMatrixI cm) + { + cmholder.addContactListFor(annotation, cm); + + } } diff --git a/src/jalview/datamodel/ContactMapHolder.java b/src/jalview/datamodel/ContactMapHolder.java index 5ef2b2a..ac1b267 100644 --- a/src/jalview/datamodel/ContactMapHolder.java +++ b/src/jalview/datamodel/ContactMapHolder.java @@ -50,4 +50,17 @@ public class ContactMapHolder implements ContactMapHolderI } return aa; } + + @Override + public ContactMatrixI getContactMatrixFor(AlignmentAnnotation ann) + { + return contactmaps == null ? null : contactmaps.get(ann.annotationId); + } + + @Override + public void addContactListFor(AlignmentAnnotation annotation, + ContactMatrixI cm) + { + contactmaps.put(annotation.annotationId, cm); + } } diff --git a/src/jalview/datamodel/ContactMapHolderI.java b/src/jalview/datamodel/ContactMapHolderI.java index 624a03e..ba23e67 100644 --- a/src/jalview/datamodel/ContactMapHolderI.java +++ b/src/jalview/datamodel/ContactMapHolderI.java @@ -18,4 +18,8 @@ public interface ContactMapHolderI Collection getContactMaps(); + public ContactMatrixI getContactMatrixFor(AlignmentAnnotation ann); + + void addContactListFor(AlignmentAnnotation annotation, ContactMatrixI cm); + } diff --git a/src/jalview/datamodel/Sequence.java b/src/jalview/datamodel/Sequence.java index d62be17..5ae7195 100755 --- a/src/jalview/datamodel/Sequence.java +++ b/src/jalview/datamodel/Sequence.java @@ -1625,6 +1625,13 @@ public class Sequence extends ASequence implements SequenceI _aa.adjustForAlignment(); // uses annotation's own record of // sequence-column mapping datasetSequence.addAlignmentAnnotation(_aa); + + // transfer contact matrices + ContactMatrixI cm = getContactMatrixFor(aa); + if (cm != null) + { + datasetSequence.addContactListFor(_aa, cm); + } } } } @@ -2111,7 +2118,7 @@ public class Sequence extends ASequence implements SequenceI //// //// Contact Matrix Holder Boilerplate //// - ContactMapHolder cmholder = new ContactMapHolder(); + ContactMapHolderI cmholder = new ContactMapHolder(); @Override public Collection getContactMaps() @@ -2120,6 +2127,12 @@ public class Sequence extends ASequence implements SequenceI } @Override + public ContactMatrixI getContactMatrixFor(AlignmentAnnotation ann) + { + return cmholder.getContactMatrixFor(ann); + } + + @Override public ContactListI getContactListFor(AlignmentAnnotation _aa, int column) { return cmholder.getContactListFor(_aa, column); @@ -2137,8 +2150,16 @@ public class Sequence extends ASequence implements SequenceI ; } aa.annotations = _aa; + aa.setSequenceRef(this); + aa.createSequenceMapping(this, getStart(), false); addAlignmentAnnotation(aa); return aa; } + @Override + public void addContactListFor(AlignmentAnnotation annotation, + ContactMatrixI cm) + { + cmholder.addContactListFor(annotation, cm); + } } diff --git a/src/jalview/datamodel/SequenceGroup.java b/src/jalview/datamodel/SequenceGroup.java index 6a0e64c..b356894 100755 --- a/src/jalview/datamodel/SequenceGroup.java +++ b/src/jalview/datamodel/SequenceGroup.java @@ -1499,6 +1499,12 @@ public class SequenceGroup implements AnnotatedCollectionI } @Override + public ContactMatrixI getContactMatrixFor(AlignmentAnnotation ann) + { + return cmholder.getContactMatrixFor(ann); + } + + @Override public ContactListI getContactListFor(AlignmentAnnotation _aa, int column) { return cmholder.getContactListFor(_aa, column); @@ -1519,4 +1525,12 @@ public class SequenceGroup implements AnnotatedCollectionI // TODO passing annotations back to context to be added return aa; } + + @Override + public void addContactListFor(AlignmentAnnotation annotation, + ContactMatrixI cm) + { + cmholder.addContactListFor(annotation, cm); + } + } diff --git a/src/jalview/datamodel/SequenceI.java b/src/jalview/datamodel/SequenceI.java index 34dbab7..c789857 100755 --- a/src/jalview/datamodel/SequenceI.java +++ b/src/jalview/datamodel/SequenceI.java @@ -596,4 +596,7 @@ public interface SequenceI extends ASequenceI, ContactMapHolderI */ public int firstResidueOutsideIterator(Iterator it); + public void addContactListFor(AlignmentAnnotation annotation, + ContactMatrixI cm); + } diff --git a/src/jalview/ext/jmol/JmolParser.java b/src/jalview/ext/jmol/JmolParser.java index ec123f4..269fc31 100644 --- a/src/jalview/ext/jmol/JmolParser.java +++ b/src/jalview/ext/jmol/JmolParser.java @@ -290,6 +290,13 @@ public class JmolParser extends StructureFile implements JmolStatusListener Console.info("retrieving pAE for " + pdbId); Alignment al = new Alignment(prot.toArray(new SequenceI[0])); EBIAlfaFold.retrieve_AlphaFold_pAE(pdbId, al, null); + if (al.getAlignmentAnnotation() != null) + { + for (AlignmentAnnotation alann : al.getAlignmentAnnotation()) + { + annotations.add(alann); + } + } ; } catch (Throwable t) { diff --git a/src/jalview/ws/dbsources/EBIAlfaFold.java b/src/jalview/ws/dbsources/EBIAlfaFold.java index 0e148ff..9e488c9 100644 --- a/src/jalview/ws/dbsources/EBIAlfaFold.java +++ b/src/jalview/ws/dbsources/EBIAlfaFold.java @@ -197,7 +197,8 @@ public class EBIAlfaFold extends EbiFileRetrievedProxy "exception.no_pdb_records_for_chain", new String[] { id, ((chain == null) ? "' '" : chain) })); } - retrieve_AlphaFold_pAE(id, pdbAlignment, retrievalUrl); + // done during structure retrieval + // retrieve_AlphaFold_pAE(id, pdbAlignment, retrievalUrl); } catch (Exception ex) // Problem parsing PDB file { @@ -274,11 +275,9 @@ public class EBIAlfaFold extends EbiFileRetrievedProxy pdbAlignment.getSequenceAt(0), (Map) pae_obj.get(0)); - // THIS IS NOT GOING TO WORK !!! - // ?? StructureFile assumes sequenceI holds all data, so AlignmentAnnotation - // needs to hold the contact matrix data. - pdbAlignment.getSequenceAt(0) - .addAlignmentAnnotation(pdbAlignment.addContactList(matrix)); + AlignmentAnnotation cmannot = pdbAlignment.getSequenceAt(0) + .addContactList(matrix); + pdbAlignment.addAnnotation(cmannot); return true; } diff --git a/src/mc_view/PDBChain.java b/src/mc_view/PDBChain.java index dc25368..035e608 100755 --- a/src/mc_view/PDBChain.java +++ b/src/mc_view/PDBChain.java @@ -28,6 +28,7 @@ import java.util.Vector; import jalview.analysis.AlignSeq; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.Annotation; +import jalview.datamodel.ContactMatrixI; import jalview.datamodel.Mapping; import jalview.datamodel.Sequence; import jalview.datamodel.SequenceFeature; @@ -664,10 +665,16 @@ public class PDBChain ana.getCalcId(), ana.label, ana.description); if (transfer == null || transfer.size() == 0) { + ContactMatrixI cm = shadow.getContactMatrixFor(ana); ana = new AlignmentAnnotation(ana); + // TODO map contact matrix under mapping ana.liftOver(sequence, shadowMap); ana.liftOver(dsq, sqmpping); dsq.addAlignmentAnnotation(ana); + if (cm != null) + { + dsq.addContactListFor(ana, cm); + } } else { @@ -688,10 +695,14 @@ public class PDBChain ana.description); if (transfer == null || transfer.size() == 0) { + ContactMatrixI cm = sequence.getContactMatrixFor(ana); ana = new AlignmentAnnotation(ana); ana.liftOver(dsq, sqmpping); dsq.addAlignmentAnnotation(ana); - // mapping.transfer(ana); + if (cm != null) + { + dsq.addContactListFor(ana, cm); + } } else { diff --git a/test/jalview/analysis/AlignmentUtilsTests.java b/test/jalview/analysis/AlignmentUtilsTests.java index e231e7f..c1eb9fd 100644 --- a/test/jalview/analysis/AlignmentUtilsTests.java +++ b/test/jalview/analysis/AlignmentUtilsTests.java @@ -2600,4 +2600,35 @@ public class AlignmentUtilsTests dnaToPeptide); assertSame(seq, cds1.getDatasetSequence()); } + + @Test(groups = "Functional") + public void testAddReferenceContactMap() + { + SequenceI sq = new Sequence("a", "SSSQ"); + ContactMatrixI cm = new SeqDistanceContactMatrix(4); + AlignmentAnnotation cm_aan = sq.addContactList(cm); + SequenceI dssq = sq.createDatasetSequence(); + Alignment ds = new Alignment(new SequenceI[] { dssq }); + + // remove annotation on our non-dataset sequence + sq.removeAlignmentAnnotation(sq.getAnnotation()[0]); + // test transfer + Alignment al = new Alignment(new SequenceI[] { sq }); + SortedMap tipEntries = new TreeMap<>(); + final Map> candidates = new LinkedHashMap<>(); + + AlignmentUtils.findAddableReferenceAnnotations(al.getSequences(), + tipEntries, candidates, al); + AlignmentUtils.addReferenceAnnotations(candidates, al, null); + assertTrue("No contact map annotation transferred", + al.getAlignmentAnnotation() != null + && al.getAlignmentAnnotation().length == 1); + AlignmentAnnotation alan = al.findAnnotations(sq, null, cm_aan.label) + .iterator().next(); + ContactListI cl = al.getContactListFor(alan, 1); + assertNotNull( + "No contact matrix recovered after reference annotation transfer", + cl); + + } } diff --git a/test/jalview/ws/seqfetcher/DbRefFetcherTest.java b/test/jalview/ws/seqfetcher/DbRefFetcherTest.java index 6769d39..d2b5aec 100644 --- a/test/jalview/ws/seqfetcher/DbRefFetcherTest.java +++ b/test/jalview/ws/seqfetcher/DbRefFetcherTest.java @@ -20,12 +20,20 @@ */ package jalview.ws.seqfetcher; -import static org.testng.Assert.assertNotEquals; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertFalse; import static org.testng.AssertJUnit.assertNotNull; import static org.testng.AssertJUnit.assertTrue; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.junit.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + import jalview.analysis.CrossRef; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.AlignmentI; @@ -43,15 +51,6 @@ import jalview.ws.dbsources.EBIAlfaFold; import jalview.ws.dbsources.Pdb; import jalview.ws.dbsources.Uniprot; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.junit.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - /** * @author jimp * @@ -240,18 +239,21 @@ public class DbRefFetcherTest public void testAlphaFoldClien() throws Exception { DbSourceProxy alphafold = new EBIAlfaFold(); - AlignmentI resp = alphafold.getSequenceRecords(alphafold.getTestQuery()); + AlignmentI resp = alphafold + .getSequenceRecords(alphafold.getTestQuery()); assertNotNull(resp); - assertEquals("One sequence only",resp.getHeight(), 1); - for (AlignmentAnnotation aa:resp.getAlignmentAnnotation()) { + assertEquals("One sequence only", resp.getHeight(), 1); + for (AlignmentAnnotation aa : resp.getAlignmentAnnotation()) + { if (aa.graph == AlignmentAnnotation.CUSTOMRENDERER) { - assertTrue("Contact map didn't provide valid contact",resp.getContactListFor(aa, 1).getContactAt(1)!=-1d); + assertTrue("Contact map didn't provide valid contact", + resp.getContactListFor(aa, 1).getContactAt(1) != -1d); // test passes return; } } - Assert.fail(); + Assert.fail("No pAE matrix found for alphafold structure."); } } -- 1.7.10.2