import static jalview.io.gff.GffConstants.CLINICAL_SIGNIFICANCE;
-import jalview.api.DBRefEntryI;
import jalview.datamodel.AlignedCodon;
import jalview.datamodel.AlignedCodonFrame;
import jalview.datamodel.AlignedCodonFrame.SequenceToSequenceMapping;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Set;
+import java.util.SortedMap;
import java.util.TreeMap;
/**
{
private static final int CODON_LENGTH = 3;
+
private static final String SEQUENCE_VARIANT = "sequence_variant:";
+
private static final String ID = "ID";
/**
*/
if (cdnaLength != mappedLength && cdnaLength > 2)
{
- String lastCodon = String.valueOf(cdnaSeqChars, cdnaLength - CODON_LENGTH, CODON_LENGTH)
- .toUpperCase();
+ String lastCodon = String.valueOf(cdnaSeqChars,
+ cdnaLength - CODON_LENGTH, CODON_LENGTH).toUpperCase();
for (String stop : ResidueProperties.STOP)
{
if (lastCodon.equals(stop))
int aaPos = 0;
int dnaPos = cdnaStart;
- for (; dnaPos < cdnaSeqChars.length - 2
- && aaPos < aaSeqChars.length; dnaPos += CODON_LENGTH, aaPos++)
+ for (; dnaPos < cdnaSeqChars.length - 2 && aaPos < aaSeqChars.length; dnaPos += CODON_LENGTH, aaPos++)
{
String codon = String.valueOf(cdnaSeqChars, dnaPos, CODON_LENGTH);
final String translated = ResidueProperties.codonTranslate(codon);
.println("alignCdsSequenceAsProtein needs aligned sequence!");
return false;
}
-
+
List<AlignedCodonFrame> dnaMappings = MappingUtils
.findMappingsForSequence(cdsSeq, mappings);
for (AlignedCodonFrame mapping : dnaMappings)
.getFromRanges());
int mappedToLength = MappingUtils
.getLength(mapList.getToRanges());
- boolean addStopCodon = (cdsLength == mappedFromLength * CODON_LENGTH + CODON_LENGTH)
+ boolean addStopCodon = (cdsLength == mappedFromLength
+ * CODON_LENGTH + CODON_LENGTH)
|| (peptide.getDatasetSequence().getLength() == mappedFromLength - 1);
if (cdsLength != mappedToLength && !addStopCodon)
{
// TODO resolve JAL-2022 so this fudge can be removed
int mappedSequenceCount = protein.getHeight() - unmappedProtein.size();
addUnmappedPeptideStarts(alignedCodons, mappedSequenceCount);
-
+
return alignedCodons;
}
* didn't find mapped CDS sequence - construct it and add
* its dataset sequence to the dataset
*/
- cdsSeq = makeCdsSequence(dnaSeq.getDatasetSequence(), aMapping);
- SequenceI cdsSeqDss = cdsSeq.createDatasetSequence();
+ cdsSeq = makeCdsSequence(dnaSeq.getDatasetSequence(), aMapping,
+ dataset).deriveSequence();
+ // cdsSeq has a name constructed as CDS|<dbref>
+ // <dbref> will be either the accession for the coding sequence,
+ // marked in the /via/ dbref to the protein product accession
+ // or it will be the original nucleotide accession.
+ SequenceI cdsSeqDss = cdsSeq.getDatasetSequence();
+
cdsSeqs.add(cdsSeq);
+
if (!dataset.getSequences().contains(cdsSeqDss))
{
+ // check if this sequence is a newly created one
+ // so needs adding to the dataset
dataset.addSequence(cdsSeqDss);
}
*/
List<int[]> cdsRange = Collections.singletonList(new int[] { 1,
cdsSeq.getLength() });
- MapList cdsToProteinMap = new MapList(cdsRange, mapList.getToRanges(),
- mapList.getFromRatio(), mapList.getToRatio());
+ MapList cdsToProteinMap = new MapList(cdsRange,
+ mapList.getToRanges(), mapList.getFromRatio(),
+ mapList.getToRatio());
AlignedCodonFrame cdsToProteinMapping = new AlignedCodonFrame();
- cdsToProteinMapping.addMap(cdsSeq, proteinProduct, cdsToProteinMap);
+ cdsToProteinMapping.addMap(cdsSeqDss, proteinProduct,
+ cdsToProteinMap);
/*
* guard against duplicating the mapping if repeating this action
mappings.add(cdsToProteinMapping);
}
- /*
- * copy protein's dbrefs to CDS sequence
- * this enables Get Cross-References from CDS alignment
- */
- DBRefEntry[] proteinRefs = DBRefUtils.selectDbRefs(false,
- proteinProduct.getDBRefs());
- if (proteinRefs != null)
- {
- for (DBRefEntry ref : proteinRefs)
- {
- DBRefEntry cdsToProteinRef = new DBRefEntry(ref);
- cdsToProteinRef.setMap(new Mapping(proteinProduct,
- cdsToProteinMap));
- cdsSeqDss.addDBRef(cdsToProteinRef);
- }
- }
-
+ propagateDBRefsToCDS(cdsSeqDss, dnaSeq.getDatasetSequence(),
+ proteinProduct, aMapping);
/*
* add another mapping from original 'from' range to CDS
*/
AlignedCodonFrame dnaToCdsMapping = new AlignedCodonFrame();
MapList dnaToCdsMap = new MapList(mapList.getFromRanges(),
- cdsRange, 1,
- 1);
- dnaToCdsMapping.addMap(dnaSeq.getDatasetSequence(), cdsSeq,
+ cdsRange, 1, 1);
+ dnaToCdsMapping.addMap(dnaSeq.getDatasetSequence(), cdsSeqDss,
dnaToCdsMap);
if (!mappings.contains(dnaToCdsMapping))
{
* same source and accession, so need a different accession for
* the CDS from the dna sequence
*/
- DBRefEntryI dnaRef = dnaDss.getSourceDBRef();
- if (dnaRef != null)
+
+ // specific use case:
+ // Genomic contig ENSCHR:1, contains coding regions for ENSG01,
+ // ENSG02, ENSG03, with transcripts and products similarly named.
+ // cannot add distinct dbrefs mapping location on ENSCHR:1 to ENSG01
+
+ // JBPNote: ?? can't actually create an example that demonstrates we
+ // need to
+ // synthesize an xref.
+
+ for (DBRefEntry primRef : dnaDss.getPrimaryDBRefs())
{
+ // creates a complementary cross-reference to the source sequence's
+ // primary reference.
+
+ DBRefEntry cdsCrossRef = new DBRefEntry(primRef.getSource(),
+ primRef.getSource() + ":" + primRef.getVersion(),
+ primRef.getAccessionId());
+ cdsCrossRef
+ .setMap(new Mapping(dnaDss, new MapList(dnaToCdsMap)));
+ cdsSeqDss.addDBRef(cdsCrossRef);
+
+ // problem here is that the cross-reference is synthesized -
+ // cdsSeq.getName() may be like 'CDS|dnaaccession' or
+ // 'CDS|emblcdsacc'
// assuming cds version same as dna ?!?
- DBRefEntry proteinToCdsRef = new DBRefEntry(dnaRef.getSource(),
- dnaRef.getVersion(), cdsSeq.getName());
+
+ DBRefEntry proteinToCdsRef = new DBRefEntry(
+ primRef.getSource(), primRef.getVersion(),
+ cdsSeq.getName());
+ //
proteinToCdsRef.setMap(new Mapping(cdsSeqDss, cdsToProteinMap
.getInverse()));
proteinProduct.addDBRef(proteinToCdsRef);
/*
* transfer any features on dna that overlap the CDS
*/
- transferFeatures(dnaSeq, cdsSeq, cdsToProteinMap, null,
+ transferFeatures(dnaSeq, cdsSeq, dnaToCdsMap, null,
SequenceOntologyI.CDS);
}
}
int mappedFromLength = MappingUtils.getLength(aMapping.getMap()
.getFromRanges());
int dnaLength = seqDss.getLength();
- if (mappedFromLength == dnaLength || mappedFromLength == dnaLength - CODON_LENGTH)
+ if (mappedFromLength == dnaLength
+ || mappedFromLength == dnaLength - CODON_LENGTH)
{
return seqDss;
}
for (SequenceToSequenceMapping map : acf.getMappings())
{
Mapping mapping = map.getMapping();
- if (mapping != aMapping && mapping.getMap().getFromRatio() == CODON_LENGTH
+ if (mapping != aMapping
+ && mapping.getMap().getFromRatio() == CODON_LENGTH
&& proteinProduct == mapping.getTo()
&& seqDss != map.getFromSeq())
{
*
* @param seq
* @param mapping
+ * @param dataset
+ * - existing dataset. We check for sequences that look like the CDS
+ * we are about to construct, if one exists already, then we will
+ * just return that one.
* @return CDS sequence (as a dataset sequence)
*/
- static SequenceI makeCdsSequence(SequenceI seq, Mapping mapping)
+ static SequenceI makeCdsSequence(SequenceI seq, Mapping mapping,
+ AlignmentI dataset)
{
char[] seqChars = seq.getSequence();
List<int[]> fromRanges = mapping.getMap().getFromRanges();
String mapFromId = mapping.getMappedFromId();
String seqId = "CDS|" + (mapFromId != null ? mapFromId : seq.getName());
SequenceI newSeq = new Sequence(seqId, newSeqChars, 1, newPos);
+ if (dataset != null)
+ {
+ SequenceI[] matches = dataset.findSequenceMatch(newSeq.getName());
+ if (matches != null)
+ {
+ boolean matched = false;
+ for (SequenceI mtch : matches)
+ {
+ if (mtch.getStart() != newSeq.getStart())
+ {
+ continue;
+ }
+ if (mtch.getEnd() != newSeq.getEnd())
+ {
+ continue;
+ }
+ if (!Arrays.equals(mtch.getSequence(), newSeq.getSequence()))
+ {
+ continue;
+ }
+ if (!matched)
+ {
+ matched = true;
+ newSeq = mtch;
+ }
+ else
+ {
+ System.err
+ .println("JAL-2154 regression: warning - found (and ignnored a duplicate CDS sequence):"
+ + mtch.toString());
+ }
+ }
+ }
+ }
// newSeq.setDescription(mapFromId);
return newSeq;
}
/**
+ * add any DBRefEntrys to cdsSeq from contig that have a Mapping congruent to
+ * the given mapping.
+ *
+ * @param cdsSeq
+ * @param contig
+ * @param mapping
+ * @return list of DBRefEntrys added.
+ */
+ public static List<DBRefEntry> propagateDBRefsToCDS(SequenceI cdsSeq,
+ SequenceI contig, SequenceI proteinProduct, Mapping mapping)
+ {
+
+ // gather direct refs from contig congrent with mapping
+ List<DBRefEntry> direct = new ArrayList<DBRefEntry>();
+ HashSet<String> directSources = new HashSet<String>();
+ if (contig.getDBRefs() != null)
+ {
+ for (DBRefEntry dbr : contig.getDBRefs())
+ {
+ if (dbr.hasMap() && dbr.getMap().getMap().isTripletMap())
+ {
+ MapList map = dbr.getMap().getMap();
+ // check if map is the CDS mapping
+ if (mapping.getMap().equals(map))
+ {
+ direct.add(dbr);
+ directSources.add(dbr.getSource());
+ }
+ }
+ }
+ }
+ DBRefEntry[] onSource = DBRefUtils.selectRefs(
+ proteinProduct.getDBRefs(),
+ directSources.toArray(new String[0]));
+ List<DBRefEntry> propagated = new ArrayList<DBRefEntry>();
+
+ // and generate appropriate mappings
+ for (DBRefEntry cdsref : direct)
+ {
+ // clone maplist and mapping
+ MapList cdsposmap = new MapList(Arrays.asList(new int[][] { new int[]
+ { cdsSeq.getStart(), cdsSeq.getEnd() } }), cdsref.getMap().getMap()
+ .getToRanges(), 3, 1);
+ Mapping cdsmap = new Mapping(cdsref.getMap().getTo(), cdsref.getMap()
+ .getMap());
+
+ // create dbref
+ DBRefEntry newref = new DBRefEntry(cdsref.getSource(),
+ cdsref.getVersion(), cdsref.getAccessionId(), new Mapping(
+ cdsmap.getTo(), cdsposmap));
+
+ // and see if we can map to the protein product for this mapping.
+ // onSource is the filtered set of accessions on protein that we are
+ // tranferring, so we assume accession is the same.
+ if (cdsmap.getTo() == null && onSource != null)
+ {
+ List<DBRefEntry> sourceRefs = DBRefUtils.searchRefs(onSource,
+ cdsref.getAccessionId());
+ if (sourceRefs != null)
+ {
+ for (DBRefEntry srcref : sourceRefs)
+ {
+ if (srcref.getSource().equalsIgnoreCase(cdsref.getSource()))
+ {
+ // we have found a complementary dbref on the protein product, so
+ // update mapping's getTo
+ newref.getMap().setTo(proteinProduct);
+ }
+ }
+ }
+ }
+ cdsSeq.addDBRef(newref);
+ propagated.add(newref);
+ }
+ return propagated;
+ }
+
+ /**
* Transfers co-located features on 'fromSeq' to 'toSeq', adjusting the
* feature start/end ranges, optionally omitting specified feature types.
* Returns the number of features copied.
StringBuilder link = new StringBuilder(32);
try
{
- link.append(desc).append(" ").append(id)
+ link.append(desc)
+ .append(" ")
+ .append(id)
.append("|http://www.ensembl.org/Homo_sapiens/Variation/Summary?v=")
.append(URLEncoder.encode(id, "UTF-8"));
sf.addLink(link.toString());
// as if
}
}
- String clinSig = (String) var.variant
- .getValue(CLINICAL_SIGNIFICANCE);
+ String clinSig = (String) var.variant.getValue(CLINICAL_SIGNIFICANCE);
if (clinSig != null)
{
sf.setValue(CLINICAL_SIGNIFICANCE, clinSig);
{
AlignmentI copy = new Alignment(new Alignment(seqs));
copy.setDataset(dataset);
-
+ boolean isProtein = !copy.isNucleotide();
SequenceIdMatcher matcher = new SequenceIdMatcher(seqs);
if (xrefs != null)
{
{
for (DBRefEntry dbref : dbrefs)
{
- if (dbref.getMap() == null || dbref.getMap().getTo() == null)
+ if (dbref.getMap() == null || dbref.getMap().getTo() == null
+ || dbref.getMap().getTo().isProtein() != isProtein)
{
continue;
}
}
newCol++;
}
-
+
/*
* trim trailing gaps
*/
* @param unmapped
* @return
*/
- static Map<Integer, Map<SequenceI, Character>> buildMappedColumnsMap(
+ static SortedMap<Integer, Map<SequenceI, Character>> buildMappedColumnsMap(
AlignmentI unaligned, AlignmentI aligned, List<SequenceI> unmapped)
{
/*
* {unalignedSequence, characterPerSequence} at that position.
* TreeMap keeps the entries in ascending column order.
*/
- Map<Integer, Map<SequenceI, Character>> map = new TreeMap<Integer, Map<SequenceI, Character>>();
+ SortedMap<Integer, Map<SequenceI, Character>> map = new TreeMap<Integer, Map<SequenceI, Character>>();
/*
* record any sequences that have no mapping so can't be realigned