X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fanalysis%2FAlignmentUtils.java;h=1158c53bb37dec432977f5bf1182587fe9d9ae3b;hb=b15a4dfe51ded457b2850f14c19b5245aadb918e;hp=9a63eb177b83205ab771e590de3e9e7bdbeeb537;hpb=c604058f0c3be7bd38baa8ac01cff87989deecd5;p=jalview.git diff --git a/src/jalview/analysis/AlignmentUtils.java b/src/jalview/analysis/AlignmentUtils.java index 9a63eb1..1158c53 100644 --- a/src/jalview/analysis/AlignmentUtils.java +++ b/src/jalview/analysis/AlignmentUtils.java @@ -29,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; @@ -36,7 +37,7 @@ import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; -import jalview.bin.Cache; +import jalview.bin.Console; import jalview.commands.RemoveGapColCommand; import jalview.datamodel.AlignedCodon; import jalview.datamodel.AlignedCodonFrame; @@ -44,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; @@ -182,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]; @@ -463,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)) @@ -480,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; @@ -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 @@ -1467,7 +1471,19 @@ public class AlignmentUtils */ final Iterable matchedAlignmentAnnotations = al .findAnnotations(seq, dsann.getCalcId(), dsann.label); - if (!matchedAlignmentAnnotations.iterator().hasNext()) + boolean found = false; + if (matchedAlignmentAnnotations != null) + { + for (AlignmentAnnotation matched : matchedAlignmentAnnotations) + { + if (dsann.description.equals(matched.description)) + { + found = true; + break; + } + } + } + if (!found) { result.add(dsann); if (labelForCalcId != null) @@ -1488,7 +1504,8 @@ public class AlignmentUtils /** * Adds annotations to the top of the alignment annotations, in the same order - * as their related sequences. + * as their related sequences. If you already have an annotation and want to + * add it to a sequence in an alignment use {@code addReferenceAnnotationTo} * * @param annotations * the annotations to add @@ -1505,31 +1522,60 @@ public class AlignmentUtils { for (AlignmentAnnotation ann : annotations.get(seq)) { - AlignmentAnnotation copyAnn = new AlignmentAnnotation(ann); - int startRes = 0; - int endRes = ann.annotations.length; - if (selectionGroup != null) - { - startRes = selectionGroup.getStartRes(); - endRes = selectionGroup.getEndRes(); - } - copyAnn.restrict(startRes, endRes); + addReferenceAnnotationTo(alignment, seq, ann, selectionGroup); + } + } + } - /* - * Add to the sequence (sets copyAnn.datasetSequence), unless the - * original annotation is already on the sequence. - */ - if (!seq.hasAnnotation(ann)) - { - seq.addAlignmentAnnotation(copyAnn); - } - // adjust for gaps - copyAnn.adjustForAlignment(); - // add to the alignment and set visible - alignment.addAnnotation(copyAnn); - copyAnn.visible = true; + /** + * Make a copy of a reference annotation {@code ann} and add it to an + * alignment sequence {@code seq} in {@code alignment}, optionally limited to + * the extent of {@code selectionGroup} + * + * @param alignment + * @param seq + * @param ann + * @param selectionGroup + * - may be null + * @return annotation added to {@code seq and {@code alignment} + */ + public static AlignmentAnnotation addReferenceAnnotationTo( + final AlignmentI alignment, final SequenceI seq, + final AlignmentAnnotation ann, final SequenceGroup selectionGroup) + { + AlignmentAnnotation copyAnn = new AlignmentAnnotation(ann); + int startRes = 0; + int endRes = ann.annotations.length; + if (selectionGroup != null) + { + startRes = -1 + Math.min(seq.getEnd(), Math.max(seq.getStart(), + seq.findPosition(selectionGroup.getStartRes()))); + endRes = -1 + Math.min(seq.getEnd(), + seq.findPosition(selectionGroup.getEndRes())); + + } + copyAnn.restrict(startRes, endRes + 0); + + /* + * Add to the sequence (sets copyAnn.datasetSequence), unless the + * original annotation is already on the sequence. + */ + if (!seq.hasAnnotation(ann)) + { + ContactMatrixI cm = seq.getDatasetSequence().getContactMatrixFor(ann); + if (cm != null) + { + seq.addContactListFor(copyAnn, cm); } + seq.addAlignmentAnnotation(copyAnn); } + // adjust for gaps + copyAnn.adjustForAlignment(); + // add to the alignment and set visible + alignment.addAnnotation(copyAnn); + copyAnn.visible = true; + + return copyAnn; } /** @@ -1569,6 +1615,21 @@ public class AlignmentUtils } } + public static AlignmentAnnotation getFirstSequenceAnnotationOfType( + AlignmentI al, int graphType) + { + AlignmentAnnotation[] anns = al.getAlignmentAnnotation(); + if (anns != null) + { + for (AlignmentAnnotation aa : anns) + { + if (aa.sequenceRef != null && aa.graph == graphType) + return aa; + } + } + return null; + } + /** * Returns true if either sequence has a cross-reference to the other * @@ -1649,8 +1710,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()); } } @@ -1754,7 +1815,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 @@ -1807,20 +1868,21 @@ public class AlignmentUtils List primrefs = dnaDss.getPrimaryDBRefs(); for (int ip = 0, np = primrefs.size(); ip < np; ip++) { - DBRefEntry primRef = primrefs.get(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' @@ -1829,8 +1891,8 @@ 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); } /* @@ -1842,8 +1904,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; @@ -2054,8 +2116,9 @@ public class AlignmentUtils } else { - Cache.log.error( - "JAL-2154 regression: warning - found (and ignored) a duplicate CDS sequence:" + mtch.toString()); + Console.error( + "JAL-2154 regression: warning - found (and ignored) a duplicate CDS sequence:" + + mtch.toString()); } } } @@ -2179,9 +2242,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) @@ -2326,8 +2389,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; @@ -2339,11 +2402,11 @@ public class AlignmentUtils int phase = 0; try { - String s = sf.getPhase(); - if (s != null) - { - phase = Integer.parseInt(s); - } + String s = sf.getPhase(); + if (s != null) + { + phase = Integer.parseInt(s); + } } catch (NumberFormatException e) { // leave as zero @@ -2399,11 +2462,11 @@ public class AlignmentUtils SequenceIdMatcher matcher = new SequenceIdMatcher(seqs); if (xrefs != null) { - // BH 2019.01.25 recoded to remove iterators - + // BH 2019.01.25 recoded to remove iterators + for (int ix = 0, nx = xrefs.length; ix < nx; ix++) { - SequenceI xref = xrefs[ix]; + SequenceI xref = xrefs[ix]; List dbrefs = xref.getDBRefs(); if (dbrefs != null) { @@ -2518,10 +2581,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, @@ -2557,8 +2620,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); }