import jalview.datamodel.Alignment;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.DBRefSource;
import jalview.datamodel.Mapping;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceFeature;
*/
public List<String> findXrefSourcesForSequences(boolean dna)
{
- List<String> sources = new ArrayList<String>();
+ List<String> sources = new ArrayList<>();
for (SequenceI seq : fromSeqs)
{
if (seq != null)
findXrefSourcesForSequence(seq, dna, sources);
}
}
+ sources.remove(DBRefSource.EMBL); // hack to prevent EMBL xrefs resulting in
+ // redundant datasets
+ if (dna)
+ {
+ sources.remove(DBRefSource.ENSEMBL); // hack to prevent Ensembl and
+ // EnsemblGenomes xref option shown
+ // from cdna panel
+ sources.remove(DBRefSource.ENSEMBLGENOMES);
+ }
+ // redundant datasets
return sources;
}
/*
* first find seq's xrefs (dna-to-peptide or peptide-to-dna)
*/
- DBRefEntry[] rfs = DBRefUtils.selectDbRefs(!fromDna, seq.getDBRefs());
+ List<DBRefEntry> rfs = DBRefUtils.selectDbRefs(!fromDna, seq.getDBRefs());
addXrefsToSources(rfs, sources);
if (dataset != null)
{
/*
* find sequence's direct (dna-to-dna, peptide-to-peptide) xrefs
*/
- DBRefEntry[] lrfs = DBRefUtils.selectDbRefs(fromDna, seq.getDBRefs());
- List<SequenceI> foundSeqs = new ArrayList<SequenceI>();
+ List<DBRefEntry> lrfs = DBRefUtils.selectDbRefs(fromDna, seq.getDBRefs());
+ List<SequenceI> foundSeqs = new ArrayList<>();
/*
* find sequences in the alignment which xref one of these DBRefs
*/
for (SequenceI rs : foundSeqs)
{
- DBRefEntry[] xrs = DBRefUtils
- .selectDbRefs(!fromDna, rs.getDBRefs());
+ List<DBRefEntry> xrs = DBRefUtils.selectDbRefs(!fromDna,
+ rs.getDBRefs());
addXrefsToSources(xrs, sources);
}
}
* @param xrefs
* @param sources
*/
- void addXrefsToSources(DBRefEntry[] xrefs, List<String> sources)
+ void addXrefsToSources(List<DBRefEntry> xrefs, List<String> sources)
{
if (xrefs != null)
{
public Alignment findXrefSequences(String source, boolean fromDna)
{
- rseqs = new ArrayList<SequenceI>();
+ rseqs = new ArrayList<>();
AlignedCodonFrame cf = new AlignedCodonFrame();
- matcher = new SequenceIdMatcher(
- dataset.getSequences());
+ matcher = new SequenceIdMatcher(dataset.getSequences());
for (SequenceI seq : fromSeqs)
{
dss = dss.getDatasetSequence();
}
boolean found = false;
- DBRefEntry[] xrfs = DBRefUtils
- .selectDbRefs(!fromDna, dss.getDBRefs());
+ List<DBRefEntry> xrfs = DBRefUtils.selectDbRefs(!fromDna,
+ dss.getDBRefs());
// ENST & ENSP comes in to both Protein and nucleotide, so we need to
// filter them
// out later.
- if ((xrfs == null || xrfs.length == 0) && dataset != null)
+ if ((xrfs == null || xrfs.size() == 0) && dataset != null)
{
/*
* found no suitable dbrefs on sequence - look for sequences in the
* alignment which share a dbref with this one
*/
- DBRefEntry[] lrfs = DBRefUtils.selectDbRefs(fromDna,
+ List<DBRefEntry> lrfs = DBRefUtils.selectDbRefs(fromDna,
seq.getDBRefs());
/*
if (matchInDataset != null && xref.getMap().getTo() != null
&& matchInDataset != xref.getMap().getTo())
{
- System.err
- .println("Implementation problem (reopen JAL-2154): CrossRef.findInDataset seems to have recovered a different sequence than the one explicitly mapped for xref."
- + "Found:"
- + matchInDataset
- + "\nExpected:"
- + xref.getMap().getTo()
- + "\nFor xref:"
+ System.err.println(
+ "Implementation problem (reopen JAL-2154): CrossRef.findInDataset seems to have recovered a different sequence than the one explicitly mapped for xref."
+ + "Found:" + matchInDataset + "\nExpected:"
+ + xref.getMap().getTo() + "\nFor xref:"
+ xref);
}
/*matcher.findIdMatch(mappedTo);*/
}
else
{
- cf.addMap(matchInDataset, dss, xref.getMap().getMap()
- .getInverse(), xref.getMap().getMappedFromId());
+ cf.addMap(matchInDataset, dss,
+ xref.getMap().getMap().getInverse(),
+ xref.getMap().getMappedFromId());
}
}
if (fromDna)
{
// map is from dna seq to a protein product
- cf.addMap(dss, rsq, xref.getMap().getMap(), xref.getMap()
- .getMappedFromId());
+ cf.addMap(dss, rsq, xref.getMap().getMap(),
+ xref.getMap().getMappedFromId());
}
else
{
if (!found)
{
- SequenceI matchedSeq = matcher.findIdMatch(xref.getSource() + "|"
- + xref.getAccessionId());
+ SequenceI matchedSeq = matcher.findIdMatch(
+ xref.getSource() + "|" + xref.getAccessionId());
// if there was a match, check it's at least the right type of
// molecule!
if (matchedSeq != null && matchedSeq.isProtein() == fromDna)
{
// do a bit more work - search for sequences with references matching
// xrefs on this sequence.
- found = searchDataset(fromDna, dss, xref, rseqs, cf, false);
+ found = searchDataset(fromDna, dss, xref, rseqs, cf, false, DBRefUtils.SEARCH_MODE_FULL);
}
if (found)
{
}
private void retrieveCrossRef(List<DBRefEntry> sourceRefs, SequenceI seq,
- DBRefEntry[] xrfs, boolean fromDna, AlignedCodonFrame cf)
+ List<DBRefEntry> xrfs, boolean fromDna, AlignedCodonFrame cf)
{
ASequenceFetcher sftch = SequenceFetcherFactory.getSequenceFetcher();
SequenceI[] retrieved = null;
- SequenceI dss = seq.getDatasetSequence() == null ? seq : seq
- .getDatasetSequence();
+ SequenceI dss = seq.getDatasetSequence() == null ? seq
+ : seq.getDatasetSequence();
// first filter in case we are retrieving crossrefs that have already been
// retrieved. this happens for cases where a database record doesn't yield
// protein products for CDS
retrieved = sftch.getSequences(sourceRefs, !fromDna);
} catch (Exception e)
{
- System.err
- .println("Problem whilst retrieving cross references for Sequence : "
+ System.err.println(
+ "Problem whilst retrieving cross references for Sequence : "
+ seq.getName());
e.printStackTrace();
}
if (retrieved != null)
{
boolean addedXref = false;
+ List<SequenceI> newDsSeqs = new ArrayList<>(),
+ doNotAdd = new ArrayList<>();
+
for (SequenceI retrievedSequence : retrieved)
{
// dataset gets contaminated ccwith non-ds sequences. why ??!
// try: Ensembl -> Nuc->Ensembl, Nuc->Uniprot-->Protein->EMBL->
- SequenceI retrievedDss = retrievedSequence.getDatasetSequence() == null ? retrievedSequence
- : retrievedSequence.getDatasetSequence();
- addedXref |= importCrossRefSeq(cf, dss, retrievedDss);
+ SequenceI retrievedDss = retrievedSequence
+ .getDatasetSequence() == null ? retrievedSequence
+ : retrievedSequence.getDatasetSequence();
+ addedXref |= importCrossRefSeq(cf, newDsSeqs, doNotAdd, dss,
+ retrievedDss);
}
+ // JBPNote: What assumptions are made for dbref structures on
+ // retrieved sequences ?
+ // addedXref will be true means importCrossRefSeq found
+ // sequences with dbrefs with mappings to sequences congruent with dss
+
if (!addedXref)
{
// try again, after looking for matching IDs
{
// dataset gets contaminated ccwith non-ds sequences. why ??!
// try: Ensembl -> Nuc->Ensembl, Nuc->Uniprot-->Protein->EMBL->
- SequenceI retrievedDss = retrievedSequence.getDatasetSequence() == null ? retrievedSequence
- : retrievedSequence.getDatasetSequence();
- addedXref |= importCrossRefSeq(cf, dss, retrievedDss);
+ SequenceI retrievedDss = retrievedSequence
+ .getDatasetSequence() == null ? retrievedSequence
+ : retrievedSequence.getDatasetSequence();
+ addedXref |= importCrossRefSeq(cf, newDsSeqs, doNotAdd, dss,
+ retrievedDss);
+ }
+ }
+ for (SequenceI newToSeq : newDsSeqs)
+ {
+ if (!doNotAdd.contains(newToSeq)
+ && dataset.findIndex(newToSeq) == -1)
+ {
+ dataset.addSequence(newToSeq);
+ matcher.add(newToSeq);
}
}
}
private void removeAlreadyRetrievedSeqs(List<DBRefEntry> sourceRefs,
boolean fromDna)
{
- DBRefEntry[] dbrSourceSet = sourceRefs.toArray(new DBRefEntry[0]);
- for (SequenceI sq : dataset.getSequences())
+ List<DBRefEntry> dbrSourceSet = new ArrayList<>(sourceRefs);
+ List<SequenceI> dsSeqs = dataset.getSequences();
+ for (int ids = 0, nds = dsSeqs.size(); ids < nds; ids++)
{
+ SequenceI sq = dsSeqs.get(ids);
boolean dupeFound = false;
// !fromDna means we are looking only for nucleotide sequences, not
// protein
if (sq.isProtein() == fromDna)
{
- for (DBRefEntry dbr : sq.getPrimaryDBRefs())
+ List<DBRefEntry> sqdbrefs = sq.getPrimaryDBRefs();
+ for (int idb = 0, ndb = sqdbrefs.size(); idb < ndb; idb++)
{
- for (DBRefEntry found : DBRefUtils.searchRefs(dbrSourceSet, dbr))
+ DBRefEntry dbr = sqdbrefs.get(idb);
+ List<DBRefEntry> searchrefs = DBRefUtils.searchRefs(dbrSourceSet, dbr, DBRefUtils.SEARCH_MODE_FULL);
+ for (int isr = 0, nsr = searchrefs.size(); isr < nsr; isr++)
{
- sourceRefs.remove(found);
+ sourceRefs.remove(searchrefs.get(isr));
dupeFound = true;
}
}
if (dupeFound)
{
// rebuild the search array from the filtered sourceRefs list
- dbrSourceSet = sourceRefs.toArray(new DBRefEntry[0]);
+ dbrSourceSet.clear();
+ dbrSourceSet.addAll(sourceRefs);
}
}
}
/**
* process sequence retrieved via a dbref on source sequence to resolve and
- * transfer data
+ * transfer data JBPNote: as of 2022-02-03 - this assumes retrievedSequence
+ * has dbRefs with Mapping references to a sequence congruent with
+ * sourceSequence
*
* @param cf
* @param sourceSequence
* @return true if retrieveSequence was imported
*/
private boolean importCrossRefSeq(AlignedCodonFrame cf,
+ List<SequenceI> newDsSeqs, List<SequenceI> doNotAdd,
SequenceI sourceSequence, SequenceI retrievedSequence)
{
/**
* sourceSequence
*/
boolean imported = false;
- DBRefEntry[] dbr = retrievedSequence.getDBRefs();
- List<SequenceI> newDsSeqs = new ArrayList<SequenceI>();
+ List<DBRefEntry> dbr = retrievedSequence.getDBRefs();
if (dbr != null)
{
- for (DBRefEntry dbref : dbr)
+ for (int ib = 0, nb = dbr.size(); ib < nb; ib++)
{
+
+ DBRefEntry dbref = dbr.get(ib);
+ // matched will return null if the dbref has no map
SequenceI matched = findInDataset(dbref);
if (matched == sourceSequence)
{
Mapping map = dbref.getMap();
if (map != null)
{
- if (map.getTo() != null && map.getMap() != null)
+ SequenceI ms = map.getTo();
+ if (ms != null && map.getMap() != null)
{
- if (map.getTo() == sourceSequence)
+ if (ms == sourceSequence)
{
// already called to import once, and most likely this sequence
// already imported !
/*
* sequence is new to dataset, so save a reference so it can be added.
*/
- newDsSeqs.add(map.getTo());
+ newDsSeqs.add(ms);
continue;
}
{
// compare ms with dss and replace with dss in mapping
// if map is congruent
- SequenceI ms = map.getTo();
// TODO findInDataset requires exact sequence match but
// 'congruent' test is only for the mapped part
// maybe not a problem in practice since only ENA provide a
int sf = map.getMap().getToLowest();
int st = map.getMap().getToHighest();
SequenceI mappedrg = ms.getSubSequence(sf, st);
- if (mappedrg.getLength() > 0
- && ms.getSequenceAsString().equals(
- matched.getSequenceAsString()))
+ if (mappedrg.getLength() > 0 && ms.getSequenceAsString()
+ .equals(matched.getSequenceAsString()))
{
/*
* sequences were a match,
+ matched.getName();
System.out.println(msg);
- DBRefEntry[] toRefs = map.getTo().getDBRefs();
+ List<DBRefEntry> toRefs = map.getTo().getDBRefs();
if (toRefs != null)
{
/*
*/
for (DBRefEntry ref : toRefs)
{
+ if (dbref.getSrcAccString()
+ .equals(ref.getSrcAccString()))
+ {
+ continue; // avoid overwriting the ref on source sequence
+ }
matched.addDBRef(ref); // add or update mapping
}
}
+ doNotAdd.add(map.getTo());
map.setTo(matched);
/*
* duplication (e.g. same variation from two
* transcripts)
*/
- SequenceFeature[] sfs = ms.getSequenceFeatures();
- if (sfs != null)
+ List<SequenceFeature> sfs = ms.getFeatures()
+ .getAllFeatures();
+ for (SequenceFeature feat : sfs)
{
- for (SequenceFeature feat : sfs)
+ /*
+ * make a flyweight feature object which ignores Parent
+ * attribute in equality test; this avoids creating many
+ * otherwise duplicate exon features on genomic sequence
+ */
+ SequenceFeature newFeature = new SequenceFeature(feat)
{
- /*
- * make a flyweight feature object which ignores Parent
- * attribute in equality test; this avoids creating many
- * otherwise duplicate exon features on genomic sequence
- */
- SequenceFeature newFeature = new SequenceFeature(
- feat)
+ @Override
+ public boolean equals(Object o)
{
- @Override
- public boolean equals(Object o)
- {
- return super.equals(o, true);
- }
- };
- matched.addSequenceFeature(newFeature);
- }
+ return super.equals(o, true);
+ }
+ };
+ matched.addSequenceFeature(newFeature);
}
-
}
cf.addMap(retrievedSequence, map.getTo(), map.getMap());
} catch (Exception e)
{
- System.err
- .println("Exception when consolidating Mapped sequence set...");
+ System.err.println(
+ "Exception when consolidating Mapped sequence set...");
e.printStackTrace(System.err);
}
}
dataset.addSequence(retrievedSequence);
matcher.add(retrievedSequence);
}
- for (SequenceI newToSeq : newDsSeqs)
- {
-
- if (dataset.findIndex(newToSeq) == -1)
- {
- dataset.addSequence(newToSeq);
- matcher.add(newToSeq);
- }
- }
}
return imported;
}
+
/**
* Sets the inverse sequence mapping in the corresponding dbref of the mapped
* to sequence (if any). This is used after fetching a cross-referenced
{
return;
}
- DBRefEntry[] dbrefs = mapTo.getDBRefs();
+ List<DBRefEntry> dbrefs = mapTo.getDBRefs();
if (dbrefs == null)
{
return;
* Returns null or the first sequence in the dataset which is identical to
* xref.mapTo, and has a) a primary dbref matching xref, or if none found, the
* first one with an ID source|xrefacc
- *
+ * JBPNote: Could refactor this to AlignmentI/DatasetI
* @param xref
* with map and mapped-to sequence
* @return
SequenceI mapsTo = xref.getMap().getTo();
String name = xref.getAccessionId();
String name2 = xref.getSource() + "|" + name;
- SequenceI dss = mapsTo.getDatasetSequence() == null ? mapsTo : mapsTo
- .getDatasetSequence();
+ SequenceI dss = mapsTo.getDatasetSequence() == null ? mapsTo
+ : mapsTo.getDatasetSequence();
// first check ds if ds is directly referenced
if (dataset.findIndex(dss) > -1)
{
for (SequenceI seq : dataset.getSequences())
{
// first check primary refs.
- List<DBRefEntry> match = DBRefUtils.searchRefs(seq.getPrimaryDBRefs()
- .toArray(new DBRefEntry[0]), template);
+ List<DBRefEntry> match = DBRefUtils.searchRefs(
+ seq.getPrimaryDBRefs(), template, DBRefUtils.SEARCH_MODE_FULL);
if (match != null && match.size() == 1 && sameSequence(seq, dss))
{
return seq;
* returns sequences with a dbref to the matched accession id
* which we don't want
*/
- if (firstIdMatch == null
- && (name.equals(seq.getName()) || seq.getName().startsWith(
- name2)))
+ if (firstIdMatch == null && (name.equals(seq.getName())
+ || seq.getName().startsWith(name2)))
{
if (sameSequence(seq, dss))
{
{
return false;
}
- char[] c1 = seq1.getSequence();
- char[] c2 = seq2.getSequence();
- if (c1.length != c2.length)
+
+ if (seq1.getLength() != seq2.getLength())
{
return false;
}
- for (int i = 0; i < c1.length; i++)
+ int length = seq1.getLength();
+ for (int i = 0; i < length; i++)
{
- int diff = c1[i] - c2[i];
+ int diff = seq1.getCharAt(i) - seq2.getCharAt(i);
/*
* same char or differ in case only ('a'-'A' == 32)
*/
* Updates any empty mappings in the cross-references with one to a compatible
* retrieved sequence if found, and adds any new mappings to the
* AlignedCodonFrame
- *
+ * JBPNote: TODO: this relies on sequence IDs like UNIPROT|ACCESSION - which do not always happen.
* @param mapFrom
* @param xrefs
* @param retrieved
* @param acf
*/
- void updateDbrefMappings(SequenceI mapFrom, DBRefEntry[] xrefs,
+ void updateDbrefMappings(SequenceI mapFrom, List<DBRefEntry> xrefs,
SequenceI[] retrieved, AlignedCodonFrame acf, boolean fromDna)
{
SequenceIdMatcher idMatcher = new SequenceIdMatcher(retrieved);
if (fromDna)
{
- AlignmentUtils.computeProteinFeatures(mapFrom, mapTo, mapping);
+ // AlignmentUtils.computeProteinFeatures(mapFrom, mapTo, mapping);
mappings.addMap(mapFrom, mapTo, mapping);
}
else
* @return true if matches were found.
*/
private boolean searchDatasetXrefs(boolean fromDna, SequenceI sequenceI,
- DBRefEntry[] lrfs, List<SequenceI> foundSeqs, AlignedCodonFrame cf)
+ List<DBRefEntry> lrfs, List<SequenceI> foundSeqs,
+ AlignedCodonFrame cf)
{
boolean found = false;
if (lrfs == null)
{
return false;
}
- for (int i = 0; i < lrfs.length; i++)
+ for (int i = 0, n = lrfs.size(); i < n; i++)
{
- DBRefEntry xref = new DBRefEntry(lrfs[i]);
- // add in wildcards
- xref.setVersion(null);
- xref.setMap(null);
- found |= searchDataset(fromDna, sequenceI, xref, foundSeqs, cf, false);
+// DBRefEntry xref = new DBRefEntry(lrfs.get(i));
+// // add in wildcards
+// xref.setVersion(null);
+// xref.setMap(null);
+ found |= searchDataset(fromDna, sequenceI, lrfs.get(i), foundSeqs, cf,
+ false, DBRefUtils.SEARCH_MODE_NO_MAP_NO_VERSION);
}
return found;
}
* sequenceI or all the returned sequences (eg a genomic reference
* associated with a locus and one or more transcripts)</li>
* </ul>
+ * @param mode SEARCH_MODE_FULL for all; SEARCH_MODE_NO_MAP_NO_VERSION optional
* @return true if relationship found and sequence added.
*/
boolean searchDataset(boolean fromDna, SequenceI fromSeq, DBRefEntry xrf,
List<SequenceI> foundSeqs, AlignedCodonFrame mappings,
- boolean direct)
+ boolean direct, int mode)
{
boolean found = false;
if (dataset == null)
System.err.println("Empty dataset sequence set - NO VECTOR");
return false;
}
- List<SequenceI> ds;
- synchronized (ds = dataset.getSequences())
+ List<SequenceI> ds = dataset.getSequences();
+ synchronized (ds)
{
for (SequenceI nxt : ds)
{
{
if (nxt.getDatasetSequence() != null)
{
- System.err
- .println("Implementation warning: CrossRef initialised with a dataset alignment with non-dataset sequences in it! ("
- + nxt.getDisplayId(true)
- + " has ds reference "
+ System.err.println(
+ "Implementation warning: CrossRef initialised with a dataset alignment with non-dataset sequences in it! ("
+ + nxt.getDisplayId(true) + " has ds reference "
+ nxt.getDatasetSequence().getDisplayId(true)
+ ")");
}
}
// look for direct or indirect references in common
- DBRefEntry[] poss = nxt.getDBRefs();
+ List<DBRefEntry> poss = nxt.getDBRefs();
List<DBRefEntry> cands = null;
// todo: indirect specifies we select either direct references to nxt
// that match xrf which is indirect to sequenceI, or indirect
// references to nxt that match xrf which is direct to sequenceI
- cands = DBRefUtils.searchRefs(poss, xrf);
+ cands = DBRefUtils.searchRefs(poss, xrf, mode);
// else
// {
// poss = DBRefUtils.selectDbRefs(nxt.isProtein()!fromDna, poss);