X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fanalysis%2FAlignmentUtils.java;h=6ac59baf4a6dc8777b41eef470ada4e6152957d5;hb=d043ce47fc710d3eb2629ba926a8a7417bd67d8c;hp=cd142ca7a3434cbc19810d704cba8e11fde391b2;hpb=ce93212014c116c4c516c6dc85c5032449d311eb;p=jalview.git diff --git a/src/jalview/analysis/AlignmentUtils.java b/src/jalview/analysis/AlignmentUtils.java index cd142ca..6ac59ba 100644 --- a/src/jalview/analysis/AlignmentUtils.java +++ b/src/jalview/analysis/AlignmentUtils.java @@ -20,6 +20,25 @@ */ package jalview.analysis; +import java.util.Locale; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; + +import jalview.bin.Console; import jalview.commands.RemoveGapColCommand; import jalview.datamodel.AlignedCodon; import jalview.datamodel.AlignedCodonFrame; @@ -44,22 +63,6 @@ import jalview.util.IntRangeComparator; import jalview.util.MapList; import jalview.util.MappingUtils; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.NoSuchElementException; -import java.util.Set; -import java.util.SortedMap; -import java.util.TreeMap; - /** * grab bag of useful alignment manipulation operations Expect these to be * refactored elsewhere at some point. @@ -181,10 +184,10 @@ public class AlignmentUtils // TODO use Character.toLowerCase to avoid creating String objects? char[] upstream = new String(ds .getSequence(s.getStart() - 1 - ustream_ds, s.getStart() - 1)) - .toLowerCase().toCharArray(); + .toLowerCase(Locale.ROOT).toCharArray(); char[] downstream = new String( - ds.getSequence(s_end - 1, s_end + dstream_ds)).toLowerCase() - .toCharArray(); + ds.getSequence(s_end - 1, s_end + dstream_ds)) + .toLowerCase(Locale.ROOT).toCharArray(); char[] coreseq = s.getSequence(); char[] nseq = new char[offset + upstream.length + downstream.length + coreseq.length]; @@ -462,7 +465,8 @@ public class AlignmentUtils if (cdnaLength != mappedLength && cdnaLength > 2) { String lastCodon = String.valueOf(cdnaSeqChars, - cdnaLength - CODON_LENGTH, CODON_LENGTH).toUpperCase(); + cdnaLength - CODON_LENGTH, CODON_LENGTH) + .toUpperCase(Locale.ROOT); for (String stop : ResidueProperties.STOP_CODONS) { if (lastCodon.equals(stop)) @@ -479,7 +483,8 @@ public class AlignmentUtils */ int startOffset = 0; if (cdnaLength != mappedLength && cdnaLength > 2 - && String.valueOf(cdnaSeqChars, 0, CODON_LENGTH).toUpperCase() + && String.valueOf(cdnaSeqChars, 0, CODON_LENGTH) + .toUpperCase(Locale.ROOT) .equals(ResidueProperties.START)) { startOffset += CODON_LENGTH; @@ -960,12 +965,11 @@ public class AlignmentUtils .findMappingsForSequence(cdsSeq, mappings); for (AlignedCodonFrame mapping : dnaMappings) { - List foundMap=new ArrayList<>(); - SequenceI peptide = mapping.findAlignedSequence(cdsSeq, protein,foundMap); + SequenceI peptide = mapping.findAlignedSequence(cdsSeq, protein); if (peptide != null) { final int peptideLength = peptide.getLength(); - Mapping map = foundMap.get(0).getMapping(); + Mapping map = mapping.getMappingBetween(cdsSeq, peptide); if (map != null) { MapList mapList = map.getMap(); @@ -974,8 +978,8 @@ public class AlignmentUtils mapList = mapList.getInverse(); } final int cdsLength = cdsDss.getLength(); - int mappedFromLength = MappingUtils.getLength(mapList - .getFromRanges()); + int mappedFromLength = MappingUtils + .getLength(mapList.getFromRanges()); int mappedToLength = MappingUtils .getLength(mapList.getToRanges()); boolean addStopCodon = (cdsLength == mappedFromLength @@ -1460,28 +1464,31 @@ public class AlignmentUtils final List result = new ArrayList<>(); for (AlignmentAnnotation dsann : datasetAnnotations) { - /* - * Find matching annotations on the alignment. If none is found, then - * add this annotation to the list of 'addable' annotations for this - * sequence. - */ - final Iterable matchedAlignmentAnnotations = al - .findAnnotations(seq, dsann.getCalcId(), dsann.label); - if (!matchedAlignmentAnnotations.iterator().hasNext()) + if (dsann.annotations != null) // ignore non-positional annotation { - result.add(dsann); - if (labelForCalcId != null) + /* + * Find matching annotations on the alignment. If none is found, then + * add this annotation to the list of 'addable' annotations for this + * sequence. + */ + final Iterable matchedAlignmentAnnotations = al + .findAnnotations(seq, dsann.getCalcId(), dsann.label); + if (!matchedAlignmentAnnotations.iterator().hasNext()) { - labelForCalcId.put(dsann.getCalcId(), dsann.label); + result.add(dsann); + if (labelForCalcId != null) + { + labelForCalcId.put(dsann.getCalcId(), dsann.label); + } } } - } - /* - * Save any addable annotations for this sequence - */ - if (!result.isEmpty()) - { - candidates.put(seq, result); + /* + * Save any addable annotations for this sequence + */ + if (!result.isEmpty()) + { + candidates.put(seq, result); + } } } } @@ -1598,11 +1605,12 @@ public class AlignmentUtils return false; } String name = seq2.getName(); - final DBRefEntry[] xrefs = seq1.getDBRefs(); + final List xrefs = seq1.getDBRefs(); if (xrefs != null) { - for (DBRefEntry xref : xrefs) + for (int ix = 0, nx = xrefs.size(); ix < nx; ix++) { + DBRefEntry xref = xrefs.get(ix); String xrefName = xref.getSource() + "|" + xref.getAccessionId(); // case-insensitive test, consistent with DBRefEntry.equalRef() if (xrefName.equalsIgnoreCase(name)) @@ -1648,8 +1656,8 @@ public class AlignmentUtils productSeqs = new HashSet<>(); for (SequenceI seq : products) { - productSeqs.add(seq.getDatasetSequence() == null ? seq : seq - .getDatasetSequence()); + productSeqs.add(seq.getDatasetSequence() == null ? seq + : seq.getDatasetSequence()); } } @@ -1753,7 +1761,7 @@ public class AlignmentUtils dataset.addSequence(cdsSeqDss); AlignedCodonFrame cdsToProteinMapping = new AlignedCodonFrame(); cdsToProteinMapping.addMap(cdsSeqDss, proteinProduct, - cdsToProteinMap); + cdsToProteinMap); /* * guard against duplicating the mapping if repeating this action @@ -1803,22 +1811,24 @@ public class AlignmentUtils // need to // synthesize an xref. - for (DBRefEntry primRef : dnaDss.getPrimaryDBRefs()) + List primrefs = dnaDss.getPrimaryDBRefs(); + for (int ip = 0, np = primrefs.size(); ip < np; ip++) { + DBRefEntry primRef = primrefs.get(ip); /* * create a cross-reference from CDS to the source sequence's * primary reference and vice versa */ String source = primRef.getSource(); String version = primRef.getVersion(); - DBRefEntry cdsCrossRef = new DBRefEntry(source, source + ":" - + version, primRef.getAccessionId()); - cdsCrossRef.setMap(new Mapping(dnaDss, new MapList(cdsToDnaMap))); + DBRefEntry cdsCrossRef = new DBRefEntry(source, + source + ":" + version, primRef.getAccessionId()); + cdsCrossRef + .setMap(new Mapping(dnaDss, new MapList(cdsToDnaMap))); cdsSeqDss.addDBRef(cdsCrossRef); - dnaSeq.addDBRef(new DBRefEntry(source, version, cdsSeq - .getName(), new Mapping(cdsSeqDss, dnaToCdsMap))); - + dnaSeq.addDBRef(new DBRefEntry(source, version, + cdsSeq.getName(), new Mapping(cdsSeqDss, dnaToCdsMap))); // problem here is that the cross-reference is synthesized - // cdsSeq.getName() may be like 'CDS|dnaaccession' or // 'CDS|emblcdsacc' @@ -1827,11 +1837,10 @@ public class AlignmentUtils DBRefEntry proteinToCdsRef = new DBRefEntry(source, version, cdsSeq.getName()); // - proteinToCdsRef.setMap(new Mapping(cdsSeqDss, cdsToProteinMap - .getInverse())); + proteinToCdsRef.setMap( + new Mapping(cdsSeqDss, cdsToProteinMap.getInverse())); proteinProduct.addDBRef(proteinToCdsRef); } - /* * transfer any features on dna that overlap the CDS */ @@ -1841,8 +1850,8 @@ public class AlignmentUtils } } - AlignmentI cds = new Alignment(cdsSeqs.toArray(new SequenceI[cdsSeqs - .size()])); + AlignmentI cds = new Alignment( + cdsSeqs.toArray(new SequenceI[cdsSeqs.size()])); cds.setDataset(dataset); return cds; @@ -1995,45 +2004,31 @@ public class AlignmentUtils SequenceI newSeq = null; - final MapList maplist = mapping.getMap(); - if (maplist.isContiguous() && maplist.isFromForwardStrand()) - { - /* - * just a subsequence, keep same dataset sequence - */ - int start = maplist.getFromLowest(); - int end = maplist.getFromHighest(); - newSeq = seq.getSubSequence(start - 1, end); - newSeq.setName(seqId); - } - else - { - /* - * construct by splicing mapped from ranges - */ - char[] seqChars = seq.getSequence(); - List fromRanges = maplist.getFromRanges(); - int cdsWidth = MappingUtils.getLength(fromRanges); - char[] newSeqChars = new char[cdsWidth]; + /* + * construct CDS sequence by splicing mapped from ranges + */ + char[] seqChars = seq.getSequence(); + List fromRanges = mapping.getMap().getFromRanges(); + int cdsWidth = MappingUtils.getLength(fromRanges); + char[] newSeqChars = new char[cdsWidth]; - int newPos = 0; - for (int[] range : fromRanges) + int newPos = 0; + for (int[] range : fromRanges) + { + if (range[0] <= range[1]) { - if (range[0] <= range[1]) - { - // forward strand mapping - just copy the range - int length = range[1] - range[0] + 1; - System.arraycopy(seqChars, range[0] - 1, newSeqChars, newPos, - length); - newPos += length; - } - else + // forward strand mapping - just copy the range + int length = range[1] - range[0] + 1; + System.arraycopy(seqChars, range[0] - 1, newSeqChars, newPos, + length); + newPos += length; + } + else + { + // reverse strand mapping - copy and complement one by one + for (int i = range[0]; i >= range[1]; i--) { - // reverse strand mapping - copy and complement one by one - for (int i = range[0]; i >= range[1]; i--) - { - newSeqChars[newPos++] = Dna.getComplement(seqChars[i - 1]); - } + newSeqChars[newPos++] = Dna.getComplement(seqChars[i - 1]); } } @@ -2067,8 +2062,8 @@ public class AlignmentUtils } else { - System.err.println( - "JAL-2154 regression: warning - found (and ignnored a duplicate CDS sequence):" + Console.error( + "JAL-2154 regression: warning - found (and ignored) a duplicate CDS sequence:" + mtch.toString()); } } @@ -2097,13 +2092,15 @@ public class AlignmentUtils List direct = new ArrayList<>(); HashSet directSources = new HashSet<>(); - if (contig.getDBRefs() != null) + List refs = contig.getDBRefs(); + if (refs != null) { - for (DBRefEntry dbr : contig.getDBRefs()) + for (int ib = 0, nb = refs.size(); ib < nb; ib++) { - if (dbr.hasMap() && dbr.getMap().getMap().isTripletMap()) + DBRefEntry dbr = refs.get(ib); + MapList map; + if (dbr.hasMap() && (map = dbr.getMap().getMap()).isTripletMap()) { - MapList map = dbr.getMap().getMap(); // check if map is the CDS mapping if (mapping.getMap().equals(map)) { @@ -2113,21 +2110,22 @@ public class AlignmentUtils } } } - DBRefEntry[] onSource = DBRefUtils.selectRefs( + List onSource = DBRefUtils.selectRefs( proteinProduct.getDBRefs(), directSources.toArray(new String[0])); List propagated = new ArrayList<>(); // and generate appropriate mappings - for (DBRefEntry cdsref : direct) + for (int ic = 0, nc = direct.size(); ic < nc; ic++) { + DBRefEntry cdsref = direct.get(ic); + Mapping m = cdsref.getMap(); // 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()); + m.getMap().getToRanges(), 3, 1); + Mapping cdsmap = new Mapping(m.getTo(), m.getMap()); // create dbref DBRefEntry newref = new DBRefEntry(cdsref.getSource(), @@ -2190,9 +2188,9 @@ public class AlignmentUtils /* * get features, optionally restricted by an ontology term */ - List sfs = select == null ? fromSeq.getFeatures() - .getPositionalFeatures() : fromSeq.getFeatures() - .getFeaturesByOntology(select); + List sfs = select == null + ? fromSeq.getFeatures().getPositionalFeatures() + : fromSeq.getFeatures().getFeaturesByOntology(select); int count = 0; for (SequenceFeature sf : sfs) @@ -2337,8 +2335,8 @@ public class AlignmentUtils { List result = new ArrayList<>(); - List sfs = dnaSeq.getFeatures().getFeaturesByOntology( - SequenceOntologyI.CDS); + List sfs = dnaSeq.getFeatures() + .getFeaturesByOntology(SequenceOntologyI.CDS); if (sfs.isEmpty()) { return result; @@ -2350,10 +2348,14 @@ public class AlignmentUtils int phase = 0; try { - phase = Integer.parseInt(sf.getPhase()); + String s = sf.getPhase(); + if (s != null) + { + phase = Integer.parseInt(s); + } } catch (NumberFormatException e) { - // ignore + // leave as zero } /* * phase > 0 on first codon means 5' incomplete - skip to the start @@ -2406,19 +2408,25 @@ public class AlignmentUtils SequenceIdMatcher matcher = new SequenceIdMatcher(seqs); if (xrefs != null) { - for (SequenceI xref : xrefs) + // BH 2019.01.25 recoded to remove iterators + + for (int ix = 0, nx = xrefs.length; ix < nx; ix++) { - DBRefEntry[] dbrefs = xref.getDBRefs(); + SequenceI xref = xrefs[ix]; + List dbrefs = xref.getDBRefs(); if (dbrefs != null) { - for (DBRefEntry dbref : dbrefs) + for (int ir = 0, nir = dbrefs.size(); ir < nir; ir++) { - if (dbref.getMap() == null || dbref.getMap().getTo() == null - || dbref.getMap().getTo().isProtein() != isProtein) + DBRefEntry dbref = dbrefs.get(ir); + Mapping map = dbref.getMap(); + SequenceI mto; + if (map == null || (mto = map.getTo()) == null + || mto.isProtein() != isProtein) { continue; } - SequenceI mappedTo = dbref.getMap().getTo(); + SequenceI mappedTo = mto; SequenceI match = matcher.findIdMatch(mappedTo); if (match == null) { @@ -2519,10 +2527,10 @@ public class AlignmentUtils * true; else returns false * * @param unaligned - * - sequences to be aligned based on aligned + * - sequences to be aligned based on aligned * @param aligned - * - 'guide' alignment containing sequences derived from same - * dataset as unaligned + * - 'guide' alignment containing sequences derived from same dataset + * as unaligned * @return */ static boolean alignAsSameSequences(AlignmentI unaligned, @@ -2558,8 +2566,7 @@ public class AlignmentUtils { return false; } - SequenceI alignedSeq = alignedDatasets.get(ds) - .get(0); + SequenceI alignedSeq = alignedDatasets.get(ds).get(0); int startCol = alignedSeq.findIndex(seq.getStart()); // 1.. leftmost = Math.min(leftmost, startCol); }