import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceI;
-import jalview.util.Comparison;
import jalview.util.DBRefUtils;
import jalview.util.MapList;
import jalview.ws.SequenceFetcherFactory;
private AlignmentI dataset;
/*
- * true if we are searching for cross-references from nucleotide,
- * i.e. for protein sequences, false if the reverse
- */
- private boolean fromDna;
-
- /*
* the sequences for which we are seeking cross-references
*/
private SequenceI[] fromSeqs;
/**
+ * matcher built from dataset
+ */
+ SequenceIdMatcher matcher;
+
+ /**
+ * sequences found by cross-ref searches to fromSeqs
+ */
+ List<SequenceI> rseqs;
+
+ /**
+ * mappings constructed
+ */
+ AlignedCodonFrame cf;
+
+ /**
* Constructor
*
* @param seqs
public CrossRef(SequenceI[] seqs, AlignmentI ds)
{
fromSeqs = seqs;
- fromDna = ds.isNucleotide();
dataset = ds.getDataset() == null ? ds : ds.getDataset();
}
* reference from another sequence in the dataset which has a cross-reference
* to a direct DBRefEntry on the given sequence</li>
* </ul>
+ *
+ * @param dna
+ * - when true, cross-references *from* dna returned. When false,
+ * cross-references *from* protein are returned
* @return
*/
- public List<String> findXrefSourcesForSequences()
+ public List<String> findXrefSourcesForSequences(boolean dna)
{
List<String> sources = new ArrayList<String>();
for (SequenceI seq : fromSeqs)
{
if (seq != null)
{
- findXrefSourcesForSequence(seq, sources);
+ findXrefSourcesForSequence(seq, dna, sources);
}
}
return sources;
*
* @param seq
* the sequence whose dbrefs we are searching against
+ * @param fromDna
+ * when true, context is DNA - so sources identifying protein
+ * products will be returned.
* @param sources
* a list of sources to add matches to
*/
- void findXrefSourcesForSequence(SequenceI seq, List<String> sources)
+ void findXrefSourcesForSequence(SequenceI seq, boolean fromDna,
+ List<String> sources)
{
/*
* first find seq's xrefs (dna-to-peptide or peptide-to-dna)
* find sequences in the alignment which xref one of these DBRefs
* i.e. is xref-ed to a common sequence identifier
*/
- searchDatasetXrefs(seq, lrfs, rseqs, null);
+ searchDatasetXrefs(fromDna, seq, lrfs, rseqs, null);
/*
* add those sequences' (dna-to-peptide or peptide-to-dna) dbref sources
* @param source
* @return cross-referenced sequences (as dataset sequences)
*/
- public Alignment findXrefSequences(String source)
+ public Alignment findXrefSequences(String source, boolean fromDna)
{
- List<SequenceI> rseqs = new ArrayList<SequenceI>();
- AlignedCodonFrame cf = new AlignedCodonFrame();
- SequenceIdMatcher matcher = new SequenceIdMatcher(
+ rseqs = new ArrayList<SequenceI>();
+ cf = new AlignedCodonFrame();
+ matcher = new SequenceIdMatcher(
dataset.getSequences());
for (SequenceI seq : fromSeqs)
* which have a dbref to an accession id for this sequence,
* and add them to the results
*/
- found = searchDatasetXrefs(dss, lrfs, rseqs, cf);
+ found = searchDatasetXrefs(fromDna, dss, lrfs, rseqs, cf);
}
if (xrfs == null && !found)
{
+ xref.getAccessionId());
if (matchedSeq != null)
{
- if (constructMapping(seq, matchedSeq, xref, cf))
+ if (constructMapping(seq, matchedSeq, xref, cf, fromDna))
{
found = true;
}
{
// do a bit more work - search for sequences with references matching
// xrefs on this sequence.
- found = searchDataset(dss, xref, rseqs, cf, false);
+ found = searchDataset(fromDna, dss, xref, rseqs, cf, false);
}
if (found)
{
*/
if (!sourceRefs.isEmpty())
{
- ASequenceFetcher sftch = SequenceFetcherFactory
- .getSequenceFetcher();
- SequenceI[] retrieved = null;
- try
- {
- retrieved = sftch.getSequences(sourceRefs, !fromDna);
- } catch (Exception e)
- {
- System.err
- .println("Problem whilst retrieving cross references for Sequence : "
- + seq.getName());
- e.printStackTrace();
- }
+ retrieveCrossRef(sourceRefs, seq, xrfs, fromDna);
+ }
+ }
+
+ Alignment ral = null;
+ if (rseqs.size() > 0)
+ {
+ ral = new Alignment(rseqs.toArray(new SequenceI[rseqs.size()]));
+ if (!cf.isEmpty())
+ {
+ dataset.addCodonFrame(cf);
+ }
+ }
+ return ral;
+ }
+
+ private void retrieveCrossRef(List<DBRefEntry> sourceRefs, SequenceI seq,
+ DBRefEntry[] xrfs, boolean fromDna)
+ {
+ ASequenceFetcher sftch = SequenceFetcherFactory.getSequenceFetcher();
+ SequenceI[] retrieved = null;
+ SequenceI dss = null;
+ try
+ {
+ retrieved = sftch.getSequences(sourceRefs, !fromDna);
+ } catch (Exception e)
+ {
+ System.err
+ .println("Problem whilst retrieving cross references for Sequence : "
+ + seq.getName());
+ e.printStackTrace();
+ }
- if (retrieved != null)
+ if (retrieved != null)
+ {
+ updateDbrefMappings(seq, xrfs, retrieved, cf, fromDna);
+ 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();
+ DBRefEntry[] dbr = retrievedSequence.getDBRefs();
+ if (dbr != null)
{
- updateDbrefMappings(seq, xrfs, retrieved, cf);
- for (SequenceI retrievedSequence : retrieved)
+ for (DBRefEntry dbref : dbr)
{
- SequenceI retrievedDss = retrievedSequence.getDatasetSequence() == null ? retrievedSequence
- : retrievedSequence.getDatasetSequence();
- DBRefEntry[] dbr = retrievedSequence.getDBRefs();
- if (dbr != null)
+ // find any entry where we should put in the sequence being
+ // cross-referenced into the map
+ Mapping map = dbref.getMap();
+ if (map != null)
{
- for (DBRefEntry dbref : dbr)
+ if (map.getTo() != null && map.getMap() != null)
{
- // find any entry where we should put in the sequence being
- // cross-referenced into the map
- Mapping map = dbref.getMap();
- if (map != null)
+ // 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
+ // mapping and it is to the full protein translation of CDS
+ SequenceI matched = findInDataset(dbref);
+ // matcher.findIdMatch(map.getTo());
+ if (matched != null)
{
- if (map.getTo() != null && map.getMap() != null)
+ /*
+ * already got an xref to this sequence; update this
+ * map to point to the same sequence, and add
+ * any new dbrefs to it
+ */
+ DBRefEntry[] toRefs = map.getTo().getDBRefs();
+ if (toRefs != null)
{
- // 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
- // mapping and it is to the full protein translation of CDS
- SequenceI matched = findInDataset(dbref);
- // matcher.findIdMatch(map.getTo());
- if (matched != null)
- {
- /*
- * already got an xref to this sequence; update this
- * map to point to the same sequence, and add
- * any new dbrefs to it
- */
- DBRefEntry[] toRefs = map.getTo().getDBRefs();
- if (toRefs != null)
- {
- for (DBRefEntry ref : toRefs)
- {
- matched.addDBRef(ref); // add or update mapping
- }
- }
- map.setTo(matched);
- }
- else
+ for (DBRefEntry ref : toRefs)
{
- matcher.add(map.getTo());
+ matched.addDBRef(ref); // add or update mapping
}
- try
+ }
+ map.setTo(matched);
+ }
+ else
+ {
+ matcher.add(map.getTo());
+ }
+ try
+ {
+ // compare ms with dss and replace with dss in mapping
+ // if map is congruent
+ SequenceI ms = map.getTo();
+ int sf = map.getMap().getToLowest();
+ int st = map.getMap().getToHighest();
+ SequenceI mappedrg = ms.getSubSequence(sf, st);
+ // SequenceI loc = dss.getSubSequence(sf, st);
+ if (mappedrg.getLength() > 0
+ && ms.getSequenceAsString().equals(
+ dss.getSequenceAsString()))
+ // && mappedrg.getSequenceAsString().equals(
+ // loc.getSequenceAsString()))
+ {
+ String msg = "Mapping updated from " + ms.getName()
+ + " to retrieved crossreference "
+ + dss.getName();
+ System.out.println(msg);
+ map.setTo(dss);
+
+ /*
+ * give the reverse reference the inverse mapping
+ * (if it doesn't have one already)
+ */
+ setReverseMapping(dss, dbref, cf);
+
+ /*
+ * copy sequence features as well, avoiding
+ * duplication (e.g. same variation from two
+ * transcripts)
+ */
+ SequenceFeature[] sfs = ms.getSequenceFeatures();
+ if (sfs != null)
{
- // compare ms with dss and replace with dss in mapping
- // if map is congruent
- SequenceI ms = map.getTo();
- int sf = map.getMap().getToLowest();
- int st = map.getMap().getToHighest();
- SequenceI mappedrg = ms.getSubSequence(sf, st);
- // SequenceI loc = dss.getSubSequence(sf, st);
- if (mappedrg.getLength() > 0
- && ms.getSequenceAsString().equals(
- dss.getSequenceAsString()))
- // && mappedrg.getSequenceAsString().equals(
- // loc.getSequenceAsString()))
+ for (SequenceFeature feat : sfs)
{
- String msg = "Mapping updated from " + ms.getName()
- + " to retrieved crossreference "
- + dss.getName();
- System.out.println(msg);
- map.setTo(dss);
-
/*
- * give the reverse reference the inverse mapping
- * (if it doesn't have one already)
+ * make a flyweight feature object which ignores Parent
+ * attribute in equality test; this avoids creating many
+ * otherwise duplicate exon features on genomic sequence
*/
- setReverseMapping(dss, dbref, cf);
-
- /*
- * copy sequence features as well, avoiding
- * duplication (e.g. same variation from two
- * transcripts)
- */
- SequenceFeature[] sfs = ms.getSequenceFeatures();
- if (sfs != null)
+ SequenceFeature newFeature = new SequenceFeature(
+ feat)
{
- for (SequenceFeature feat : sfs)
+ @Override
+ public boolean equals(Object o)
{
- /*
- * 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)
- {
- return super.equals(o, true);
- }
- };
- dss.addSequenceFeature(newFeature);
+ return super.equals(o, true);
}
- }
+ };
+ dss.addSequenceFeature(newFeature);
}
- cf.addMap(retrievedDss, map.getTo(), map.getMap());
- } catch (Exception e)
- {
- System.err
- .println("Exception when consolidating Mapped sequence set...");
- e.printStackTrace(System.err);
}
}
+ cf.addMap(retrievedDss, map.getTo(), map.getMap());
+ } catch (Exception e)
+ {
+ System.err
+ .println("Exception when consolidating Mapped sequence set...");
+ e.printStackTrace(System.err);
}
}
}
- retrievedSequence.updatePDBIds();
- rseqs.add(retrievedDss);
- dataset.addSequence(retrievedDss);
- matcher.add(retrievedDss);
}
}
+ retrievedSequence.updatePDBIds();
+ rseqs.add(retrievedDss);
+ dataset.addSequence(retrievedDss);
+ matcher.add(retrievedDss);
}
}
-
- Alignment ral = null;
- if (rseqs.size() > 0)
- {
- ral = new Alignment(rseqs.toArray(new SequenceI[rseqs.size()]));
- if (!cf.isEmpty())
- {
- dataset.addCodonFrame(cf);
- }
- }
- return ral;
}
-
/**
* Sets the inverse sequence mapping in the corresponding dbref of the mapped
* to sequence (if any). This is used after fetching a cross-referenced
* @param retrieved
* @param acf
*/
- void updateDbrefMappings(SequenceI mapFrom,
- DBRefEntry[] xrefs, SequenceI[] retrieved, AlignedCodonFrame acf)
+ void updateDbrefMappings(SequenceI mapFrom, DBRefEntry[] xrefs,
+ SequenceI[] retrieved, AlignedCodonFrame acf, boolean fromDna)
{
SequenceIdMatcher matcher = new SequenceIdMatcher(retrieved);
for (DBRefEntry xref : xrefs)
}
for (SequenceI seq : matches)
{
- constructMapping(mapFrom, seq, xref, acf);
+ constructMapping(mapFrom, seq, xref, acf, fromDna);
}
}
}
* @return
*/
boolean constructMapping(SequenceI mapFrom, SequenceI mapTo,
- DBRefEntry xref, AlignedCodonFrame mappings)
+ DBRefEntry xref, AlignedCodonFrame mappings, boolean fromDna)
{
MapList mapping = null;
* dataset (that is not equal to sequenceI) Identifies matching DBRefEntry
* based on source and accession string only - Map and Version are nulled.
*
+ * @param fromDna
+ * - true if context was searching from Dna sequences, false if
+ * context was searching from Protein sequences
* @param sequenceI
* @param lrfs
* @param rseqs
* @return true if matches were found.
*/
- private boolean searchDatasetXrefs(SequenceI sequenceI,
+ private boolean searchDatasetXrefs(boolean fromDna, SequenceI sequenceI,
DBRefEntry[] lrfs, List<SequenceI> rseqs, AlignedCodonFrame cf)
{
boolean found = false;
// add in wildcards
xref.setVersion(null);
xref.setMap(null);
- found |= searchDataset(sequenceI, xref, rseqs, cf, false);
+ found |= searchDataset(fromDna, sequenceI, xref, rseqs, cf, false);
}
return found;
}
* Searches dataset for DBRefEntrys matching the given one (xrf) and adds the
* associated sequence to rseqs
*
+ * @param fromDna
+ * true if context was searching for refs *from* dna sequence, false
+ * if context was searching for refs *from* protein sequence
* @param sequenceI
* a sequence to ignore (start point of search)
* @param xrf
* @param cf
* a set of sequence mappings to add to
* @param direct
- * - search all references or only subset
+ * - indicates the type of relationship between returned sequences,
+ * xrf, and sequenceI that is required.
+ * <ul>
+ * <li>direct implies xrf is a primary reference for sequenceI AND
+ * the sequences to be located (eg a uniprot ID for a protein
+ * sequence, and a uniprot ref on a transcript sequence).</li>
+ * <li>indirect means xrf is a cross reference with respect to
+ * sequenceI or all the returned sequences (eg a genomic reference
+ * associated with a locus and one or more transcripts)</li>
+ * </ul>
* @return true if relationship found and sequence added.
*/
- boolean searchDataset(SequenceI sequenceI, DBRefEntry xrf,
- List<SequenceI> rseqs, AlignedCodonFrame cf, boolean direct)
+ boolean searchDataset(boolean fromDna, SequenceI sequenceI,
+ DBRefEntry xrf, List<SequenceI> rseqs, AlignedCodonFrame cf,
+ boolean direct)
{
boolean found = false;
if (dataset == null)
* complementary type if !direct
*/
{
- boolean isDna = Comparison
- .isNucleotide(new SequenceI[] { nxt });
+ boolean isDna = !nxt.isProtein();
if (direct ? (isDna != fromDna) : (isDna == fromDna))
{
// skip this sequence because it is wrong molecule type