From: gmungoc Date: Mon, 21 Aug 2017 13:06:46 +0000 (+0100) Subject: Merge branch 'develop' into features/JAL-2446NCList X-Git-Tag: Release_2_10_3b1~150 X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=be762d8d9c71a7aa3121e845c45911c7192b7827;hp=-c;p=jalview.git Merge branch 'develop' into features/JAL-2446NCList Conflicts: src/MCview/PDBChain.java src/jalview/analysis/AlignmentSorter.java src/jalview/analysis/AlignmentUtils.java src/jalview/analysis/Dna.java src/jalview/appletgui/AlignFrame.java src/jalview/appletgui/FeatureRenderer.java src/jalview/appletgui/Finder.java src/jalview/appletgui/SeqPanel.java src/jalview/commands/EditCommand.java src/jalview/datamodel/AlignedCodonFrame.java src/jalview/datamodel/Sequence.java src/jalview/datamodel/SequenceFeature.java src/jalview/datamodel/xdb/embl/EmblEntry.java src/jalview/ext/ensembl/EnsemblGene.java src/jalview/gui/AlignmentPanel.java src/jalview/gui/AnnotationExporter.java src/jalview/gui/CutAndPasteTransfer.java src/jalview/gui/FeatureRenderer.java src/jalview/gui/Finder.java src/jalview/gui/PopupMenu.java src/jalview/gui/SeqCanvas.java src/jalview/gui/SeqPanel.java src/jalview/io/FeaturesFile.java src/jalview/io/JSONFile.java src/jalview/io/gff/InterProScanHelper.java src/jalview/io/vamsas/Datasetsequence.java src/jalview/renderer/seqfeatures/FeatureRenderer.java src/jalview/util/RangeComparator.java src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java src/jalview/ws/jws2/AADisorderClient.java --- be762d8d9c71a7aa3121e845c45911c7192b7827 diff --combined src/MCview/PDBChain.java index 8285d88,f2dd3d0..f4bd31c --- a/src/MCview/PDBChain.java +++ b/src/MCview/PDBChain.java @@@ -41,11 -41,11 +41,6 @@@ public class PDBChai { public static final String RESNUM_FEATURE = "RESNUM"; -- /** -- * SequenceFeature group for PDB File features added to sequences -- */ -- private static final String PDBFILEFEATURE = "PDBFile"; -- private static final String IEASTATUS = "IEA:jalview"; public String id; @@@ -83,10 -83,10 +78,10 @@@ public String pdbid = ""; -- public PDBChain(String pdbid, String id) ++ public PDBChain(String thePdbid, String theId) { -- this.pdbid = pdbid == null ? pdbid : pdbid.toLowerCase(); -- this.id = id; ++ this.pdbid = thePdbid == null ? thePdbid : thePdbid.toLowerCase(); ++ this.id = theId; } /** @@@ -167,14 -167,15 +162,14 @@@ } /** - * copy over the RESNUM seqfeatures from the internal chain sequence to the + * Copies over the RESNUM seqfeatures from the internal chain sequence to the * mapped sequence * * @param seq * @param status * The Status of the transferred annotation - * @return the features added to sq (or its dataset) */ - public SequenceFeature[] transferRESNUMFeatures(SequenceI seq, + public void transferRESNUMFeatures(SequenceI seq, String status) { SequenceI sq = seq; @@@ -183,11 -184,10 +178,11 @@@ sq = sq.getDatasetSequence(); if (sq == sequence) { - return null; + return; } } - /** + + /* * Remove any existing features for this chain if they exist ? * SequenceFeature[] seqsfeatures=seq.getSequenceFeatures(); int * totfeat=seqsfeatures.length; // Remove any features for this exact chain @@@ -197,21 -197,24 +192,22 @@@ { status = PDBChain.IEASTATUS; } - SequenceFeature[] features = sequence.getSequenceFeatures(); - if (features == null) - { - return null; - } - for (int i = 0; i < features.length; i++) + + List features = sequence.getSequenceFeatures(); + for (SequenceFeature feature : features) { - if (features[i].getFeatureGroup() != null - && features[i].getFeatureGroup().equals(pdbid)) + if (feature.getFeatureGroup() != null + && feature.getFeatureGroup().equals(pdbid)) { - SequenceFeature tx = new SequenceFeature(features[i]); - tx.setBegin(1 + residues.elementAt(tx.getBegin() - offset).atoms - .elementAt(0).alignmentMapping); - tx.setEnd(1 + residues.elementAt(tx.getEnd() - offset).atoms - .elementAt(0).alignmentMapping); + int newBegin = 1 + residues.elementAt(feature.getBegin() - offset).atoms + .elementAt(0).alignmentMapping; + int newEnd = 1 + residues.elementAt(feature.getEnd() - offset).atoms + .elementAt(0).alignmentMapping; + SequenceFeature tx = new SequenceFeature(feature, newBegin, newEnd, + feature.getFeatureGroup(), feature.getScore()); tx.setStatus(status - + ((tx.getStatus() == null || tx.getStatus().length() == 0) ? "" + + ((tx.getStatus() == null || tx.getStatus().length() == 0) + ? "" : ":" + tx.getStatus())); if (tx.begin != 0 && tx.end != 0) { @@@ -219,6 -222,7 +215,6 @@@ } } } - return features; } /** @@@ -346,47 -350,48 +342,48 @@@ // Add inserted residues as features to the base residue Atom currAtom = resAtoms.get(0); - if (currAtom.insCode != ' ' - && !residues.isEmpty() - && residues.lastElement().atoms.get(0).resNumber == currAtom.resNumber) + if (currAtom.insCode != ' ' && !residues.isEmpty() + && residues.lastElement().atoms + .get(0).resNumber == currAtom.resNumber) { - SequenceFeature sf = new SequenceFeature("INSERTION", - currAtom.resName + ":" + currAtom.resNumIns + " " + pdbid - + id, - "", offset + count - 1, offset + count - 1, "PDB_INS"); + String desc = currAtom.resName + ":" + currAtom.resNumIns + " " + + pdbid + id; + SequenceFeature sf = new SequenceFeature("INSERTION", desc, offset + + count - 1, offset + count - 1, "PDB_INS"); resFeatures.addElement(sf); residues.lastElement().atoms.addAll(resAtoms); } else { - // Make a new Residue object with the new atoms vector residues.addElement(new Residue(resAtoms, resNumber - 1, count)); Residue tmpres = residues.lastElement(); Atom tmpat = tmpres.atoms.get(0); // Make A new SequenceFeature for the current residue numbering - SequenceFeature sf = new SequenceFeature(RESNUM_FEATURE, - tmpat.resName + ":" + tmpat.resNumIns + " " + pdbid + id, - "", offset + count, offset + count, pdbid); + String desc = tmpat.resName + + ":" + tmpat.resNumIns + " " + pdbid + id; + SequenceFeature sf = new SequenceFeature(RESNUM_FEATURE, desc, + offset + count, offset + count, pdbid); resFeatures.addElement(sf); resAnnotation.addElement(new Annotation(tmpat.tfactor)); // Keep totting up the sequence - if ((symbol = ResidueProperties.getAA3Hash().get(tmpat.resName)) == null) + if ((symbol = ResidueProperties.getAA3Hash() + .get(tmpat.resName)) == null) { String nucname = tmpat.resName.trim(); // use the aaIndex rather than call 'toLower' - which would take a bit // more time. deoxyn = nucname.length() == 2 - && ResidueProperties.aaIndex[nucname.charAt(0)] == ResidueProperties.aaIndex['D']; + && ResidueProperties.aaIndex[nucname + .charAt(0)] == ResidueProperties.aaIndex['D']; if (tmpat.name.equalsIgnoreCase("CA") || ResidueProperties.nucleotideIndex[nucname .charAt((deoxyn ? 1 : 0))] == -1) { - char r = ResidueProperties - .getSingleCharacterCode(ResidueProperties - .getCanonicalAminoAcid(tmpat.resName)); + char r = ResidueProperties.getSingleCharacterCode( + ResidueProperties.getCanonicalAminoAcid(tmpat.resName)); seq.append(r == '0' ? 'X' : r); // System.err.println("PDBReader:Null aa3Hash for " + // tmpat.resName); @@@ -402,8 -407,8 +399,8 @@@ { if (nucleotide) { - System.err - .println("Warning: mixed nucleotide and amino acid chain.. its gonna do bad things to you!"); + System.err.println( + "Warning: mixed nucleotide and amino acid chain.. its gonna do bad things to you!"); } seq.append(ResidueProperties.aa[((Integer) symbol).intValue()]); } @@@ -515,8 -520,8 +512,8 @@@ try { index = ResidueProperties.aa3Hash.get(b.at1.resName).intValue(); - b.startCol = cs.findColour(ResidueProperties.aa[index].charAt(0), - 0, null, null, 0f); + b.startCol = cs.findColour(ResidueProperties.aa[index].charAt(0), 0, + null, null, 0f); index = ResidueProperties.aa3Hash.get(b.at2.resName).intValue(); b.endCol = cs.findColour(ResidueProperties.aa[index].charAt(0), 0, @@@ -566,8 -571,8 +563,8 @@@ for (AlignmentAnnotation ana : shadow.getAnnotation()) { - List transfer = sq.getAlignmentAnnotations( - ana.getCalcId(), ana.label); + List transfer = sq + .getAlignmentAnnotations(ana.getCalcId(), ana.label); if (transfer == null || transfer.size() == 0) { ana = new AlignmentAnnotation(ana); @@@ -608,7 -613,8 +605,8 @@@ // Useful for debugging mappings - adds annotation for mapped position float min = -1, max = 0; Annotation[] an = new Annotation[sq.getEnd() - sq.getStart() + 1]; - for (int i = sq.getStart(), j = sq.getEnd(), k = 0; i <= j; i++, k++) + for (int i = sq.getStart(), j = sq + .getEnd(), k = 0; i <= j; i++, k++) { int prn = mapping.getPDBResNum(k + 1); diff --combined src/jalview/analysis/AAFrequency.java index a792d24,f8e8379..e4f2dfa --- a/src/jalview/analysis/AAFrequency.java +++ b/src/jalview/analysis/AAFrequency.java @@@ -147,13 -147,14 +147,13 @@@ public class AAFrequenc { if (sequences[row] == null) { - System.err - .println("WARNING: Consensus skipping null sequence - possible race condition."); + System.err.println( + "WARNING: Consensus skipping null sequence - possible race condition."); continue; } - char[] seq = sequences[row].getSequence(); - if (seq.length > column) + if (sequences[row].getLength() > column) { - char c = seq[column]; + char c = sequences[row].getCharAt(column); residueCounts.add(c); if (Comparison.isNucleotide(c)) { @@@ -315,7 -316,7 +315,7 @@@ // always set ranges again gaprow.graphMax = nseq; gaprow.graphMin = 0; - double scale = 0.8/nseq; + double scale = 0.8 / nseq; for (int i = startCol; i < endCol; i++) { ProfileI profile = profiles.get(i); @@@ -333,9 -334,9 +333,9 @@@ String description = "" + gapped; - gaprow.annotations[i] = new Annotation("", description, - '\0', gapped, jalview.util.ColorUtils.bleachColour( - Color.DARK_GRAY, (float) scale * gapped)); + gaprow.annotations[i] = new Annotation("", description, '\0', gapped, + jalview.util.ColorUtils.bleachColour(Color.DARK_GRAY, + (float) scale * gapped)); } } @@@ -344,7 -345,8 +344,8 @@@ *
    *
  • the full profile (percentages of all residues present), if * showSequenceLogo is true, or
  • - *
  • just the modal (most common) residue(s), if showSequenceLogo is false
  • + *
  • just the modal (most common) residue(s), if showSequenceLogo is + * false
  • *
* Percentages are as a fraction of all sequence, or only ungapped sequences * if ignoreGaps is true. @@@ -365,8 -367,8 +366,8 @@@ String description = null; if (counts != null && showSequenceLogo) { - int normaliseBy = ignoreGaps ? profile.getNonGapped() : profile - .getHeight(); + int normaliseBy = ignoreGaps ? profile.getNonGapped() + : profile.getHeight(); description = counts.getTooltip(normaliseBy, dp); } else @@@ -423,8 -425,8 +424,8 @@@ QuickSort.sort(values, symbols); int nextArrayPos = 2; int totalPercentage = 0; - final int divisor = ignoreGaps ? profile.getNonGapped() : profile - .getHeight(); + final int divisor = ignoreGaps ? profile.getNonGapped() + : profile.getHeight(); /* * traverse the arrays in reverse order (highest counts first) @@@ -541,8 -543,8 +542,8 @@@ { continue; } - List codons = MappingUtils - .findCodonsFor(seq, col, mappings); + List codons = MappingUtils.findCodonsFor(seq, col, + mappings); for (char[] codon : codons) { int codonEncoded = CodingUtils.encodeCodon(codon); @@@ -622,10 -624,10 +623,10 @@@ int modalCodonEncoded = codons[codons.length - 1]; int modalCodonCount = sortedCodonCounts[codons.length - 1]; - String modalCodon = String.valueOf(CodingUtils - .decodeCodon(modalCodonEncoded)); - if (sortedCodonCounts.length > 1 - && sortedCodonCounts[codons.length - 2] == sortedCodonCounts[codons.length - 1]) + String modalCodon = String + .valueOf(CodingUtils.decodeCodon(modalCodonEncoded)); + if (sortedCodonCounts.length > 1 && sortedCodonCounts[codons.length + - 2] == sortedCodonCounts[codons.length - 1]) { /* * two or more codons share the modal count @@@ -684,8 -686,8 +685,8 @@@ { if (samePercent.length() > 0) { - mouseOver.append(samePercent).append(": ") - .append(lastPercent).append("% "); + mouseOver.append(samePercent).append(": ").append(lastPercent) + .append("% "); } samePercent.setLength(0); samePercent.append(codon); diff --combined src/jalview/analysis/AlignmentSorter.java index 9943a22,6b8ea4a..b5cefe0 --- a/src/jalview/analysis/AlignmentSorter.java +++ b/src/jalview/analysis/AlignmentSorter.java @@@ -29,11 -29,11 +29,11 @@@ import jalview.datamodel.SequenceFeatur import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; import jalview.datamodel.SequenceNode; import jalview.util.QuickSort; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; import java.util.List; /** @@@ -53,7 -53,7 +53,7 @@@ */ public class AlignmentSorter { - /** + /* * todo: refactor searches to follow a basic pattern: (search property, last * search state, current sort direction) */ @@@ -71,18 -71,19 +71,18 @@@ static boolean sortTreeAscending = true; - /** - * last Annotation Label used by sortByScore + /* + * last Annotation Label used for sort by Annotation score */ - private static String lastSortByScore; - - private static boolean sortByScoreAscending = true; + private static String lastSortByAnnotation; - /** - * compact representation of last arguments to SortByFeatureScore + /* + * string hash of last arguments to sortByFeature + * (sort order toggles if this is unchanged between sorts) */ - private static String lastSortByFeatureScore; + private static String sortByFeatureCriteria; - private static boolean sortByFeatureScoreAscending = true; + private static boolean sortByFeatureAscending = true; private static boolean sortLengthAscending; @@@ -108,8 -109,9 +108,9 @@@ true); for (int i = 0; i < nSeq; i++) { - scores[i] = (float) PIDModel.computePID(align.getSequenceAt(i) - .getSequenceAsString(), refSeq, pidParams); + scores[i] = (float) PIDModel.computePID( + align.getSequenceAt(i).getSequenceAsString(), refSeq, + pidParams); seqs[i] = align.getSequenceAt(i); } @@@ -415,7 -417,8 +416,8 @@@ } else { - setReverseOrder(align, vectorSubsetToArray(tmp, align.getSequences())); + setReverseOrder(align, + vectorSubsetToArray(tmp, align.getSequences())); } } @@@ -450,12 -453,9 +452,9 @@@ if (tmp.size() != nSeq) { - System.err - .println("WARNING: tmp.size()=" - + tmp.size() - + " != nseq=" - + nSeq - + " in getOrderByTree - tree contains sequences not in alignment"); + System.err.println("WARNING: tmp.size()=" + tmp.size() + " != nseq=" + + nSeq + + " in getOrderByTree - tree contains sequences not in alignment"); } } @@@ -491,7 -491,8 +490,8 @@@ } else { - setReverseOrder(align, vectorSubsetToArray(tmp, align.getSequences())); + setReverseOrder(align, + vectorSubsetToArray(tmp, align.getSequences())); } } @@@ -658,9 -659,9 +658,9 @@@ } jalview.util.QuickSort.sort(scores, seqs); - if (lastSortByScore != scoreLabel) + if (lastSortByAnnotation != scoreLabel) { - lastSortByScore = scoreLabel; + lastSortByAnnotation = scoreLabel; setOrder(alignment, seqs); } else @@@ -681,62 -682,99 +681,41 @@@ public static String FEATURE_DENSITY = "density"; - private static boolean containsIgnoreCase(final String lab, - final List labs) - { - if (labs == null) - { - return true; - } - if (lab == null) - { - return false; - } - for (String label : labs) - { - if (lab.equalsIgnoreCase(label)) - { - return true; - } - } - return false; - } - /** - * sort the alignment using the features on each sequence found between start - * and stop with the given featureLabel (and optional group qualifier) + * Sort sequences by feature score or density, optionally restricted by + * feature types, feature groups, or alignment start/end positions. + *

+ * If the sort is repeated for the same combination of types and groups, sort + * order is reversed. * - * @param featureLabel - * (may not be null) - * @param groupLabel - * (may be null) - * @param start - * (-1 to include non-positional features) - * @param stop - * (-1 to only sort on non-positional features) + * @param featureTypes + * a list of feature types to include (or null for all) + * @param groups + * a list of feature groups to include (or null for all) + * @param startCol + * start column position to include (base zero) + * @param endCol + * end column position to include (base zero) * @param alignment - * - aligned sequences containing features + * the alignment to be sorted * @param method - * - one of the string constants FEATURE_SCORE, FEATURE_LABEL, - * FEATURE_DENSITY + * either "average_score" or "density" ("text" not yet implemented) */ - public static void sortByFeature(String featureLabel, String groupLabel, - int start, int stop, AlignmentI alignment, String method) - { - sortByFeature( - featureLabel == null ? null : Arrays.asList(new String[] - { featureLabel }), - groupLabel == null ? null : Arrays.asList(new String[] - { groupLabel }), start, stop, alignment, method); - } - - private static boolean containsIgnoreCase(final String lab, - final List labs) - { - if (labs == null) - { - return true; - } - if (lab == null) - { - return false; - } - for (String label : labs) - { - if (lab.equalsIgnoreCase(label)) - { - return true; - } - } - return false; - } - - public static void sortByFeature(List featureLabels, - List groupLabels, int start, int stop, + public static void sortByFeature(List featureTypes, + List groups, final int startCol, final int endCol, AlignmentI alignment, String method) { if (method != FEATURE_SCORE && method != FEATURE_LABEL && method != FEATURE_DENSITY) { - throw new Error(MessageManager - .getString("error.implementation_error_sortbyfeature")); + String msg = String + .format("Implementation Error - sortByFeature method must be either '%s' or '%s'", + FEATURE_SCORE, FEATURE_DENSITY); + System.err.println(msg); + return; } - boolean ignoreScore = method != FEATURE_SCORE; - StringBuffer scoreLabel = new StringBuffer(); - scoreLabel.append(start + stop + method); - // This doesn't quite work yet - we'd like to have a canonical ordering that - // can be preserved from call to call - if (featureLabels != null) - { - for (String label : featureLabels) - { - scoreLabel.append(label); - } - } - if (groupLabels != null) - { - for (String label : groupLabels) - { - scoreLabel.append(label); - } - } - - /* - * if resorting the same feature, toggle sort order - */ - if (lastSortByFeatureScore == null - || !scoreLabel.toString().equals(lastSortByFeatureScore)) - { - sortByFeatureScoreAscending = true; - } - else - { - sortByFeatureScoreAscending = !sortByFeatureScoreAscending; - } - lastSortByFeatureScore = scoreLabel.toString(); + flipFeatureSortIfUnchanged(method, featureTypes, groups, startCol, endCol); SequenceI[] seqs = alignment.getSequencesArray(); @@@ -745,44 -783,57 +724,44 @@@ int hasScores = 0; // number of scores present on set double[] scores = new double[seqs.length]; int[] seqScores = new int[seqs.length]; - Object[] feats = new Object[seqs.length]; - double min = 0, max = 0; + Object[][] feats = new Object[seqs.length][]; + double min = 0d; + double max = 0d; + for (int i = 0; i < seqs.length; i++) { - SequenceFeature[] sf = seqs[i].getSequenceFeatures(); - if (sf == null) - { - sf = new SequenceFeature[0]; - } - else - { - SequenceFeature[] tmp = new SequenceFeature[sf.length]; - for (int s = 0; s < tmp.length; s++) - { - tmp[s] = sf[s]; - } - sf = tmp; - } - int sstart = (start == -1) ? start : seqs[i].findPosition(start); - int sstop = (stop == -1) ? stop : seqs[i].findPosition(stop); + /* + * get sequence residues overlapping column region + * and features for residue positions and specified types + */ + String[] types = featureTypes == null ? null : featureTypes + .toArray(new String[featureTypes.size()]); + List sfs = seqs[i].findFeatures(startCol + 1, + endCol + 1, types); + seqScores[i] = 0; scores[i] = 0.0; - int n = sf.length; - for (int f = 0; f < sf.length; f++) + + Iterator it = sfs.listIterator(); + while (it.hasNext()) { - // filter for selection criteria - SequenceFeature feature = sf[f]; + SequenceFeature sf = it.next(); /* - * double-check feature overlaps columns (JAL-2544) - * (could avoid this with a findPositions(fromCol, toCol) method) - * findIndex returns base 1 column values, startCol/endCol are base 0 + * accept all features with null or empty group, otherwise + * check group is one of the currently visible groups */ - boolean noOverlap = seqs[i].findIndex(feature.getBegin()) > stop + 1 - || seqs[i].findIndex(feature.getEnd()) < start + 1; - boolean skipFeatureType = featureLabels != null && !AlignmentSorter - .containsIgnoreCase(feature.type, featureLabels); - boolean skipFeatureGroup = groupLabels != null - && (feature.getFeatureGroup() != null - && !AlignmentSorter.containsIgnoreCase( - feature.getFeatureGroup(), groupLabels)); - if (noOverlap || skipFeatureType || skipFeatureGroup) + String featureGroup = sf.getFeatureGroup(); + if (groups != null && featureGroup != null + && !"".equals(featureGroup) + && !groups.contains(featureGroup)) { - // forget about this feature - sf[f] = null; - n--; + it.remove(); } else { - // or, also take a look at the scores if necessary. - if (!ignoreScore && !Float.isNaN(feature.getScore())) + float score = sf.getScore(); + if (FEATURE_SCORE.equals(method) && !Float.isNaN(score)) { if (seqScores[i] == 0) { @@@ -790,26 -841,34 +769,26 @@@ } seqScores[i]++; hasScore[i] = true; - scores[i] += feature.getScore(); // take the first instance of this - // score. + scores[i] += score; + // take the first instance of this score // ?? } } } - SequenceFeature[] fs; - feats[i] = fs = new SequenceFeature[n]; - if (n > 0) + + feats[i] = sfs.toArray(new SequenceFeature[sfs.size()]); + if (!sfs.isEmpty()) { - n = 0; - for (int f = 0; f < sf.length; f++) - { - if (sf[f] != null) - { - ((SequenceFeature[]) feats[i])[n++] = sf[f]; - } - } if (method == FEATURE_LABEL) { - // order the labels by alphabet - String[] labs = new String[fs.length]; - for (int l = 0; l < labs.length; l++) + // order the labels by alphabet (not yet implemented) + String[] labs = new String[sfs.size()]; + for (int l = 0; l < sfs.size(); l++) { - labs[l] = (fs[l].getDescription() != null - ? fs[l].getDescription() - : fs[l].getType()); + SequenceFeature sf = sfs.get(l); + String description = sf.getDescription(); + labs[l] = (description != null ? description : sf.getType()); } - QuickSort.sort(labs, ((Object[]) feats[i])); + QuickSort.sort(labs, feats[i]); } } if (hasScore[i]) @@@ -819,18 -878,23 +798,18 @@@ // update the score bounds. if (hasScores == 1) { - max = min = scores[i]; + min = scores[i]; + max = min; } else { - if (max < scores[i]) - { - max = scores[i]; - } - if (min > scores[i]) - { - min = scores[i]; - } + max = Math.max(max, scores[i]); + min = Math.min(min, scores[i]); } } } - if (method == FEATURE_SCORE) + if (FEATURE_SCORE.equals(method)) { if (hasScores == 0) { @@@ -855,9 -919,9 +834,9 @@@ } } } - QuickSort.sortByDouble(scores, seqs, sortByFeatureScoreAscending); + QuickSort.sortByDouble(scores, seqs, sortByFeatureAscending); } - else if (method == FEATURE_DENSITY) + else if (FEATURE_DENSITY.equals(method)) { for (int i = 0; i < seqs.length; i++) { @@@ -867,53 -931,18 +846,53 @@@ // System.err.println("Sorting on Density: seq "+seqs[i].getName()+ // " Feats: "+featureCount+" Score : "+scores[i]); } - QuickSort.sortByDouble(scores, seqs, sortByFeatureScoreAscending); + QuickSort.sortByDouble(scores, seqs, sortByFeatureAscending); } - else + + setOrder(alignment, seqs); + } + + /** + * Builds a string hash of criteria for sorting, and if unchanged from last + * time, reverse the sort order + * + * @param method + * @param featureTypes + * @param groups + * @param startCol + * @param endCol + */ + protected static void flipFeatureSortIfUnchanged(String method, + List featureTypes, List groups, + final int startCol, final int endCol) + { + StringBuilder sb = new StringBuilder(64); + sb.append(startCol).append(method).append(endCol); + if (featureTypes != null) { - if (method == FEATURE_LABEL) - { - throw new Error( - MessageManager.getString("error.not_yet_implemented")); - } + Collections.sort(featureTypes); + sb.append(featureTypes.toString()); } + if (groups != null) + { + Collections.sort(groups); + sb.append(groups.toString()); + } + String scoreCriteria = sb.toString(); - setOrder(alignment, seqs); + /* + * if resorting on the same criteria, toggle sort order + */ + if (sortByFeatureCriteria == null + || !scoreCriteria.equals(sortByFeatureCriteria)) + { + sortByFeatureAscending = true; + } + else + { + sortByFeatureAscending = !sortByFeatureAscending; + } + sortByFeatureCriteria = scoreCriteria; } } diff --combined src/jalview/analysis/AlignmentUtils.java index b65096c,1b8f84f..2b9b9f9 --- a/src/jalview/analysis/AlignmentUtils.java +++ b/src/jalview/analysis/AlignmentUtils.java @@@ -35,14 -35,14 +35,14 @@@ import jalview.datamodel.Sequence import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; -import jalview.io.gff.SequenceOntologyFactory; +import jalview.datamodel.features.SequenceFeatures; import jalview.io.gff.SequenceOntologyI; import jalview.schemes.ResidueProperties; import jalview.util.Comparison; import jalview.util.DBRefUtils; +import jalview.util.IntRangeComparator; import jalview.util.MapList; import jalview.util.MappingUtils; -import jalview.util.RangeComparator; import jalview.util.StringUtils; import java.io.UnsupportedEncodingException; @@@ -51,6 -51,7 +51,6 @@@ import java.util.ArrayList import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@@ -170,10 -171,12 +170,12 @@@ public class AlignmentUtil } } // 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(); - char[] downstream = new String(ds.getSequence(s_end - 1, s_end - + dstream_ds)).toLowerCase().toCharArray(); + char[] upstream = new String(ds + .getSequence(s.getStart() - 1 - ustream_ds, s.getStart() - 1)) + .toLowerCase().toCharArray(); + char[] downstream = new String( + ds.getSequence(s_end - 1, s_end + dstream_ds)).toLowerCase() + .toCharArray(); char[] coreseq = s.getSequence(); char[] nseq = new char[offset + upstream.length + downstream.length + coreseq.length]; @@@ -188,8 -191,8 +190,8 @@@ System.arraycopy(upstream, 0, nseq, p, upstream.length); System.arraycopy(coreseq, 0, nseq, p + upstream.length, coreseq.length); - System.arraycopy(downstream, 0, nseq, p + coreseq.length - + upstream.length, downstream.length); + System.arraycopy(downstream, 0, nseq, + p + coreseq.length + upstream.length, downstream.length); s.setSequence(new String(nseq)); s.setStart(s.getStart() - ustream_ds); s.setEnd(s_end + downstream.length); @@@ -316,9 -319,9 +318,9 @@@ * @return */ protected static boolean mapProteinToCdna( - final AlignmentI proteinAlignment, - final AlignmentI cdnaAlignment, Set mappedDna, - Set mappedProtein, boolean xrefsOnly) + final AlignmentI proteinAlignment, final AlignmentI cdnaAlignment, + Set mappedDna, Set mappedProtein, + boolean xrefsOnly) { boolean mappingExistsOrAdded = false; List thisSeqs = proteinAlignment.getSequences(); @@@ -347,9 -350,8 +349,8 @@@ * Don't map non-xrefd sequences more than once each. This heuristic * allows us to pair up similar sequences in ordered alignments. */ - if (!xrefsOnly - && (mappedProtein.contains(aaSeq) || mappedDna - .contains(cdnaSeq))) + if (!xrefsOnly && (mappedProtein.contains(aaSeq) + || mappedDna.contains(cdnaSeq))) { continue; } @@@ -402,7 -404,8 +403,8 @@@ /** * Builds a mapping (if possible) of a cDNA to a protein sequence. *

    - *
  • first checks if the cdna translates exactly to the protein sequence
  • + *
  • first checks if the cdna translates exactly to the protein + * sequence
  • *
  • else checks for translation after removing a STOP codon
  • *
  • else checks for translation after removing a START codon
  • *
  • if that fails, inspect CDS features on the cDNA sequence
  • @@@ -424,8 -427,9 +426,9 @@@ * String objects. */ final SequenceI proteinDataset = proteinSeq.getDatasetSequence(); - char[] aaSeqChars = proteinDataset != null ? proteinDataset - .getSequence() : proteinSeq.getSequence(); + char[] aaSeqChars = proteinDataset != null + ? proteinDataset.getSequence() + : proteinSeq.getSequence(); final SequenceI cdnaDataset = cdnaSeq.getDatasetSequence(); char[] cdnaSeqChars = cdnaDataset != null ? cdnaDataset.getSequence() : cdnaSeq.getSequence(); @@@ -466,8 -470,7 +469,7 @@@ * If lengths still don't match, try ignoring start codon. */ int startOffset = 0; - if (cdnaLength != mappedLength - && cdnaLength > 2 + if (cdnaLength != mappedLength && cdnaLength > 2 && String.valueOf(cdnaSeqChars, 0, CODON_LENGTH).toUpperCase() .equals(ResidueProperties.START)) { @@@ -481,8 -484,9 +483,9 @@@ /* * protein is translation of dna (+/- start/stop codons) */ - MapList map = new MapList(new int[] { cdnaStart, cdnaEnd }, new int[] - { proteinStart, proteinEnd }, CODON_LENGTH, 1); + MapList map = new MapList(new int[] { cdnaStart, cdnaEnd }, + new int[] + { proteinStart, proteinEnd }, CODON_LENGTH, 1); return map; } @@@ -512,7 -516,8 +515,8 @@@ 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); @@@ -631,10 -636,9 +635,9 @@@ * @param preserveUnmappedGaps * @param preserveMappedGaps */ - public static void alignSequenceAs(SequenceI alignTo, - SequenceI alignFrom, AlignedCodonFrame mapping, String myGap, - char sourceGap, boolean preserveMappedGaps, - boolean preserveUnmappedGaps) + public static void alignSequenceAs(SequenceI alignTo, SequenceI alignFrom, + AlignedCodonFrame mapping, String myGap, char sourceGap, + boolean preserveMappedGaps, boolean preserveUnmappedGaps) { // TODO generalise to work for Protein-Protein, dna-dna, dna-protein @@@ -650,16 -654,15 +653,16 @@@ int toOffset = alignTo.getStart() - 1; int sourceGapMappedLength = 0; boolean inExon = false; - final char[] thisSeq = alignTo.getSequence(); - final char[] thatAligned = alignFrom.getSequence(); - StringBuilder thisAligned = new StringBuilder(2 * thisSeq.length); + final int toLength = alignTo.getLength(); + final int fromLength = alignFrom.getLength(); + StringBuilder thisAligned = new StringBuilder(2 * toLength); /* * Traverse the 'model' aligned sequence */ - for (char sourceChar : thatAligned) + for (int i = 0; i < fromLength; i++) { + char sourceChar = alignFrom.getCharAt(i); if (sourceChar == sourceGap) { sourceGapMappedLength += ratio; @@@ -699,9 -702,9 +702,9 @@@ */ int intronLength = 0; while (basesWritten + toOffset < mappedCodonEnd - && thisSeqPos < thisSeq.length) + && thisSeqPos < toLength) { - final char c = thisSeq[thisSeqPos++]; + final char c = alignTo.getCharAt(thisSeqPos++); if (c != myGapChar) { basesWritten++; @@@ -727,7 -730,7 +730,7 @@@ int gapsToAdd = calculateGapsToInsert(preserveMappedGaps, preserveUnmappedGaps, sourceGapMappedLength, inExon, trailingCopiedGap.length(), intronLength, startOfCodon); - for (int i = 0; i < gapsToAdd; i++) + for (int k = 0; k < gapsToAdd; k++) { thisAligned.append(myGapChar); } @@@ -755,9 -758,9 +758,9 @@@ * At end of model aligned sequence. Copy any remaining target sequence, optionally * including (intron) gaps. */ - while (thisSeqPos < thisSeq.length) + while (thisSeqPos < toLength) { - final char c = thisSeq[thisSeqPos++]; + final char c = alignTo.getCharAt(thisSeqPos++); if (c != myGapChar || preserveUnmappedGaps) { thisAligned.append(c); @@@ -830,8 -833,9 +833,9 @@@ } else { - gapsToAdd = Math.min(intronLength + trailingGapLength - - sourceGapMappedLength, trailingGapLength); + gapsToAdd = Math.min( + intronLength + trailingGapLength - sourceGapMappedLength, + trailingGapLength); } } } @@@ -930,7 -934,8 +934,8 @@@ * @return */ static boolean alignCdsSequenceAsProtein(SequenceI cdsSeq, - AlignmentI protein, List mappings, char gapChar) + AlignmentI protein, List mappings, + char gapChar) { SequenceI cdsDss = cdsSeq.getDatasetSequence(); if (cdsDss == null) @@@ -947,7 -952,7 +952,7 @@@ SequenceI peptide = mapping.findAlignedSequence(cdsSeq, protein); if (peptide != null) { - int peptideLength = peptide.getLength(); + final int peptideLength = peptide.getLength(); Mapping map = mapping.getMappingBetween(cdsSeq, peptide); if (map != null) { @@@ -956,21 -961,20 +961,20 @@@ { mapList = mapList.getInverse(); } - int cdsLength = cdsDss.getLength(); - int mappedFromLength = MappingUtils - .getLength(mapList.getFromRanges()); + final int cdsLength = cdsDss.getLength(); + int mappedFromLength = MappingUtils.getLength(mapList + .getFromRanges()); int mappedToLength = MappingUtils .getLength(mapList.getToRanges()); boolean addStopCodon = (cdsLength == mappedFromLength * CODON_LENGTH + CODON_LENGTH) - || (peptide.getDatasetSequence().getLength() == mappedFromLength - 1); + || (peptide.getDatasetSequence() + .getLength() == mappedFromLength - 1); if (cdsLength != mappedToLength && !addStopCodon) { - System.err - .println(String - .format("Can't align cds as protein (length mismatch %d/%d): %s", - cdsLength, mappedToLength, - cdsSeq.getName())); + System.err.println(String.format( + "Can't align cds as protein (length mismatch %d/%d): %s", + cdsLength, mappedToLength, cdsSeq.getName())); } /* @@@ -984,15 -988,14 +988,15 @@@ * walk over the aligned peptide sequence and insert mapped * codons for residues in the aligned cds sequence */ - char[] alignedPeptide = peptide.getSequence(); - char[] nucleotides = cdsDss.getSequence(); int copiedBases = 0; int cdsStart = cdsDss.getStart(); int proteinPos = peptide.getStart() - 1; int cdsCol = 0; - for (char residue : alignedPeptide) + + for (int col = 0; col < peptideLength; col++) { + char residue = peptide.getCharAt(col); + if (Comparison.isGap(residue)) { cdsCol += CODON_LENGTH; @@@ -1010,7 -1013,7 +1014,7 @@@ { for (int j = codon[0]; j <= codon[1]; j++) { - char mappedBase = nucleotides[j - cdsStart]; + char mappedBase = cdsDss.getCharAt(j - cdsStart); alignedCds[cdsCol++] = mappedBase; copiedBases++; } @@@ -1022,7 -1025,7 +1026,7 @@@ * append stop codon if not mapped from protein, * closing it up to the end of the mapped sequence */ - if (copiedBases == nucleotides.length - CODON_LENGTH) + if (copiedBases == cdsLength - CODON_LENGTH) { for (int i = alignedCds.length - 1; i >= 0; i--) { @@@ -1032,9 -1035,10 +1036,9 @@@ break; } } - for (int i = nucleotides.length - - CODON_LENGTH; i < nucleotides.length; i++) + for (int i = cdsLength - CODON_LENGTH; i < cdsLength; i++) { - alignedCds[cdsCol++] = nucleotides[i]; + alignedCds[cdsCol++] = cdsDss.getCharAt(i); } } cdsSeq.setSequence(new String(alignedCds)); @@@ -1088,8 -1092,8 +1092,8 @@@ if (prot != null) { Mapping seqMap = mapping.getMappingForSequence(dnaSeq); - addCodonPositions(dnaSeq, prot, protein.getGapCharacter(), - seqMap, alignedCodons); + addCodonPositions(dnaSeq, prot, protein.getGapCharacter(), seqMap, + alignedCodons); unmappedProtein.remove(prot); } } @@@ -1142,8 -1146,8 +1146,8 @@@ AlignedCodon codon = sequenceCodon.getValue(); if (codon.peptideCol > 1) { - System.err - .println("Problem mapping protein with >1 unmapped start positions: " + System.err.println( + "Problem mapping protein with >1 unmapped start positions: " + seq.getName()); } else if (codon.peptideCol == 1) @@@ -1154,8 -1158,8 +1158,8 @@@ if (lastCodon != null) { AlignedCodon firstPeptide = new AlignedCodon(lastCodon.pos1, - lastCodon.pos2, lastCodon.pos3, String.valueOf(seq - .getCharAt(0)), 0); + lastCodon.pos2, lastCodon.pos3, + String.valueOf(seq.getCharAt(0)), 0); toAdd.put(seq, firstPeptide); } else @@@ -1204,26 -1208,21 +1208,26 @@@ List unmappedProtein) { /* - * Prefill aligned sequences with gaps before inserting aligned protein - * residues. + * prefill peptide sequences with gaps */ int alignedWidth = alignedCodons.size(); char[] gaps = new char[alignedWidth]; Arrays.fill(gaps, protein.getGapCharacter()); - String allGaps = String.valueOf(gaps); + Map peptides = new HashMap<>(); for (SequenceI seq : protein.getSequences()) { if (!unmappedProtein.contains(seq)) { - seq.setSequence(allGaps); + peptides.put(seq, Arrays.copyOf(gaps, gaps.length)); } } + /* + * Traverse the codons left to right (as defined by CodonComparator) + * and insert peptides in each column where the sequence is mapped. + * This gives a peptide 'alignment' where residues are aligned if their + * corresponding codons occupy the same columns in the cdna alignment. + */ int column = 0; for (AlignedCodon codon : alignedCodons.keySet()) { @@@ -1231,20 -1230,12 +1235,20 @@@ .get(codon); for (Entry entry : columnResidues.entrySet()) { - // place translated codon at its column position in sequence - entry.getKey().getSequence()[column] = entry.getValue().product - .charAt(0); + char residue = entry.getValue().product.charAt(0); + peptides.get(entry.getKey())[column] = residue; } column++; } + + /* + * and finally set the constructed sequences + */ + for (Entry entry : peptides.entrySet()) + { + entry.getKey().setSequence(new String(entry.getValue())); + } + return 0; } @@@ -1317,7 -1308,8 +1321,8 @@@ *
      *
    • One alignment must be nucleotide, and the other protein
    • *
    • At least one pair of sequences must be already mapped, or mappable
    • - *
    • Mappable means the nucleotide translation matches the protein sequence
    • + *
    • Mappable means the nucleotide translation matches the protein + * sequence
    • *
    • The translation may ignore start and stop codons if present in the * nucleotide
    • *
    @@@ -1373,9 -1365,10 +1378,10 @@@ return false; } - SequenceI dnaDs = dnaSeq.getDatasetSequence() == null ? dnaSeq : dnaSeq - .getDatasetSequence(); - SequenceI proteinDs = proteinSeq.getDatasetSequence() == null ? proteinSeq + SequenceI dnaDs = dnaSeq.getDatasetSequence() == null ? dnaSeq + : dnaSeq.getDatasetSequence(); + SequenceI proteinDs = proteinSeq.getDatasetSequence() == null + ? proteinSeq : proteinSeq.getDatasetSequence(); for (AlignedCodonFrame mapping : mappings) @@@ -1412,8 -1405,7 +1418,7 @@@ * the alignment to check for presence of annotations */ public static void findAddableReferenceAnnotations( - List sequenceScope, - Map labelForCalcId, + List sequenceScope, Map labelForCalcId, final Map> candidates, AlignmentI al) { @@@ -1517,8 -1509,8 +1522,8 @@@ /** * Set visibility of alignment annotations of specified types (labels), for - * specified sequences. This supports controls like - * "Show all secondary structure", "Hide all Temp factor", etc. + * specified sequences. This supports controls like "Show all secondary + * structure", "Hide all Temp factor", etc. * * @al the alignment to scan for annotations * @param types @@@ -1542,9 -1534,8 +1547,8 @@@ { if (anyType || types.contains(aa.label)) { - if ((aa.sequenceRef != null) - && (forSequences == null || forSequences - .contains(aa.sequenceRef))) + if ((aa.sequenceRef != null) && (forSequences == null + || forSequences.contains(aa.sequenceRef))) { aa.visible = doShow; } @@@ -1632,8 -1623,8 +1636,8 @@@ productSeqs = new HashSet(); for (SequenceI seq : products) { - productSeqs.add(seq.getDatasetSequence() == null ? seq : seq - .getDatasetSequence()); + productSeqs.add(seq.getDatasetSequence() == null ? seq + : seq.getDatasetSequence()); } } @@@ -1726,8 -1717,9 +1730,9 @@@ /* * add a mapping from CDS to the (unchanged) mapped to range */ - List cdsRange = Collections.singletonList(new int[] { 1, - cdsSeq.getLength() }); + List cdsRange = Collections + .singletonList(new int[] + { 1, cdsSeq.getLength() }); MapList cdsToProteinMap = new MapList(cdsRange, mapList.getToRanges(), mapList.getFromRatio(), mapList.getToRatio()); @@@ -1792,12 -1784,11 +1797,11 @@@ // 'CDS|emblcdsacc' // assuming cds version same as dna ?!? - DBRefEntry proteinToCdsRef = new DBRefEntry( - primRef.getSource(), primRef.getVersion(), - cdsSeq.getName()); + DBRefEntry proteinToCdsRef = new DBRefEntry(primRef.getSource(), + primRef.getVersion(), cdsSeq.getName()); // - proteinToCdsRef.setMap(new Mapping(cdsSeqDss, cdsToProteinMap - .getInverse())); + proteinToCdsRef.setMap( + new Mapping(cdsSeqDss, cdsToProteinMap.getInverse())); proteinProduct.addDBRef(proteinToCdsRef); } @@@ -1810,8 -1801,8 +1814,8 @@@ } } - 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; @@@ -1848,8 -1839,8 +1852,8 @@@ * is this mapping from the whole dna sequence (i.e. CDS)? * allowing for possible stop codon on dna but not peptide */ - int mappedFromLength = MappingUtils.getLength(aMapping.getMap() - .getFromRanges()); + int mappedFromLength = MappingUtils + .getLength(aMapping.getMap().getFromRanges()); int dnaLength = seqDss.getLength(); if (mappedFromLength == dnaLength || mappedFromLength == dnaLength - CODON_LENGTH) @@@ -1873,8 -1864,8 +1877,8 @@@ && proteinProduct == mapping.getTo() && seqDss != map.getFromSeq()) { - mappedFromLength = MappingUtils.getLength(mapping.getMap() - .getFromRanges()); + mappedFromLength = MappingUtils + .getLength(mapping.getMap().getFromRanges()); if (mappedFromLength == map.getFromSeq().getLength()) { /* @@@ -1972,8 -1963,8 +1976,8 @@@ } else { - System.err - .println("JAL-2154 regression: warning - found (and ignnored a duplicate CDS sequence):" + System.err.println( + "JAL-2154 regression: warning - found (and ignnored a duplicate CDS sequence):" + mtch.toString()); } } @@@ -2025,16 -2016,17 +2029,17 @@@ 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()); + 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)); + 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 @@@ -2069,11 -2061,11 +2074,11 @@@ * * @param fromSeq * @param toSeq + * @param mapping + * the mapping from 'fromSeq' to 'toSeq' * @param select * if not null, only features of this type are copied (including * subtypes in the Sequence Ontology) - * @param mapping - * the mapping from 'fromSeq' to 'toSeq' * @param omitting */ public static int transferFeatures(SequenceI fromSeq, SequenceI toSeq, @@@ -2085,74 -2077,75 +2090,74 @@@ copyTo = copyTo.getDatasetSequence(); } - SequenceOntologyI so = SequenceOntologyFactory.getInstance(); + /* + * get features, optionally restricted by an ontology term + */ + List sfs = select == null ? fromSeq.getFeatures() + .getPositionalFeatures() : fromSeq.getFeatures() + .getFeaturesByOntology(select); + int count = 0; - SequenceFeature[] sfs = fromSeq.getSequenceFeatures(); - if (sfs != null) + for (SequenceFeature sf : sfs) { - for (SequenceFeature sf : sfs) + String type = sf.getType(); + boolean omit = false; + for (String toOmit : omitting) { - String type = sf.getType(); - if (select != null && !so.isA(type, select)) - { - continue; - } - boolean omit = false; - for (String toOmit : omitting) + if (type.equals(toOmit)) { - if (type.equals(toOmit)) - { - omit = true; - } - } - if (omit) - { - continue; + omit = true; } + } + if (omit) + { + continue; + } - /* - * locate the mapped range - null if either start or end is - * not mapped (no partial overlaps are calculated) - */ - int start = sf.getBegin(); - int end = sf.getEnd(); - int[] mappedTo = mapping.locateInTo(start, end); - /* - * if whole exon range doesn't map, try interpreting it - * as 5' or 3' exon overlapping the CDS range - */ - if (mappedTo == null) - { - mappedTo = mapping.locateInTo(end, end); - if (mappedTo != null) - { - /* - * end of exon is in CDS range - 5' overlap - * to a range from the start of the peptide - */ - mappedTo[0] = 1; - } - } - if (mappedTo == null) + /* + * locate the mapped range - null if either start or end is + * not mapped (no partial overlaps are calculated) + */ + int start = sf.getBegin(); + int end = sf.getEnd(); + int[] mappedTo = mapping.locateInTo(start, end); + /* + * if whole exon range doesn't map, try interpreting it + * as 5' or 3' exon overlapping the CDS range + */ + if (mappedTo == null) + { + mappedTo = mapping.locateInTo(end, end); + if (mappedTo != null) { - mappedTo = mapping.locateInTo(start, start); - if (mappedTo != null) - { - /* - * start of exon is in CDS range - 3' overlap - * to a range up to the end of the peptide - */ - mappedTo[1] = toSeq.getLength(); - } + /* + * end of exon is in CDS range - 5' overlap + * to a range from the start of the peptide + */ + mappedTo[0] = 1; } + } + if (mappedTo == null) + { + mappedTo = mapping.locateInTo(start, start); if (mappedTo != null) { - SequenceFeature copy = new SequenceFeature(sf); - copy.setBegin(Math.min(mappedTo[0], mappedTo[1])); - copy.setEnd(Math.max(mappedTo[0], mappedTo[1])); - copyTo.addSequenceFeature(copy); - count++; + /* + * start of exon is in CDS range - 3' overlap + * to a range up to the end of the peptide + */ + mappedTo[1] = toSeq.getLength(); } } + if (mappedTo != null) + { + int newBegin = Math.min(mappedTo[0], mappedTo[1]); + int newEnd = Math.max(mappedTo[0], mappedTo[1]); + SequenceFeature copy = new SequenceFeature(sf, newBegin, newEnd, + sf.getFeatureGroup(), sf.getScore()); + copyTo.addSequenceFeature(copy); + count++; + } } return count; } @@@ -2217,44 -2210,49 +2222,44 @@@ public static List findCdsPositions(SequenceI dnaSeq) { List result = new ArrayList(); - SequenceFeature[] sfs = dnaSeq.getSequenceFeatures(); - if (sfs == null) + + List sfs = dnaSeq.getFeatures().getFeaturesByOntology( + SequenceOntologyI.CDS); + if (sfs.isEmpty()) { return result; } - - SequenceOntologyI so = SequenceOntologyFactory.getInstance(); + SequenceFeatures.sortFeatures(sfs, true); int startPhase = 0; for (SequenceFeature sf : sfs) { + int phase = 0; + try + { + phase = Integer.parseInt(sf.getPhase()); + } catch (NumberFormatException e) + { + // ignore + } /* - * process a CDS feature (or a sub-type of CDS) + * phase > 0 on first codon means 5' incomplete - skip to the start + * of the next codon; example ENST00000496384 */ - if (so.isA(sf.getType(), SequenceOntologyI.CDS)) + int begin = sf.getBegin(); + int end = sf.getEnd(); + if (result.isEmpty()) { - int phase = 0; - try - { - phase = Integer.parseInt(sf.getPhase()); - } catch (NumberFormatException e) - { - // ignore - } - /* - * phase > 0 on first codon means 5' incomplete - skip to the start - * of the next codon; example ENST00000496384 - */ - int begin = sf.getBegin(); - int end = sf.getEnd(); - if (result.isEmpty()) + begin += phase; + if (begin > end) { - begin += phase; - if (begin > end) - { - // shouldn't happen! - System.err.println( - "Error: start phase extends beyond start CDS in " - + dnaSeq.getName()); - } + // shouldn't happen! + System.err + .println("Error: start phase extends beyond start CDS in " + + dnaSeq.getName()); } - result.add(new int[] { begin, end }); } + result.add(new int[] { begin, end }); } /* @@@ -2274,7 -2272,7 +2279,7 @@@ * ranges are assembled in order. Other cases should not use this method, * but instead construct an explicit mapping for CDS (e.g. EMBL parsing). */ - Collections.sort(result, new RangeComparator(true)); + Collections.sort(result, IntRangeComparator.ASCENDING); return result; } @@@ -2327,6 -2325,24 +2332,6 @@@ count += computePeptideVariants(peptide, peptidePos, codonVariants); } - /* - * sort to get sequence features in start position order - * - would be better to store in Sequence as a TreeSet or NCList? - */ - if (peptide.getSequenceFeatures() != null) - { - Arrays.sort(peptide.getSequenceFeatures(), - new Comparator() - { - @Override - public int compare(SequenceFeature o1, SequenceFeature o2) - { - int c = Integer.compare(o1.getBegin(), o2.getBegin()); - return c == 0 ? Integer.compare(o1.getEnd(), o2.getEnd()) - : c; - } - }); - } return count; } @@@ -2445,8 -2461,8 +2450,8 @@@ * are currently ignored here */ String trans = codon.contains("-") ? "-" - : (codon.length() > CODON_LENGTH ? null : ResidueProperties - .codonTranslate(codon)); + : (codon.length() > CODON_LENGTH ? null + : ResidueProperties.codonTranslate(codon)); if (trans != null && !trans.equals(residue)) { String residue3Char = StringUtils @@@ -2454,9 -2470,10 +2459,9 @@@ String trans3Char = StringUtils .toSentenceCase(ResidueProperties.aa2Triplet.get(trans)); String desc = "p." + residue3Char + peptidePos + trans3Char; - // set score to 0f so 'graduated colour' option is offered! JAL-2060 SequenceFeature sf = new SequenceFeature( SequenceOntologyI.SEQUENCE_VARIANT, desc, peptidePos, - peptidePos, 0f, var.getSource()); + peptidePos, var.getSource()); StringBuilder attributes = new StringBuilder(32); String id = (String) var.variant.getValue(ID); if (id != null) @@@ -2471,10 -2488,8 +2476,8 @@@ StringBuilder link = new StringBuilder(32); try { - link.append(desc) - .append(" ") - .append(id) - .append("|http://www.ensembl.org/Homo_sapiens/Variation/Summary?v=") + 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()); } catch (UnsupportedEncodingException e) @@@ -2516,10 -2531,10 +2519,10 @@@ * LinkedHashMap ensures we keep the peptide features in sequence order */ LinkedHashMap[]> variants = new LinkedHashMap[]>(); - SequenceOntologyI so = SequenceOntologyFactory.getInstance(); - SequenceFeature[] dnaFeatures = dnaSeq.getSequenceFeatures(); - if (dnaFeatures == null) + List dnaFeatures = dnaSeq.getFeatures() + .getFeaturesByOntology(SequenceOntologyI.SEQUENCE_VARIANT); + if (dnaFeatures.isEmpty()) { return variants; } @@@ -2539,80 -2554,84 +2542,80 @@@ // not handling multi-locus variant features continue; } - if (so.isA(sf.getType(), SequenceOntologyI.SEQUENCE_VARIANT)) + int[] mapsTo = dnaToProtein.locateInTo(dnaCol, dnaCol); + if (mapsTo == null) { - int[] mapsTo = dnaToProtein.locateInTo(dnaCol, dnaCol); - if (mapsTo == null) - { - // feature doesn't lie within coding region - continue; - } - int peptidePosition = mapsTo[0]; - List[] codonVariants = variants.get(peptidePosition); - if (codonVariants == null) - { - codonVariants = new ArrayList[CODON_LENGTH]; - codonVariants[0] = new ArrayList(); - codonVariants[1] = new ArrayList(); - codonVariants[2] = new ArrayList(); - variants.put(peptidePosition, codonVariants); - } + // feature doesn't lie within coding region + continue; + } + int peptidePosition = mapsTo[0]; + List[] codonVariants = variants.get(peptidePosition); + if (codonVariants == null) + { + codonVariants = new ArrayList[CODON_LENGTH]; + codonVariants[0] = new ArrayList(); + codonVariants[1] = new ArrayList(); + codonVariants[2] = new ArrayList(); + variants.put(peptidePosition, codonVariants); + } - /* - * extract dna variants to a string array - */ - String alls = (String) sf.getValue("alleles"); - if (alls == null) - { - continue; - } - String[] alleles = alls.toUpperCase().split(","); - int i = 0; - for (String allele : alleles) - { - alleles[i++] = allele.trim(); // lose any space characters "A, G" - } + /* + * extract dna variants to a string array + */ + String alls = (String) sf.getValue("alleles"); + if (alls == null) + { + continue; + } + String[] alleles = alls.toUpperCase().split(","); + int i = 0; + for (String allele : alleles) + { + alleles[i++] = allele.trim(); // lose any space characters "A, G" + } - /* - * get this peptide's codon positions e.g. [3, 4, 5] or [4, 7, 10] - */ - int[] codon = peptidePosition == lastPeptidePostion ? lastCodon - : MappingUtils.flattenRanges(dnaToProtein - .locateInFrom(peptidePosition, peptidePosition)); - lastPeptidePostion = peptidePosition; - lastCodon = codon; + /* + * get this peptide's codon positions e.g. [3, 4, 5] or [4, 7, 10] + */ + int[] codon = peptidePosition == lastPeptidePostion ? lastCodon + : MappingUtils.flattenRanges(dnaToProtein.locateInFrom( + peptidePosition, peptidePosition)); + lastPeptidePostion = peptidePosition; + lastCodon = codon; - /* - * save nucleotide (and any variant) for each codon position - */ - for (int codonPos = 0; codonPos < CODON_LENGTH; codonPos++) + /* + * save nucleotide (and any variant) for each codon position + */ + for (int codonPos = 0; codonPos < CODON_LENGTH; codonPos++) + { + String nucleotide = String.valueOf( + dnaSeq.getCharAt(codon[codonPos] - dnaStart)).toUpperCase(); + List codonVariant = codonVariants[codonPos]; + if (codon[codonPos] == dnaCol) { - String nucleotide = String - .valueOf(dnaSeq.getCharAt(codon[codonPos] - dnaStart)) - .toUpperCase(); - List codonVariant = codonVariants[codonPos]; - if (codon[codonPos] == dnaCol) + if (!codonVariant.isEmpty() + && codonVariant.get(0).variant == null) { - if (!codonVariant.isEmpty() - && codonVariant.get(0).variant == null) - { - /* - * already recorded base value, add this variant - */ - codonVariant.get(0).variant = sf; - } - else - { - /* - * add variant with base value - */ - codonVariant.add(new DnaVariant(nucleotide, sf)); - } + /* + * already recorded base value, add this variant + */ + codonVariant.get(0).variant = sf; } - else if (codonVariant.isEmpty()) + else { /* - * record (possibly non-varying) base value + * add variant with base value */ - codonVariant.add(new DnaVariant(nucleotide)); + codonVariant.add(new DnaVariant(nucleotide, sf)); } } + else if (codonVariant.isEmpty()) + { + /* + * record (possibly non-varying) base value + */ + codonVariant.add(new DnaVariant(nucleotide)); + } } } return variants; @@@ -2796,8 -2815,8 +2799,8 @@@ */ for (SequenceI seq : unaligned.getSequences()) { - List alignedSequences = alignedDatasets.get(seq - .getDatasetSequence()); + List alignedSequences = alignedDatasets + .get(seq.getDatasetSequence()); // TODO: getSequenceAsString() will be deprecated in the future // TODO: need to leave to SequenceI implementor to update gaps seq.setSequence(alignedSequences.get(0).getSequenceAsString()); @@@ -2821,7 -2840,8 +2824,8 @@@ * @return */ static SortedMap> buildMappedColumnsMap( - AlignmentI unaligned, AlignmentI aligned, List unmapped) + AlignmentI unaligned, AlignmentI aligned, + List unmapped) { /* * Map will hold, for each aligned column position, a map of @@@ -2856,7 -2876,8 +2860,8 @@@ } /** - * Helper method that adds to a map the mapped column positions of a sequence.
    + * Helper method that adds to a map the mapped column positions of a sequence. + *
    * For example if aaTT-Tg-gAAA is mapped to TTTAAA then the map should record * that columns 3,4,6,10,11,12 map to characters T,T,T,A,A,A of the mapped to * sequence. @@@ -2885,11 -2906,13 +2890,11 @@@ */ if (seqMap.getTo() == fromSeq.getDatasetSequence()) { - seqMap = new Mapping(seq.getDatasetSequence(), seqMap.getMap() - .getInverse()); + seqMap = new Mapping(seq.getDatasetSequence(), + seqMap.getMap().getInverse()); } - char[] fromChars = fromSeq.getSequence(); int toStart = seq.getStart(); - char[] toChars = seq.getSequence(); /* * traverse [start, end, start, end...] ranges in fromSeq @@@ -2920,10 -2943,10 +2925,10 @@@ * of the next character of the mapped-to sequence; stop when all * the characters of the range have been counted */ - while (mappedCharPos <= range[1] && fromCol <= fromChars.length + while (mappedCharPos <= range[1] && fromCol <= fromSeq.getLength() && fromCol >= 0) { - if (!Comparison.isGap(fromChars[fromCol - 1])) + if (!Comparison.isGap(fromSeq.getCharAt(fromCol - 1))) { /* * mapped from sequence has a character in this column @@@ -2935,7 -2958,7 +2940,7 @@@ seqsMap = new HashMap(); map.put(fromCol, seqsMap); } - seqsMap.put(seq, toChars[mappedCharPos - toStart]); + seqsMap.put(seq, seq.getCharAt(mappedCharPos - toStart)); mappedCharPos++; } fromCol += (forward ? 1 : -1); diff --combined src/jalview/analysis/Conservation.java index f94a658,ba4f705..131b39c --- a/src/jalview/analysis/Conservation.java +++ b/src/jalview/analysis/Conservation.java @@@ -143,8 -143,8 +143,8 @@@ public class Conservatio * @param end * end column position */ - public Conservation(String name, int threshold, - List sequences, int start, int end) + public Conservation(String name, int threshold, List sequences, + int start, int end) { this.name = name; this.threshold = threshold; @@@ -244,8 -244,8 +244,8 @@@ else { // JBPNote INFO level debug - System.err - .println("ERROR: calcSeqNum called with out of range sequence index for Alignment\n"); + System.err.println( + "ERROR: calcSeqNum called with out of range sequence index for Alignment\n"); } } @@@ -414,7 -414,8 +414,8 @@@ continue; } - char c = sequences[i].getCharAt(column); // gaps do not have upper/lower case + char c = sequences[i].getCharAt(column); // gaps do not have upper/lower + // case if (Comparison.isGap((c))) { @@@ -618,7 -619,8 +619,8 @@@ * @param endCol * @param scoreMatrix */ - protected void findQuality(int startCol, int endCol, ScoreMatrix scoreMatrix) + protected void findQuality(int startCol, int endCol, + ScoreMatrix scoreMatrix) { quality = new Vector(); @@@ -734,23 -736,28 +736,23 @@@ public void completeAnnotations(AlignmentAnnotation conservation, AlignmentAnnotation quality2, int istart, int alWidth) { - char[] sequence = getConsSequence().getSequence(); - float minR; - float minG; - float minB; - float maxR; - float maxG; - float maxB; - minR = 0.3f; - minG = 0.0f; - minB = 0f; - maxR = 1.0f - minR; - maxG = 0.9f - minG; - maxB = 0f - minB; // scalable range for colouring both Conservation and - // Quality + SequenceI cons = getConsSequence(); + + /* + * colour scale for Conservation and Quality; + */ + float minR = 0.3f; + float minG = 0.0f; + float minB = 0f; + float maxR = 1.0f - minR; + float maxG = 0.9f - minG; + float maxB = 0f - minB; float min = 0f; float max = 11f; float qmin = 0f; float qmax = 0f; - char c; - if (conservation != null && conservation.annotations != null && conservation.annotations.length < alWidth) { @@@ -773,7 -780,7 +775,7 @@@ { float value = 0; - c = sequence[i]; + char c = cons.getCharAt(i); if (Character.isDigit(c)) { @@@ -793,11 -800,11 +795,11 @@@ float vprop = value - min; vprop /= max; int consp = i - start; - String conssym = (value > 0 && consp > -1 && consp < consSymbs.length) ? consSymbs[consp] - : ""; + String conssym = (value > 0 && consp > -1 + && consp < consSymbs.length) ? consSymbs[consp] : ""; conservation.annotations[i] = new Annotation(String.valueOf(c), - conssym, ' ', value, new Color(minR + (maxR * vprop), minG - + (maxG * vprop), minB + (maxB * vprop))); + conssym, ' ', value, new Color(minR + (maxR * vprop), + minG + (maxG * vprop), minB + (maxB * vprop))); } // Quality calc @@@ -806,10 -813,9 +808,9 @@@ value = quality.elementAt(i).floatValue(); float vprop = value - qmin; vprop /= qmax; - quality2.annotations[i] = new Annotation(" ", - String.valueOf(value), ' ', value, new Color(minR - + (maxR * vprop), minG + (maxG * vprop), minB - + (maxB * vprop))); + quality2.annotations[i] = new Annotation(" ", String.valueOf(value), + ' ', value, new Color(minR + (maxR * vprop), + minG + (maxG * vprop), minB + (maxB * vprop))); } } } @@@ -860,11 -866,12 +861,12 @@@ */ String getTooltip(int column) { - char[] sequence = getConsSequence().getSequence(); - char val = column < sequence.length ? sequence[column] : '-'; + SequenceI cons = getConsSequence(); + char val = column < cons.getLength() ? cons.getCharAt(column) : '-'; boolean hasConservation = val != '-' && val != '0'; int consp = column - start; - String tip = (hasConservation && consp > -1 && consp < consSymbs.length) ? consSymbs[consp] + String tip = (hasConservation && consp > -1 && consp < consSymbs.length) + ? consSymbs[consp] : ""; return tip; } diff --combined src/jalview/analysis/CrossRef.java index b77e403,1a56393..e6bae9b --- a/src/jalview/analysis/CrossRef.java +++ b/src/jalview/analysis/CrossRef.java @@@ -164,8 -164,8 +164,8 @@@ public class CrossRe */ for (SequenceI rs : foundSeqs) { - DBRefEntry[] xrs = DBRefUtils - .selectDbRefs(!fromDna, rs.getDBRefs()); + DBRefEntry[] xrs = DBRefUtils.selectDbRefs(!fromDna, + rs.getDBRefs()); addXrefsToSources(xrs, sources); } } @@@ -230,8 -230,8 +230,8 @@@ dss = dss.getDatasetSequence(); } boolean found = false; - DBRefEntry[] xrfs = DBRefUtils - .selectDbRefs(!fromDna, dss.getDBRefs()); + DBRefEntry[] xrfs = DBRefUtils.selectDbRefs(!fromDna, + dss.getDBRefs()); // ENST & ENSP comes in to both Protein and nucleotide, so we need to // filter them // out later. @@@ -291,13 -291,10 +291,10 @@@ 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);*/ @@@ -323,8 -320,9 +320,9 @@@ } else { - cf.addMap(matchInDataset, dss, xref.getMap().getMap() - .getInverse(), xref.getMap().getMappedFromId()); + cf.addMap(matchInDataset, dss, + xref.getMap().getMap().getInverse(), + xref.getMap().getMappedFromId()); } } @@@ -340,8 -338,8 +338,8 @@@ 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 { @@@ -355,8 -353,8 +353,8 @@@ 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) @@@ -406,8 -404,8 +404,8 @@@ { 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 @@@ -423,8 -421,8 +421,8 @@@ 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(); } @@@ -432,14 -430,16 +430,16 @@@ if (retrieved != null) { boolean addedXref = false; - List newDsSeqs = new ArrayList(), doNotAdd = new ArrayList(); + List 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(); + SequenceI retrievedDss = retrievedSequence + .getDatasetSequence() == null ? retrievedSequence + : retrievedSequence.getDatasetSequence(); addedXref |= importCrossRefSeq(cf, newDsSeqs, doNotAdd, dss, retrievedDss); } @@@ -452,8 -452,9 +452,9 @@@ { // dataset gets contaminated ccwith non-ds sequences. why ??! // try: Ensembl -> Nuc->Ensembl, Nuc->Uniprot-->Protein->EMBL-> - SequenceI retrievedDss = retrievedSequence.getDatasetSequence() == null ? retrievedSequence - : retrievedSequence.getDatasetSequence(); + SequenceI retrievedDss = retrievedSequence + .getDatasetSequence() == null ? retrievedSequence + : retrievedSequence.getDatasetSequence(); addedXref |= importCrossRefSeq(cf, newDsSeqs, doNotAdd, dss, retrievedDss); } @@@ -577,9 -578,8 +578,8 @@@ 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, @@@ -597,8 -597,8 +597,8 @@@ */ for (DBRefEntry ref : toRefs) { - if (dbref.getSrcAccString().equals( - ref.getSrcAccString())) + if (dbref.getSrcAccString() + .equals(ref.getSrcAccString())) { continue; // avoid overwriting the ref on source sequence } @@@ -619,31 -619,34 +619,31 @@@ * duplication (e.g. same variation from two * transcripts) */ - SequenceFeature[] sfs = ms.getSequenceFeatures(); - if (sfs != null) + List 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); } } @@@ -722,8 -725,8 +722,8 @@@ 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) { @@@ -738,8 -741,8 +738,8 @@@ for (SequenceI seq : dataset.getSequences()) { // first check primary refs. - List match = DBRefUtils.searchRefs(seq.getPrimaryDBRefs() - .toArray(new DBRefEntry[0]), template); + List match = DBRefUtils.searchRefs( + seq.getPrimaryDBRefs().toArray(new DBRefEntry[0]), template); if (match != null && match.size() == 1 && sameSequence(seq, dss)) { return seq; @@@ -749,9 -752,8 +749,8 @@@ * 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)) { @@@ -783,15 -785,15 +782,15 @@@ { 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) */ @@@ -862,8 -864,8 +861,8 @@@ MapList mapping = null; SequenceI dsmapFrom = mapFrom.getDatasetSequence() == null ? mapFrom : mapFrom.getDatasetSequence(); - SequenceI dsmapTo = mapTo.getDatasetSequence() == null ? mapTo : mapTo - .getDatasetSequence(); + SequenceI dsmapTo = mapTo.getDatasetSequence() == null ? mapTo + : mapTo.getDatasetSequence(); /* * look for a reverse mapping, if found make its inverse. * Note - we do this on dataset sequences only. @@@ -947,7 -949,8 +946,8 @@@ * @return true if matches were found. */ private boolean searchDatasetXrefs(boolean fromDna, SequenceI sequenceI, - DBRefEntry[] lrfs, List foundSeqs, AlignedCodonFrame cf) + DBRefEntry[] lrfs, List foundSeqs, + AlignedCodonFrame cf) { boolean found = false; if (lrfs == null) @@@ -960,7 -963,8 +960,8 @@@ // add in wildcards xref.setVersion(null); xref.setMap(null); - found |= searchDataset(fromDna, sequenceI, xref, foundSeqs, cf, false); + found |= searchDataset(fromDna, sequenceI, xref, foundSeqs, cf, + false); } return found; } @@@ -1016,10 -1020,9 +1017,9 @@@ { 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) + ")"); } diff --combined src/jalview/analysis/Dna.java index 2106dc2,0128624..a10b037 --- a/src/jalview/analysis/Dna.java +++ b/src/jalview/analysis/Dna.java @@@ -45,6 -45,7 +45,6 @@@ import java.util.ArrayList import java.util.Arrays; import java.util.Comparator; import java.util.List; -import java.util.Map; public class Dna { @@@ -119,7 -120,8 +119,7 @@@ * @param ac2 * @return */ - public static final int compareCodonPos(AlignedCodon ac1, - AlignedCodon ac2) + public static final int compareCodonPos(AlignedCodon ac1, AlignedCodon ac2) { return comparator.compare(ac1, ac2); // return jalview_2_8_2compare(ac1, ac2); @@@ -133,7 -135,8 +133,8 @@@ * @param ac2 * @return */ - private static int jalview_2_8_2compare(AlignedCodon ac1, AlignedCodon ac2) + private static int jalview_2_8_2compare(AlignedCodon ac1, + AlignedCodon ac2) { if (ac1 == null || ac2 == null || (ac1.equals(ac2))) { @@@ -434,7 -437,8 +435,8 @@@ /* * Filled up a reading frame... */ - AlignedCodon alignedCodon = new AlignedCodon(cdp[0], cdp[1], cdp[2]); + AlignedCodon alignedCodon = new AlignedCodon(cdp[0], cdp[1], + cdp[2]); String aa = ResidueProperties.codonTranslate(new String(codon)); rf = 0; final String gapString = String.valueOf(gapChar); @@@ -443,10 -447,11 +445,11 @@@ aa = gapString; if (skipint == null) { - skipint = new int[] { alignedCodon.pos1, alignedCodon.pos3 /* - * cdp[0], - * cdp[2] - */}; + skipint = new int[] { alignedCodon.pos1, + alignedCodon.pos3 /* + * cdp[0], + * cdp[2] + */ }; } skipint[1] = alignedCodon.pos3; // cdp[2]; } @@@ -501,8 -506,8 +504,8 @@@ } if (vc + 2 < t.length) { - System.arraycopy(scontigs, vc + 2, t, vc, t.length - - vc + 2); + System.arraycopy(scontigs, vc + 2, t, vc, + t.length - vc + 2); } scontigs = t; } @@@ -595,9 -600,9 +598,9 @@@ } else if (!alignedCodons[aspos].equals(alignedCodon)) { - throw new IllegalStateException("Tried to coalign " - + alignedCodons[aspos].toString() + " with " - + alignedCodon.toString()); + throw new IllegalStateException( + "Tried to coalign " + alignedCodons[aspos].toString() + + " with " + alignedCodon.toString()); } if (aspos >= aaWidth) { @@@ -684,7 -689,7 +687,7 @@@ */ MapList map = new MapList(scontigs, new int[] { 1, resSize }, 3, 1); - transferCodedFeatures(selection, newseq, map, null, null); + transferCodedFeatures(selection, newseq, map); /* * Construct a dataset sequence for our new peptide. @@@ -753,15 -758,25 +756,15 @@@ /** * Given a peptide newly translated from a dna sequence, copy over and set any - * features on the peptide from the DNA. If featureTypes is null, all features - * on the dna sequence are searched (rather than just the displayed ones), and - * similarly for featureGroups. + * features on the peptide from the DNA. * * @param dna * @param pep * @param map - * @param featureTypes - * hash whose keys are the displayed feature type strings - * @param featureGroups - * hash where keys are feature groups and values are Boolean objects - * indicating if they are displayed. */ private static void transferCodedFeatures(SequenceI dna, SequenceI pep, - MapList map, Map featureTypes, - Map featureGroups) + MapList map) { - SequenceFeature[] sfs = dna.getSequenceFeatures(); - Boolean fgstate; DBRefEntry[] dnarefs = DBRefUtils.selectRefs(dna.getDBRefs(), DBRefSource.DNACODINGDBS); if (dnarefs != null) @@@ -775,15 -790,24 +778,15 @@@ } } } - if (sfs != null) + for (SequenceFeature sf : dna.getFeatures().getAllFeatures()) { - for (SequenceFeature sf : sfs) - { - fgstate = (featureGroups == null) ? null - : featureGroups.get(sf.featureGroup); - if ((featureTypes == null || featureTypes.containsKey(sf.getType())) - && (fgstate == null || fgstate.booleanValue())) + if (FeatureProperties.isCodingFeature(null, sf.getType())) { - if (FeatureProperties.isCodingFeature(null, sf.getType())) + // if (map.intersectsFrom(sf[f].begin, sf[f].end)) { - // if (map.intersectsFrom(sf[f].begin, sf[f].end)) - { - } } } - } } } diff --combined src/jalview/analysis/Rna.java index 3108ef3,94544e7..0d39abf --- a/src/jalview/analysis/Rna.java +++ b/src/jalview/analysis/Rna.java @@@ -31,11 -31,10 +31,11 @@@ import jalview.datamodel.SequenceFeatur import jalview.util.MessageManager; import java.util.ArrayList; +import java.util.HashMap; import java.util.Hashtable; import java.util.List; +import java.util.Map; import java.util.Stack; -import java.util.Vector; public class Rna { @@@ -49,7 -48,8 +49,8 @@@ */ public static boolean isOpeningParenthesis(char c) { - return ('A' <= c && c <= 'Z' || c == '(' || c == '[' || c == '{' || c == '<'); + return ('A' <= c && c <= 'Z' || c == '(' || c == '[' || c == '{' + || c == '<'); } /** @@@ -74,7 -74,8 +75,8 @@@ */ public static boolean isClosingParenthesis(char c) { - return ('a' <= c && c <= 'z' || c == ')' || c == ']' || c == '}' || c == '>'); + return ('a' <= c && c <= 'z' || c == ')' || c == ']' || c == '}' + || c == '>'); } /** @@@ -133,11 -134,11 +135,11 @@@ * @return * @throw {@link WUSSParseException} */ - public static Vector getSimpleBPs(CharSequence line) + protected static List getSimpleBPs(CharSequence line) throws WUSSParseException { Hashtable> stacks = new Hashtable>(); - Vector pairs = new Vector(); + List pairs = new ArrayList(); int i = 0; while (i < line.length()) { @@@ -160,8 -161,8 +162,8 @@@ if (!stacks.containsKey(opening)) { throw new WUSSParseException(MessageManager.formatMessage( - "exception.mismatched_unseen_closing_char", - new String[] { String.valueOf(base) }), i); + "exception.mismatched_unseen_closing_char", new String[] + { String.valueOf(base) }), i); } Stack stack = stacks.get(opening); @@@ -169,8 -170,8 +171,8 @@@ { // error whilst parsing i'th position. pass back throw new WUSSParseException(MessageManager.formatMessage( - "exception.mismatched_closing_char", - new String[] { String.valueOf(base) }), i); + "exception.mismatched_closing_char", new String[] + { String.valueOf(base) }), i); } int temp = stack.pop(); @@@ -188,17 -189,33 +190,17 @@@ * i (length of input string) */ throw new WUSSParseException(MessageManager.formatMessage( - "exception.mismatched_opening_char", - new String[] { String.valueOf(opening), - String.valueOf(stack.pop()) }), i); + "exception.mismatched_opening_char", new String[] + { String.valueOf(opening), String.valueOf(stack.pop()) }), + i); } } return pairs; } - public static SequenceFeature[] getBasePairs(List bps) - throws WUSSParseException - { - SequenceFeature[] outPairs = new SequenceFeature[bps.size()]; - for (int p = 0; p < bps.size(); p++) - { - SimpleBP bp = bps.get(p); - outPairs[p] = new SequenceFeature("RNA helix", "", "", bp.getBP5(), - bp.getBP3(), ""); - } - return outPairs; - } + - public static List getModeleBP(CharSequence line) - throws WUSSParseException - { - Vector bps = getSimpleBPs(line); - return new ArrayList(bps); - } + /** * Function to get the end position corresponding to a given start position @@@ -215,6 -232,88 +217,6 @@@ */ /** - * Figures out which helix each position belongs to and stores the helix - * number in the 'featureGroup' member of a SequenceFeature Based off of RALEE - * code ralee-helix-map. - * - * @param pairs - * Array of SequenceFeature (output from Rna.GetBasePairs) - */ - public static void HelixMap(SequenceFeature[] pairs) - { - - int helix = 0; // Number of helices/current helix - int lastopen = 0; // Position of last open bracket reviewed - int lastclose = 9999999; // Position of last close bracket reviewed - int i = pairs.length; // Number of pairs - - int open; // Position of an open bracket under review - int close; // Position of a close bracket under review - int j; // Counter - - Hashtable helices = new Hashtable(); - // Keep track of helix number for each position - - // Go through each base pair and assign positions a helix - for (i = 0; i < pairs.length; i++) - { - - open = pairs[i].getBegin(); - close = pairs[i].getEnd(); - - // System.out.println("open " + open + " close " + close); - // System.out.println("lastclose " + lastclose + " lastopen " + lastopen); - - // we're moving from right to left based on closing pair - /* - * catch things like <<..>>..<<..>> | - */ - if (open > lastclose) - { - helix++; - } - - /* - * catch things like <<..<<..>>..<<..>>>> | - */ - j = pairs.length - 1; - while (j >= 0) - { - int popen = pairs[j].getBegin(); - - // System.out.println("j " + j + " popen " + popen + " lastopen " - // +lastopen + " open " + open); - if ((popen < lastopen) && (popen > open)) - { - if (helices.containsValue(popen) - && ((helices.get(popen)) == helix)) - { - continue; - } - else - { - helix++; - break; - } - } - - j -= 1; - } - - // Put positions and helix information into the hashtable - helices.put(open, helix); - helices.put(close, helix); - - // Record helix as featuregroup - pairs[i].setFeatureGroup(Integer.toString(helix)); - - lastopen = open; - lastclose = close; - - } - } - - /** * Answers true if the character is a recognised symbol for RNA secondary * structure. Currently accepts a-z, A-Z, ()[]{}<>. * @@@ -403,76 -502,4 +405,76 @@@ return c; } } + + public static SequenceFeature[] getHelixMap(CharSequence rnaAnnotation) + throws WUSSParseException + { + List result = new ArrayList(); + + int helix = 0; // Number of helices/current helix + int lastopen = 0; // Position of last open bracket reviewed + int lastclose = 9999999; // Position of last close bracket reviewed + + Map helices = new HashMap(); + // Keep track of helix number for each position + + // Go through each base pair and assign positions a helix + List bps = getSimpleBPs(rnaAnnotation); + for (SimpleBP basePair : bps) + { + final int open = basePair.getBP5(); + final int close = basePair.getBP3(); + + // System.out.println("open " + open + " close " + close); + // System.out.println("lastclose " + lastclose + " lastopen " + lastopen); + + // we're moving from right to left based on closing pair + /* + * catch things like <<..>>..<<..>> | + */ + if (open > lastclose) + { + helix++; + } + + /* + * catch things like <<..<<..>>..<<..>>>> | + */ + int j = bps.size() - 1; + while (j >= 0) + { + int popen = bps.get(j).getBP5(); + + // System.out.println("j " + j + " popen " + popen + " lastopen " + // +lastopen + " open " + open); + if ((popen < lastopen) && (popen > open)) + { + if (helices.containsValue(popen) + && ((helices.get(popen)) == helix)) + { + continue; + } + else + { + helix++; + break; + } + } + j -= 1; + } + + // Put positions and helix information into the hashtable + helices.put(open, helix); + helices.put(close, helix); + + // Record helix as featuregroup + result.add(new SequenceFeature("RNA helix", "", open, close, + String.valueOf(helix))); + + lastopen = open; + lastclose = close; + } + + return result.toArray(new SequenceFeature[result.size()]); + } } diff --combined src/jalview/analysis/SeqsetUtils.java index 27b3041,2b21e5e..fabd0c6 --- a/src/jalview/analysis/SeqsetUtils.java +++ b/src/jalview/analysis/SeqsetUtils.java @@@ -27,7 -27,6 +27,7 @@@ import jalview.datamodel.SequenceI import java.util.Enumeration; import java.util.Hashtable; +import java.util.List; import java.util.Vector; public class SeqsetUtils @@@ -51,11 -50,15 +51,11 @@@ { sqinfo.put("Description", seq.getDescription()); } - Vector sfeat = new Vector(); - jalview.datamodel.SequenceFeature[] sfarray = seq.getSequenceFeatures(); - if (sfarray != null && sfarray.length > 0) - { - for (int i = 0; i < sfarray.length; i++) - { - sfeat.addElement(sfarray[i]); - } - } + + Vector sfeat = new Vector(); + List sfs = seq.getFeatures().getAllFeatures(); + sfeat.addAll(sfs); + if (seq.getDatasetSequence() == null) { sqinfo.put("SeqFeatures", sfeat); @@@ -92,8 -95,7 +92,8 @@@ String oldname = (String) sqinfo.get("Name"); Integer start = (Integer) sqinfo.get("Start"); Integer end = (Integer) sqinfo.get("End"); - Vector sfeatures = (Vector) sqinfo.get("SeqFeatures"); + Vector sfeatures = (Vector) sqinfo + .get("SeqFeatures"); Vector pdbid = (Vector) sqinfo.get("PdbId"); String description = (String) sqinfo.get("Description"); Sequence seqds = (Sequence) sqinfo.get("datasetSequence"); @@@ -116,22 -118,26 +116,21 @@@ sq.setEnd(end.intValue()); } - if ((sfeatures != null) && (sfeatures.size() > 0)) + if (sfeatures != null && !sfeatures.isEmpty()) { - SequenceFeature[] sfarray = new SequenceFeature[sfeatures.size()]; - for (int is = 0, isize = sfeatures.size(); is < isize; is++) - { - sfarray[is] = (SequenceFeature) sfeatures.elementAt(is); - } - sq.setSequenceFeatures(sfarray); + sq.setSequenceFeatures(sfeatures); } if (description != null) { sq.setDescription(description); } - if ((seqds != null) - && !(seqds.getName().equals("THISISAPLACEHOLDER") && seqds - .getLength() == 0)) + if ((seqds != null) && !(seqds.getName().equals("THISISAPLACEHOLDER") + && seqds.getLength() == 0)) { if (sfeatures != null) { - System.err - .println("Implementation error: setting dataset sequence for a sequence which has sequence features.\n\tDataset sequence features will not be visible."); + System.err.println( + "Implementation error: setting dataset sequence for a sequence which has sequence features.\n\tDataset sequence features will not be visible."); } sq.setDatasetSequence(seqds); } @@@ -254,8 -260,9 +253,9 @@@ if (unmatched.size() > 0 && !quiet) { System.err.println("Did not find matches for :"); - for (Enumeration i = unmatched.elements(); i.hasMoreElements(); System.out - .println(((SequenceI) i.nextElement()).getName())) + for (Enumeration i = unmatched.elements(); i + .hasMoreElements(); System.out + .println(((SequenceI) i.nextElement()).getName())) { ; } diff --combined src/jalview/analysis/scoremodels/FeatureDistanceModel.java index ddbaf73,c20d4f1..e506be2 --- a/src/jalview/analysis/scoremodels/FeatureDistanceModel.java +++ b/src/jalview/analysis/scoremodels/FeatureDistanceModel.java @@@ -124,8 -124,8 +124,8 @@@ public class FeatureDistanceModel exten /* * first record feature types in this column for each sequence */ - Map> sfap = findFeatureTypesAtColumn( - seqs, cpos); + Map> sfap = findFeatureTypesAtColumn(seqs, + cpos); /* * count feature types on either i'th or j'th sequence but not both @@@ -177,12 -177,10 +177,12 @@@ /** * Builds and returns a map containing a (possibly empty) list (one per * SeqCigar) of visible feature types at the given column position. The map - * has no entry for sequences which are gapped at the column position. + * does not include entries for features which straddle a gapped column + * positions. * * @param seqs * @param columnPosition + * (0..) * @return */ protected Map> findFeatureTypesAtColumn( @@@ -194,12 -192,9 +194,12 @@@ int spos = seq.findPosition(columnPosition); if (spos != -1) { + /* + * position is not a gap + */ Set types = new HashSet(); - List sfs = fr.findFeaturesAtRes(seq.getRefSeq(), - spos); + List sfs = fr.findFeaturesAtResidue( + seq.getRefSeq(), spos); for (SequenceFeature sf : sfs) { types.add(sf.getType()); diff --combined src/jalview/appletgui/APopupMenu.java index 80b2d73,6fdb49c..9d44479 --- a/src/jalview/appletgui/APopupMenu.java +++ b/src/jalview/appletgui/APopupMenu.java @@@ -76,8 -76,8 +76,8 @@@ import java.util.SortedMap import java.util.TreeMap; import java.util.Vector; - public class APopupMenu extends java.awt.PopupMenu implements - ActionListener, ItemListener + public class APopupMenu extends java.awt.PopupMenu + implements ActionListener, ItemListener { Menu groupMenu = new Menu(); @@@ -262,8 -262,9 +262,9 @@@ purinePyrimidineColour.setEnabled(false); nucleotideColour.setEnabled(false); } - editGroupName.setLabel(MessageManager.formatMessage( - "label.name_param", new Object[] { sg.getName() })); + editGroupName.setLabel( + MessageManager.formatMessage("label.name_param", new Object[] + { sg.getName() })); showText.setState(sg.getDisplayText()); showColourText.setState(sg.getColourText()); showBoxes.setState(sg.getDisplayBoxes()); @@@ -304,17 -305,18 +305,18 @@@ seqMenu.setLabel(seq.getName()); if (seq == ap.av.getAlignment().getSeqrep()) { - makeReferenceSeq.setLabel(MessageManager - .getString("action.unmark_as_reference"));// Unmark - // representative"); + makeReferenceSeq.setLabel( + MessageManager.getString("action.unmark_as_reference"));// Unmark + // representative"); } else { - makeReferenceSeq.setLabel(MessageManager - .getString("action.set_as_reference")); // ); + makeReferenceSeq.setLabel( + MessageManager.getString("action.set_as_reference")); // ); } - repGroup.setLabel(MessageManager.formatMessage( - "label.represent_group_with", new Object[] { seq.getName() })); + repGroup.setLabel(MessageManager + .formatMessage("label.represent_group_with", new Object[] + { seq.getName() })); } else { @@@ -446,8 -448,9 +448,9 @@@ /* * First for the currently selected sequence (if there is one): */ - final List selectedSequence = (seq == null ? Collections - . emptyList() : Arrays.asList(seq)); + final List selectedSequence = (seq == null + ? Collections. emptyList() + : Arrays.asList(seq)); buildAnnotationTypesMenus(seqShowAnnotationsMenu, seqHideAnnotationsMenu, selectedSequence); configureReferenceAnnotationsMenu(seqAddReferenceAnnotations, @@@ -456,9 -459,9 +459,9 @@@ /* * and repeat for the current selection group (if there is one): */ - final List selectedGroup = (ap.av.getSelectionGroup() == null ? Collections - . emptyList() : ap.av.getSelectionGroup() - .getSequences()); + final List selectedGroup = (ap.av.getSelectionGroup() == null + ? Collections. emptyList() + : ap.av.getSelectionGroup().getSequences()); buildAnnotationTypesMenus(groupShowAnnotationsMenu, groupHideAnnotationsMenu, selectedGroup); configureReferenceAnnotationsMenu(groupAddReferenceAnnotations, @@@ -485,8 -488,8 +488,8 @@@ SortedMap tipEntries = new TreeMap(); final Map> candidates = new LinkedHashMap>(); AlignmentI al = this.ap.av.getAlignment(); - AlignmentUtils.findAddableReferenceAnnotations(forSequences, - tipEntries, candidates, al); + AlignmentUtils.findAddableReferenceAnnotations(forSequences, tipEntries, + candidates, al); if (!candidates.isEmpty()) { StringBuilder tooltip = new StringBuilder(64); @@@ -751,9 -754,10 +754,10 @@@ seq = sg.getSequenceAt(0); } - EditNameDialog dialog = new EditNameDialog(seq.getSequenceAsString( - sg.getStartRes(), sg.getEndRes() + 1), null, - "Edit Sequence ", null, + EditNameDialog dialog = new EditNameDialog( + seq.getSequenceAsString(sg.getStartRes(), + sg.getEndRes() + 1), + null, "Edit Sequence ", null, ap.alignFrame, "Edit Sequence", 500, 100, true); @@@ -761,16 -765,16 +765,16 @@@ { EditCommand editCommand = new EditCommand( MessageManager.getString("label.edit_sequences"), - Action.REPLACE, dialog.getName().replace(' ', - ap.av.getGapCharacter()), + Action.REPLACE, + dialog.getName().replace(' ', ap.av.getGapCharacter()), sg.getSequencesAsArray(ap.av.getHiddenRepSequences()), sg.getStartRes(), sg.getEndRes() + 1, ap.av.getAlignment()); ap.alignFrame.addHistoryItem(editCommand); - ap.av.firePropertyChange("alignment", null, ap.av.getAlignment() - .getSequences()); + ap.av.firePropertyChange("alignment", null, + ap.av.getAlignment().getSequences()); } } } @@@ -807,8 -811,8 +811,8 @@@ ap.alignFrame.addHistoryItem(caseCommand); - ap.av.firePropertyChange("alignment", null, ap.av.getAlignment() - .getSequences()); + ap.av.firePropertyChange("alignment", null, + ap.av.getAlignment().getSequences()); } } @@@ -831,7 -835,7 +835,7 @@@ if (start <= end) { seqs.add(sg.getSequenceAt(i)); - features.add(new SequenceFeature(null, null, null, start, end, + features.add(new SequenceFeature(null, null, start, end, "Jalview")); } } @@@ -843,8 -847,7 +847,8 @@@ { ap.alignFrame.sequenceFeatures.setState(true); ap.av.setShowSequenceFeatures(true); - ap.highlightSearchResults(null); + ap.av.setSearchResults(null); // clear highlighting + ap.repaint(); // draw new/amended features } } } @@@ -861,15 -864,15 +865,15 @@@ Frame frame = new Frame(); frame.add(cap); - JalviewLite.addFrame(frame, MessageManager.formatMessage( - "label.selection_output_command", - new Object[] { e.getActionCommand() }), 600, 500); + JalviewLite.addFrame(frame, MessageManager + .formatMessage("label.selection_output_command", new Object[] + { e.getActionCommand() }), 600, 500); // JBPNote: getSelectionAsNewSequence behaviour has changed - this method // now returns a full copy of sequence data // TODO consider using getSequenceSelection instead here - FileFormatI fileFormat = FileFormats.getInstance().forName( - e.getActionCommand()); + FileFormatI fileFormat = FileFormats.getInstance() + .forName(e.getActionCommand()); cap.setText(new AppletFormatAdapter().formatSequences(fileFormat, ap.av.getShowJVSuffix(), ap, true)); @@@ -893,25 -896,26 +897,26 @@@ StringBuilder contents = new StringBuilder(128); for (SequenceI seq : sequences) { - contents.append(MessageManager.formatMessage( - "label.annotation_for_displayid", - new Object[] { seq.getDisplayId(true) })); + contents.append(MessageManager + .formatMessage("label.annotation_for_displayid", new Object[] + { seq.getDisplayId(true) })); new SequenceAnnotationReport(null).createSequenceAnnotationReport( - contents, - seq, - true, - true, - (ap.seqPanel.seqCanvas.fr != null) ? ap.seqPanel.seqCanvas.fr - .getMinMax() : null); + contents, seq, true, true, + (ap.seqPanel.seqCanvas.fr != null) + ? ap.seqPanel.seqCanvas.fr.getMinMax() + : null); contents.append("

    "); } Frame frame = new Frame(); frame.add(cap); - jalview.bin.JalviewLite.addFrame(frame, "Sequence Details for " - + (sequences.length == 1 ? sequences[0].getDisplayId(true) - : "Selection"), 600, 500); - cap.setText(MessageManager.formatMessage("label.html_content", - new Object[] { contents.toString() })); + jalview.bin.JalviewLite.addFrame(frame, + "Sequence Details for " + (sequences.length == 1 + ? sequences[0].getDisplayId(true) + : "Selection"), + 600, 500); + cap.setText( + MessageManager.formatMessage("label.html_content", new Object[] + { contents.toString() })); } void editName() @@@ -943,21 -947,22 +948,22 @@@ } else { - new MCview.AppletPDBViewer(entry, new SequenceI[] { seq }, null, - ap, DataSourceType.URL); + new MCview.AppletPDBViewer(entry, new SequenceI[] { seq }, null, ap, + DataSourceType.URL); } } else { - CutAndPasteTransfer cap = new CutAndPasteTransfer(true, ap.alignFrame); + CutAndPasteTransfer cap = new CutAndPasteTransfer(true, + ap.alignFrame); cap.setText(MessageManager.getString("label.paste_pdb_file")); cap.setPDBImport(seq); Frame frame = new Frame(); frame.add(cap); JalviewLite.addFrame(frame, MessageManager.formatMessage( - "label.paste_pdb_file_for_sequence", - new Object[] { seq.getName() }), 400, 300); + "label.paste_pdb_file_for_sequence", new Object[] + { seq.getName() }), 400, 300); } } @@@ -967,12 -972,12 +973,12 @@@ sequenceFeature.addActionListener(this); editGroupName.addActionListener(this); - unGroupMenuItem.setLabel(MessageManager - .getString("action.remove_group")); + unGroupMenuItem + .setLabel(MessageManager.getString("action.remove_group")); unGroupMenuItem.addActionListener(this); - createGroupMenuItem.setLabel(MessageManager - .getString("action.create_group")); + createGroupMenuItem + .setLabel(MessageManager.getString("action.create_group")); createGroupMenuItem.addActionListener(this); modifyPID.setEnabled(abovePIDColour.getState()); @@@ -984,8 -989,8 +990,8 @@@ sequenceName.addActionListener(this); sequenceDetails.addActionListener(this); selSeqDetails.addActionListener(this); - displayNonconserved.setLabel(MessageManager - .getString("label.show_non_conserved")); + displayNonconserved + .setLabel(MessageManager.getString("label.show_non_conserved")); displayNonconserved.setState(false); displayNonconserved.addItemListener(this); showText.setLabel(MessageManager.getString("action.text")); @@@ -996,8 -1001,9 +1002,9 @@@ seqMenu.setLabel(MessageManager.getString("label.sequence")); pdb.setLabel(MessageManager.getString("label.view_pdb_structure")); hideSeqs.setLabel(MessageManager.getString("action.hide_sequences")); - repGroup.setLabel(MessageManager.formatMessage( - "label.represent_group_with", new Object[] { "" })); + repGroup.setLabel(MessageManager + .formatMessage("label.represent_group_with", new Object[] + { "" })); revealAll.setLabel(MessageManager.getString("action.reveal_all")); revealSeq.setLabel(MessageManager.getString("action.reveal_sequences")); menu1.setLabel(MessageManager.getString("label.group:")); @@@ -1043,28 -1049,28 +1050,28 @@@ /* * setName allows setSelectedColour to do its thing */ - clustalColour.setLabel(MessageManager - .getString("label.colourScheme_clustal")); + clustalColour.setLabel( + MessageManager.getString("label.colourScheme_clustal")); clustalColour.setName(JalviewColourScheme.Clustal.toString()); clustalColour.addItemListener(this); - BLOSUM62Colour.setLabel(MessageManager - .getString("label.colourScheme_blosum62")); + BLOSUM62Colour.setLabel( + MessageManager.getString("label.colourScheme_blosum62")); BLOSUM62Colour.setName(JalviewColourScheme.Blosum62.toString()); BLOSUM62Colour.addItemListener(this); - PIDColour.setLabel(MessageManager - .getString("label.colourScheme_%_identity")); + PIDColour.setLabel( + MessageManager.getString("label.colourScheme_%_identity")); PIDColour.setName(JalviewColourScheme.PID.toString()); PIDColour.addItemListener(this); - zappoColour.setLabel(MessageManager - .getString("label.colourScheme_zappo")); + zappoColour + .setLabel(MessageManager.getString("label.colourScheme_zappo")); zappoColour.setName(JalviewColourScheme.Zappo.toString()); zappoColour.addItemListener(this); - taylorColour.setLabel(MessageManager - .getString("label.colourScheme_taylor")); + taylorColour.setLabel( + MessageManager.getString("label.colourScheme_taylor")); taylorColour.setName(JalviewColourScheme.Taylor.toString()); taylorColour.addItemListener(this); - hydrophobicityColour.setLabel(MessageManager - .getString("label.colourScheme_hydrophobic")); + hydrophobicityColour.setLabel( + MessageManager.getString("label.colourScheme_hydrophobic")); hydrophobicityColour .setName(JalviewColourScheme.Hydrophobic.toString()); hydrophobicityColour.addItemListener(this); @@@ -1076,36 -1082,36 +1083,36 @@@ .getString("label.colourScheme_strand_propensity")); strandColour.setName(JalviewColourScheme.Strand.toString()); strandColour.addItemListener(this); - turnColour.setLabel(MessageManager - .getString("label.colourScheme_turn_propensity")); + turnColour.setLabel( + MessageManager.getString("label.colourScheme_turn_propensity")); turnColour.setName(JalviewColourScheme.Turn.toString()); turnColour.addItemListener(this); - buriedColour.setLabel(MessageManager - .getString("label.colourScheme_buried_index")); + buriedColour.setLabel( + MessageManager.getString("label.colourScheme_buried_index")); buriedColour.setName(JalviewColourScheme.Buried.toString()); buriedColour.addItemListener(this); - nucleotideColour.setLabel(MessageManager - .getString("label.colourScheme_nucleotide")); + nucleotideColour.setLabel( + MessageManager.getString("label.colourScheme_nucleotide")); nucleotideColour.setName(JalviewColourScheme.Nucleotide.toString()); nucleotideColour.addItemListener(this); purinePyrimidineColour.setLabel(MessageManager .getString("label.colourScheme_purine/pyrimidine")); - purinePyrimidineColour.setName(JalviewColourScheme.PurinePyrimidine - .toString()); + purinePyrimidineColour + .setName(JalviewColourScheme.PurinePyrimidine.toString()); purinePyrimidineColour.addItemListener(this); - userDefinedColour.setLabel(MessageManager - .getString("action.user_defined")); + userDefinedColour + .setLabel(MessageManager.getString("action.user_defined")); userDefinedColour.addActionListener(this); - abovePIDColour.setLabel(MessageManager - .getString("label.above_identity_threshold")); + abovePIDColour.setLabel( + MessageManager.getString("label.above_identity_threshold")); abovePIDColour.addItemListener(this); - modifyPID.setLabel(MessageManager - .getString("label.modify_identity_threshold")); + modifyPID.setLabel( + MessageManager.getString("label.modify_identity_threshold")); modifyPID.addActionListener(this); - conservationColour.setLabel(MessageManager - .getString("action.by_conservation")); + conservationColour + .setLabel(MessageManager.getString("action.by_conservation")); conservationColour.addItemListener(this); modifyConservation.setLabel(MessageManager .getString("label.modify_conservation_threshold")); @@@ -1162,8 -1168,8 +1169,8 @@@ protected void clustalColour_actionPerformed() { SequenceGroup sg = getGroup(); - sg.cs = new ResidueShader(new ClustalxColourScheme(sg, - ap.av.getHiddenRepSequences())); + sg.cs = new ResidueShader( + new ClustalxColourScheme(sg, ap.av.getHiddenRepSequences())); refresh(); } @@@ -1217,8 -1223,7 +1224,7 @@@ public void purinePyrimidineColour_actionPerformed() { - getGroup().cs = new ResidueShader( - new PurinePyrimidineColourScheme()); + getGroup().cs = new ResidueShader(new PurinePyrimidineColourScheme()); refresh(); } @@@ -1232,10 -1237,11 +1238,11 @@@ if (abovePIDColour.getState()) { - sg.cs.setConsensus(AAFrequency.calculate(sg.getSequences(ap.av - .getHiddenRepSequences()), 0, ap.av.getAlignment().getWidth())); - int threshold = SliderPanel.setPIDSliderSource(ap, sg.cs, getGroup() - .getName()); + sg.cs.setConsensus(AAFrequency.calculate( + sg.getSequences(ap.av.getHiddenRepSequences()), 0, + ap.av.getAlignment().getWidth())); + int threshold = SliderPanel.setPIDSliderSource(ap, sg.cs, + getGroup().getName()); sg.cs.setThreshold(threshold, ap.av.isIgnoreGapsConsensus()); @@@ -1261,8 -1267,9 +1268,9 @@@ { SequenceGroup sg = getGroup(); sg.cs = new ResidueShader(new PIDColourScheme()); - sg.cs.setConsensus(AAFrequency.calculate(sg.getSequences(ap.av - .getHiddenRepSequences()), 0, ap.av.getAlignment().getWidth())); + sg.cs.setConsensus(AAFrequency.calculate( + sg.getSequences(ap.av.getHiddenRepSequences()), 0, + ap.av.getAlignment().getWidth())); refresh(); } @@@ -1272,8 -1279,9 +1280,9 @@@ sg.cs = new ResidueShader(new Blosum62ColourScheme()); - sg.cs.setConsensus(AAFrequency.calculate(sg.getSequences(ap.av - .getHiddenRepSequences()), 0, ap.av.getAlignment().getWidth())); + sg.cs.setConsensus(AAFrequency.calculate( + sg.getSequences(ap.av.getHiddenRepSequences()), 0, + ap.av.getAlignment().getWidth())); refresh(); } @@@ -1295,10 -1303,9 +1304,9 @@@ if (conservationColour.getState()) { Conservation conservation = Conservation.calculateConservation( - "Group", sg - .getSequences(ap.av.getHiddenRepSequences()), 0, ap.av - .getAlignment().getWidth(), false, ap.av.getConsPercGaps(), - false); + "Group", sg.getSequences(ap.av.getHiddenRepSequences()), 0, + ap.av.getAlignment().getWidth(), false, + ap.av.getConsPercGaps(), false); sg.getGroupColourScheme().setConservation(conservation); SliderPanel.setConservationSlider(ap, sg.cs, sg.getName()); SliderPanel.showConservationSlider(); @@@ -1413,9 -1420,11 +1421,11 @@@ showMenu.removeAll(); hideMenu.removeAll(); - final List all = Arrays.asList(new String[] { MessageManager - .getString("label.all") }); - addAnnotationTypeToShowHide(showMenu, forSequences, "", all, true, true); + final List all = Arrays + .asList(new String[] + { MessageManager.getString("label.all") }); + addAnnotationTypeToShowHide(showMenu, forSequences, "", all, true, + true); addAnnotationTypeToShowHide(hideMenu, forSequences, "", all, true, false); showMenu.addSeparator(); diff --combined src/jalview/appletgui/AlignFrame.java index b30c5ae,b48dec9..ed04a0a --- a/src/jalview/appletgui/AlignFrame.java +++ b/src/jalview/appletgui/AlignFrame.java @@@ -173,15 -173,15 +173,15 @@@ public class AlignFrame extends Embmenu } public AlignFrame(AlignmentI al, SequenceI[] hiddenSeqs, - HiddenColumns hidden, JalviewLite applet, - String title, boolean embedded) + HiddenColumns hidden, JalviewLite applet, String title, + boolean embedded) { this(al, hiddenSeqs, hidden, applet, title, embedded, true); } public AlignFrame(AlignmentI al, SequenceI[] hiddenSeqs, - HiddenColumns hidden, JalviewLite applet, - String title, boolean embedded, boolean addToDisplay) + HiddenColumns hidden, JalviewLite applet, String title, + boolean embedded, boolean addToDisplay) { if (applet != null) { @@@ -390,8 -390,8 +390,8 @@@ { Map colours = alignPanel.seqPanel.seqCanvas .getFeatureRenderer().getFeatureColours(); - boolean relaxedIdMatching = viewport.applet.getDefaultParameter( - "relaxedidmatch", false); + boolean relaxedIdMatching = viewport.applet + .getDefaultParameter("relaxedidmatch", false); featuresFile = new FeaturesFile(file, sourceType).parse( viewport.getAlignment(), colours, true, relaxedIdMatching); } catch (Exception ex) @@@ -428,9 -428,10 +428,10 @@@ ViewportRanges ranges = viewport.getRanges(); if (viewport.cursorMode - && ((evt.getKeyCode() >= KeyEvent.VK_0 && evt.getKeyCode() <= KeyEvent.VK_9) || (evt - .getKeyCode() >= KeyEvent.VK_NUMPAD0 && evt - .getKeyCode() <= KeyEvent.VK_NUMPAD9)) + && ((evt.getKeyCode() >= KeyEvent.VK_0 + && evt.getKeyCode() <= KeyEvent.VK_9) + || (evt.getKeyCode() >= KeyEvent.VK_NUMPAD0 + && evt.getKeyCode() <= KeyEvent.VK_NUMPAD9)) && Character.isDigit(evt.getKeyChar())) { alignPanel.seqPanel.numberPressed(evt.getKeyChar()); @@@ -573,9 -574,9 +574,9 @@@ case KeyEvent.VK_F2: viewport.cursorMode = !viewport.cursorMode; - statusBar.setText(MessageManager.formatMessage( - "label.keyboard_editing_mode", - new String[] { (viewport.cursorMode ? "on" : "off") })); + statusBar.setText(MessageManager + .formatMessage("label.keyboard_editing_mode", new String[] + { (viewport.cursorMode ? "on" : "off") })); if (viewport.cursorMode) { alignPanel.seqPanel.seqCanvas.cursorX = ranges.getStartRes(); @@@ -708,9 -709,8 +709,8 @@@ // Hide everything by the current selection - this is a hack - we do the // invert and then hide // first check that there will be visible columns after the invert. - if (viewport.hasSelectedColumns() - || (sg != null && sg.getSize() > 0 && sg.getStartRes() <= sg - .getEndRes())) + if (viewport.hasSelectedColumns() || (sg != null && sg.getSize() > 0 + && sg.getStartRes() <= sg.getEndRes())) { // now invert the sequence set, if required - empty selection implies // that no hiding is required. @@@ -839,16 -839,18 +839,18 @@@ { boolean newState = sortAnnBySequence.getState(); sortAnnByLabel.setState(false); - setAnnotationSortOrder(newState ? SequenceAnnotationOrder.SEQUENCE_AND_LABEL - : SequenceAnnotationOrder.NONE); + setAnnotationSortOrder( + newState ? SequenceAnnotationOrder.SEQUENCE_AND_LABEL + : SequenceAnnotationOrder.NONE); setViewportAnnotationOrder(); } else if (source == sortAnnByLabel) { boolean newState = sortAnnByLabel.getState(); sortAnnBySequence.setState(false); - setAnnotationSortOrder(newState ? SequenceAnnotationOrder.LABEL_AND_SEQUENCE - : SequenceAnnotationOrder.NONE); + setAnnotationSortOrder( + newState ? SequenceAnnotationOrder.LABEL_AND_SEQUENCE + : SequenceAnnotationOrder.NONE); setViewportAnnotationOrder(); } else if (source == showAutoFirst) @@@ -1208,9 -1210,9 +1210,9 @@@ cap.setText(contents.toString()); Frame frame = new Frame(); frame.add(cap); - jalview.bin.JalviewLite.addFrame(frame, MessageManager.formatMessage( - "label.alignment_properties", new String[] { getTitle() }), - 400, 250); + jalview.bin.JalviewLite.addFrame(frame, MessageManager + .formatMessage("label.alignment_properties", new String[] + { getTitle() }), 400, 250); } else if (source == overviewMenuItem) { @@@ -1371,15 -1373,15 +1373,15 @@@ CutAndPasteTransfer cap = new CutAndPasteTransfer(true, this); Frame frame = new Frame(); frame.add(cap); - JalviewLite.addFrame(frame, MessageManager.formatMessage( - "label.alignment_output_command", - new Object[] { e.getActionCommand() }), 600, 500); - - FileFormatI fileFormat = FileFormats.getInstance().forName( - e.getActionCommand()); - cap.setText(new AppletFormatAdapter(alignPanel).formatSequences( - fileFormat, viewport.getAlignment(), - viewport.getShowJVSuffix())); + JalviewLite.addFrame(frame, MessageManager + .formatMessage("label.alignment_output_command", new Object[] + { e.getActionCommand() }), 600, 500); + + FileFormatI fileFormat = FileFormats.getInstance() + .forName(e.getActionCommand()); + cap.setText( + new AppletFormatAdapter(alignPanel).formatSequences(fileFormat, + viewport.getAlignment(), viewport.getShowJVSuffix())); } public void loadAnnotations() @@@ -1424,32 -1426,21 +1426,32 @@@ return null; } + private List getDisplayedFeatureGroups() + { + if (alignPanel.getFeatureRenderer() != null + && viewport.getFeaturesDisplayed() != null) + { + return alignPanel.getFeatureRenderer().getDisplayedFeatureGroups(); + + } + return null; + } + public String outputFeatures(boolean displayTextbox, String format) { String features; FeaturesFile formatter = new FeaturesFile(); if (format.equalsIgnoreCase("Jalview")) { - features = formatter.printJalviewFormat( - viewport.getAlignment().getSequencesArray(), - getDisplayedFeatureCols()); + features = formatter.printJalviewFormat(viewport.getAlignment() + .getSequencesArray(), getDisplayedFeatureCols(), + getDisplayedFeatureGroups(), true); } else { - features = formatter.printGffFormat( - viewport.getAlignment().getSequencesArray(), - getDisplayedFeatureCols()); + features = formatter.printGffFormat(viewport.getAlignment() + .getSequencesArray(), getDisplayedFeatureCols(), + getDisplayedFeatureGroups(), true); } if (displayTextbox) @@@ -1492,8 -1483,8 +1494,8 @@@ : "?"; url.append(firstSep); - url.append("open=" - + appendProtocol(viewport.applet.getParameter("file"))); + url.append( + "open=" + appendProtocol(viewport.applet.getParameter("file"))); if (viewport.applet.getParameter("features") != null) { @@@ -1504,30 -1495,30 +1506,30 @@@ if (viewport.applet.getParameter("annotations") != null) { url.append("&annotations="); - url.append(appendProtocol(viewport.applet.getParameter("annotations"))); + url.append( + appendProtocol(viewport.applet.getParameter("annotations"))); } if (viewport.applet.getParameter("jnetfile") != null || viewport.applet.getParameter("jpredfile") != null) { url.append("&annotations="); - url.append(appendProtocol(viewport.applet.getParameter("jnetfile") != null ? viewport.applet - .getParameter("jnetfile") : viewport.applet - .getParameter("jpredfile"))); + url.append(appendProtocol( + viewport.applet.getParameter("jnetfile") != null + ? viewport.applet.getParameter("jnetfile") + : viewport.applet.getParameter("jpredfile"))); } if (viewport.applet.getParameter("defaultColour") != null) { - url.append("&colour=" - + removeWhiteSpace(viewport.applet - .getParameter("defaultColour"))); + url.append("&colour=" + removeWhiteSpace( + viewport.applet.getParameter("defaultColour"))); } if (viewport.applet.getParameter("userDefinedColour") != null) { - url.append("&colour=" - + removeWhiteSpace(viewport.applet - .getParameter("userDefinedColour"))); + url.append("&colour=" + removeWhiteSpace( + viewport.applet.getParameter("userDefinedColour"))); } if (viewport.applet.getParameter("tree") != null) { @@@ -1617,9 -1608,9 +1619,9 @@@ { undoMenuItem.setEnabled(true); CommandI command = viewport.getHistoryList().peek(); - undoMenuItem.setLabel(MessageManager.formatMessage( - "label.undo_command", - new Object[] { command.getDescription() })); + undoMenuItem.setLabel(MessageManager + .formatMessage("label.undo_command", new Object[] + { command.getDescription() })); } else { @@@ -1632,9 -1623,9 +1634,9 @@@ redoMenuItem.setEnabled(true); CommandI command = viewport.getRedoList().peek(); - redoMenuItem.setLabel(MessageManager.formatMessage( - "label.redo_command", - new Object[] { command.getDescription() })); + redoMenuItem.setLabel(MessageManager + .formatMessage("label.redo_command", new Object[] + { command.getDescription() })); } else { @@@ -1686,8 -1677,8 +1688,8 @@@ // viewport.getColumnSelection().getHiddenColumns() // != null; updateEditMenuBar(); - originalSource.firePropertyChange("alignment", null, originalSource - .getAlignment().getSequences()); + originalSource.firePropertyChange("alignment", null, + originalSource.getAlignment().getSequences()); } /** @@@ -1719,8 -1710,8 +1721,8 @@@ // != null; updateEditMenuBar(); - originalSource.firePropertyChange("alignment", null, originalSource - .getAlignment().getSequences()); + originalSource.firePropertyChange("alignment", null, + originalSource.getAlignment().getSequences()); } AlignmentViewport getOriginatingSource(CommandI command) @@@ -1734,8 -1725,8 +1736,8 @@@ { EditCommand editCommand = (EditCommand) command; al = editCommand.getAlignment(); - Vector comps = (Vector) PaintRefresher.components.get(viewport - .getSequenceSetId()); - Vector comps = (Vector) PaintRefresher.components ++ Vector comps = PaintRefresher.components + .get(viewport.getSequenceSetId()); for (int i = 0; i < comps.size(); i++) { if (comps.elementAt(i) instanceof AlignmentPanel) @@@ -1800,15 -1791,15 +1802,15 @@@ List sg = new Vector<>(); if (viewport.cursorMode) { - sg.add(viewport.getAlignment().getSequenceAt( - alignPanel.seqPanel.seqCanvas.cursorY)); + sg.add(viewport.getAlignment() + .getSequenceAt(alignPanel.seqPanel.seqCanvas.cursorY)); } else if (viewport.getSelectionGroup() != null && viewport.getSelectionGroup().getSize() != viewport .getAlignment().getHeight()) { - sg = viewport.getSelectionGroup().getSequences( - viewport.getHiddenRepSequences()); + sg = viewport.getSelectionGroup() + .getSequences(viewport.getHiddenRepSequences()); } if (sg.size() < 1) @@@ -1828,8 -1819,8 +1830,8 @@@ SequenceI[] seqs1 = sg.toArray(new SequenceI[sg.size()]); - SequenceI[] seqs2 = invertGroup.toArray(new SequenceI[invertGroup - .size()]); + SequenceI[] seqs2 = invertGroup + .toArray(new SequenceI[invertGroup.size()]); for (int i = 0; i < invertGroup.size(); i++) { seqs2[i] = invertGroup.elementAt(i); @@@ -1838,13 -1829,13 +1840,13 @@@ SlideSequencesCommand ssc; if (right) { - ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1, - size, viewport.getGapCharacter()); + ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1, size, + viewport.getGapCharacter()); } else { - ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2, - size, viewport.getGapCharacter()); + ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2, size, + viewport.getGapCharacter()); } int groupAdjustment = 0; @@@ -1884,9 -1875,8 +1886,8 @@@ if (historyList != null && historyList.size() > 0 && historyList.peek() instanceof SlideSequencesCommand) { - appendHistoryItem = ssc - .appendSlideCommand((SlideSequencesCommand) historyList - .peek()); + appendHistoryItem = ssc.appendSlideCommand( + (SlideSequencesCommand) historyList.peek()); } if (!appendHistoryItem) @@@ -1977,14 -1967,10 +1978,10 @@@ endRes += seq.getStart() - 1; } - copiedSequences.append(seq.getName() - + "\t" - + startRes - + "\t" - + endRes - + "\t" - + seq.getSequenceAsString(sg.getStartRes(), - sg.getEndRes() + 1) + "\n"); + copiedSequences.append(seq.getName() + "\t" + startRes + "\t" + endRes + + "\t" + seq.getSequenceAsString(sg.getStartRes(), + sg.getEndRes() + 1) + + "\n"); } } @@@ -2035,8 -2021,9 +2032,9 @@@ } else { - newtitle = newtitle.concat(MessageManager.formatMessage( - "label.from_msname", new String[] { getTitle() })); + newtitle = newtitle.concat(MessageManager + .formatMessage("label.from_msname", new String[] + { getTitle() })); } AlignFrame af = new AlignFrame(new Alignment(newSeqs), viewport.applet, newtitle, false); @@@ -2078,8 -2065,8 +2076,8 @@@ viewport.getRanges().setEndSeq(viewport.getAlignment().getHeight()); viewport.getAlignment().getWidth(); - viewport.firePropertyChange("alignment", null, viewport.getAlignment() - .getSequences()); + viewport.firePropertyChange("alignment", null, + viewport.getAlignment().getSequences()); } @@@ -2111,15 -2098,15 +2109,15 @@@ */ if (sg.getSize() == viewport.getAlignment().getHeight()) { - boolean isEntireAlignWidth = (((sg.getEndRes() - sg.getStartRes()) + 1) == viewport - .getAlignment().getWidth()) ? true : false; + boolean isEntireAlignWidth = (((sg.getEndRes() - sg.getStartRes()) + + 1) == viewport.getAlignment().getWidth()) ? true : false; if (isEntireAlignWidth) { String title = MessageManager.getString("label.delete_all"); Panel infoPanel = new Panel(); infoPanel.setLayout(new FlowLayout()); - infoPanel - .add(new Label(MessageManager.getString("warn.delete_all"))); + infoPanel.add( + new Label(MessageManager.getString("warn.delete_all"))); final JVDialog dialog = new JVDialog(this, title, true, 400, 200); dialog.setMainPanel(infoPanel); @@@ -2153,8 -2140,8 +2151,8 @@@ viewport.setSelectionGroup(null); viewport.getAlignment().deleteGroup(sg); - viewport.firePropertyChange("alignment", null, viewport.getAlignment() - .getSequences()); + viewport.firePropertyChange("alignment", null, + viewport.getAlignment().getSequences()); if (viewport.getAlignment().getHeight() < 1) { @@@ -2331,8 -2318,8 +2329,8 @@@ SequenceI[] seqs; if (viewport.getSelectionGroup() != null) { - seqs = viewport.getSelectionGroup().getSequencesAsArray( - viewport.getHiddenRepSequences()); + seqs = viewport.getSelectionGroup() + .getSequencesAsArray(viewport.getHiddenRepSequences()); } else { @@@ -2352,10 -2339,9 +2350,9 @@@ column, al); } - statusBar.setText(MessageManager.formatMessage( - "label.removed_columns", - new String[] { Integer.valueOf(trimRegion.getSize()) - .toString() })); + statusBar.setText(MessageManager + .formatMessage("label.removed_columns", new String[] + { Integer.valueOf(trimRegion.getSize()).toString() })); addHistoryItem(trimRegion); for (SequenceGroup sg : al.getGroups()) @@@ -2381,8 -2367,8 +2378,8 @@@ SequenceI[] seqs; if (viewport.getSelectionGroup() != null) { - seqs = viewport.getSelectionGroup().getSequencesAsArray( - viewport.getHiddenRepSequences()); + seqs = viewport.getSelectionGroup() + .getSequencesAsArray(viewport.getHiddenRepSequences()); start = viewport.getSelectionGroup().getStartRes(); end = viewport.getSelectionGroup().getEndRes(); } @@@ -2397,10 -2383,9 +2394,9 @@@ addHistoryItem(removeGapCols); - statusBar.setText(MessageManager.formatMessage( - "label.removed_empty_columns", - new String[] { Integer.valueOf(removeGapCols.getSize()) - .toString() })); + statusBar.setText(MessageManager + .formatMessage("label.removed_empty_columns", new String[] + { Integer.valueOf(removeGapCols.getSize()).toString() })); // This is to maintain viewport position on first residue // of first sequence @@@ -2426,8 -2411,8 +2422,8 @@@ SequenceI[] seqs; if (viewport.getSelectionGroup() != null) { - seqs = viewport.getSelectionGroup().getSequencesAsArray( - viewport.getHiddenRepSequences()); + seqs = viewport.getSelectionGroup() + .getSequencesAsArray(viewport.getHiddenRepSequences()); start = viewport.getSelectionGroup().getStartRes(); end = viewport.getSelectionGroup().getEndRes(); } @@@ -2441,8 -2426,8 +2437,8 @@@ SequenceI seq = al.getSequenceAt(0); int startRes = seq.findPosition(ranges.getStartRes()); - addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end, - al)); + addHistoryItem( + new RemoveGapsCommand("Remove Gaps", seqs, start, end, al)); ranges.setStartRes(seq.findIndex(startRes) - 1); @@@ -2476,12 -2461,14 +2472,14 @@@ if (viewport.getAlignment().getAlignmentAnnotation() != null) { - for (int i = 0; i < viewport.getAlignment().getAlignmentAnnotation().length; i++) + for (int i = 0; i < viewport.getAlignment() + .getAlignmentAnnotation().length; i++) { - if (!viewport.getAlignment().getAlignmentAnnotation()[i].autoCalculated) + if (!viewport.getAlignment() + .getAlignmentAnnotation()[i].autoCalculated) { - newal.addAnnotation(viewport.getAlignment() - .getAlignmentAnnotation()[i]); + newal.addAnnotation( + viewport.getAlignment().getAlignmentAnnotation()[i]); } } } @@@ -2498,8 -2485,8 +2496,8 @@@ PaintRefresher.Register(newaf.alignPanel.seqPanel.seqCanvas, newaf.alignPanel.av.getSequenceSetId()); - Vector comps = (Vector) PaintRefresher.components.get(viewport - .getSequenceSetId()); - Vector comps = (Vector) PaintRefresher.components ++ Vector comps = PaintRefresher.components + .get(viewport.getSequenceSetId()); int viewSize = -1; for (int i = 0; i < comps.size(); i++) { @@@ -2633,9 -2620,9 +2631,9 @@@ final OverviewPanel overview = new OverviewPanel(alignPanel); frame.add(overview); // +50 must allow for applet frame window - jalview.bin.JalviewLite.addFrame(frame, MessageManager.formatMessage( - "label.overview_params", new String[] { this.getTitle() }), - overview.getPreferredSize().width, + jalview.bin.JalviewLite.addFrame(frame, MessageManager + .formatMessage("label.overview_params", new String[] + { this.getTitle() }), overview.getPreferredSize().width, overview.getPreferredSize().height + 50); frame.pack(); @@@ -2732,8 -2719,8 +2730,8 @@@ public void sortPairwiseMenuItem_actionPerformed() { SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray(); - AlignmentSorter.sortByPID(viewport.getAlignment(), viewport - .getAlignment().getSequenceAt(0)); + AlignmentSorter.sortByPID(viewport.getAlignment(), + viewport.getAlignment().getSequenceAt(0)); addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder, viewport.getAlignment())); @@@ -2744,8 -2731,8 +2742,8 @@@ { SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray(); AlignmentSorter.sortByID(viewport.getAlignment()); - addHistoryItem(new OrderCommand("ID Sort", oldOrder, - viewport.getAlignment())); + addHistoryItem( + new OrderCommand("ID Sort", oldOrder, viewport.getAlignment())); alignPanel.paintAlignment(true); } @@@ -2794,7 -2781,8 +2792,8 @@@ SequenceI current; int Width = viewport.getAlignment().getWidth(); - for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++) + for (int i = 0; i < viewport.getAlignment().getSequences() + .size(); i++) { current = viewport.getAlignment().getSequenceAt(i); @@@ -2807,8 -2795,8 +2806,8 @@@ } if ((viewport.getSelectionGroup() != null - && viewport.getSelectionGroup().getSize() < 4 && viewport - .getSelectionGroup().getSize() > 0) + && viewport.getSelectionGroup().getSize() < 4 + && viewport.getSelectionGroup().getSize() > 0) || viewport.getAlignment().getHeight() < 4) { return; @@@ -2837,15 -2825,15 +2836,15 @@@ protected void njTreeBlosumMenuItem_actionPerformed() { - newTreePanel(TreeBuilder.NEIGHBOUR_JOINING, ScoreModels.getInstance() - .getBlosum62().getName(), + newTreePanel(TreeBuilder.NEIGHBOUR_JOINING, + ScoreModels.getInstance().getBlosum62().getName(), "Neighbour joining tree using BLOSUM62"); } protected void avTreeBlosumMenuItem_actionPerformed() { - newTreePanel(TreeBuilder.AVERAGE_DISTANCE, ScoreModels.getInstance() - .getBlosum62().getName(), + newTreePanel(TreeBuilder.AVERAGE_DISTANCE, + ScoreModels.getInstance().getBlosum62().getName(), "Average distance tree using BLOSUM62"); } @@@ -2857,7 -2845,8 +2856,8 @@@ SequenceI current; int Width = viewport.getAlignment().getWidth(); - for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++) + for (int i = 0; i < viewport.getAlignment().getSequences() + .size(); i++) { current = viewport.getAlignment().getSequenceAt(i); @@@ -2870,8 -2859,8 +2870,8 @@@ } - if ((viewport.getSelectionGroup() != null && viewport - .getSelectionGroup().getSize() > 1) + if ((viewport.getSelectionGroup() != null + && viewport.getSelectionGroup().getSize() > 1) || (viewport.getAlignment().getHeight() > 1)) { final TreePanel tp = new TreePanel(alignPanel, type, pwType); @@@ -2912,13 -2901,13 +2912,13 @@@ public void sortByTree(TreePanel treePanel, String title) { SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray(); - AlignmentSorter - .sortByTree(viewport.getAlignment(), treePanel.getTree()); + AlignmentSorter.sortByTree(viewport.getAlignment(), + treePanel.getTree()); // addHistoryItem(new HistoryItem("Sort", viewport.alignment, // HistoryItem.SORT)); - addHistoryItem(new OrderCommand(MessageManager.formatMessage( - "label.order_by_params", new String[] { title }), oldOrder, - viewport.getAlignment())); + addHistoryItem(new OrderCommand(MessageManager + .formatMessage("label.order_by_params", new String[] + { title }), oldOrder, viewport.getAlignment())); alignPanel.paintAlignment(true); } @@@ -3014,39 -3003,37 +3014,37 @@@ // TODO: update this text for each release or centrally store it for // lite and application g.setFont(new Font("Helvetica", Font.BOLD, 14)); - g.drawString(MessageManager.formatMessage( - "label.jalviewLite_release", new String[] { version }), x, - y += fh); + g.drawString(MessageManager + .formatMessage("label.jalviewLite_release", new String[] + { version }), x, y += fh); g.setFont(new Font("Helvetica", Font.BOLD, 12)); - g.drawString(MessageManager.formatMessage( - "label.jaview_build_date", new String[] { builddate }), x, - y += fh); + g.drawString(MessageManager.formatMessage("label.jaview_build_date", + new String[] + { builddate }), x, y += fh); g.setFont(new Font("Helvetica", Font.PLAIN, 12)); - g.drawString(MessageManager.getString("label.jalview_authors_1"), - x, y += fh * 1.5); + g.drawString(MessageManager.getString("label.jalview_authors_1"), x, + y += fh * 1.5); g.drawString(MessageManager.getString("label.jalview_authors_2"), x + 50, y += fh + 8); - g.drawString( - MessageManager.getString("label.jalview_dev_managers"), x, - y += fh); + g.drawString(MessageManager.getString("label.jalview_dev_managers"), + x, y += fh); g.drawString(MessageManager .getString("label.jalview_distribution_lists"), x, y += fh); g.drawString(MessageManager.getString("label.jalview_please_cite"), x, y += fh + 8); g.drawString( - MessageManager.getString("label.jalview_cite_1_authors"), - x, y += fh); - g.drawString( - MessageManager.getString("label.jalview_cite_1_title"), x, + MessageManager.getString("label.jalview_cite_1_authors"), x, y += fh); + g.drawString(MessageManager.getString("label.jalview_cite_1_title"), + x, y += fh); g.drawString(MessageManager.getString("label.jalview_cite_1_ref"), x, y += fh); } } Frame frame = new Frame(); - frame.add(new AboutPanel(JalviewLite.getVersion(), JalviewLite - .getBuildDate())); + frame.add(new AboutPanel(JalviewLite.getVersion(), + JalviewLite.getBuildDate())); jalview.bin.JalviewLite.addFrame(frame, MessageManager.getString("label.jalview"), 580, 220); @@@ -3319,20 -3306,20 +3317,20 @@@ pasteNew.addActionListener(this); pasteThis.setLabel(MessageManager.getString("label.to_this_alignment")); pasteThis.addActionListener(this); - remove2LeftMenuItem.setLabel(MessageManager - .getString("action.remove_left")); + remove2LeftMenuItem + .setLabel(MessageManager.getString("action.remove_left")); remove2LeftMenuItem.addActionListener(this); - remove2RightMenuItem.setLabel(MessageManager - .getString("action.remove_right")); + remove2RightMenuItem + .setLabel(MessageManager.getString("action.remove_right")); remove2RightMenuItem.addActionListener(this); - removeGappedColumnMenuItem.setLabel(MessageManager - .getString("action.remove_empty_columns")); + removeGappedColumnMenuItem.setLabel( + MessageManager.getString("action.remove_empty_columns")); removeGappedColumnMenuItem.addActionListener(this); - removeAllGapsMenuItem.setLabel(MessageManager - .getString("action.remove_all_gaps")); + removeAllGapsMenuItem + .setLabel(MessageManager.getString("action.remove_all_gaps")); removeAllGapsMenuItem.addActionListener(this); - removeRedundancyMenuItem.setLabel(MessageManager - .getString("action.remove_redundancy")); + removeRedundancyMenuItem + .setLabel(MessageManager.getString("action.remove_redundancy")); removeRedundancyMenuItem.addActionListener(this); /* @@@ -3342,25 -3329,25 +3340,25 @@@ findMenuItem.addActionListener(this); selectAllSequenceMenuItem.addActionListener(this); deselectAllSequenceMenuItem.addActionListener(this); - invertSequenceMenuItem.setLabel(MessageManager - .getString("action.invert_sequence_selection")); + invertSequenceMenuItem.setLabel( + MessageManager.getString("action.invert_sequence_selection")); invertSequenceMenuItem.addActionListener(this); - invertColSel.setLabel(MessageManager - .getString("action.invert_column_selection")); + invertColSel.setLabel( + MessageManager.getString("action.invert_column_selection")); invertColSel.addActionListener(this); - deleteGroups.setLabel(MessageManager - .getString("action.undefine_groups")); + deleteGroups + .setLabel(MessageManager.getString("action.undefine_groups")); deleteGroups.addActionListener(this); - grpsFromSelection.setLabel(MessageManager - .getString("action.make_groups_selection")); + grpsFromSelection.setLabel( + MessageManager.getString("action.make_groups_selection")); grpsFromSelection.addActionListener(this); createGroup.setLabel(MessageManager.getString("action.create_group")); createGroup.addActionListener(this); unGroup.setLabel(MessageManager.getString("action.remove_group")); unGroup.addActionListener(this); - annotationColumnSelection.setLabel(MessageManager - .getString("action.select_by_annotation")); + annotationColumnSelection.setLabel( + MessageManager.getString("action.select_by_annotation")); annotationColumnSelection.addActionListener(this); /* @@@ -3374,14 -3361,14 +3372,14 @@@ Menu hideMenu = new Menu(MessageManager.getString("action.hide")); hideColumns .setLabel(MessageManager.getString("label.selected_columns")); - hideSequences.setLabel(MessageManager - .getString("label.selected_sequences")); - hideAllButSelection.setLabel(MessageManager - .getString("label.all_but_selected_region")); - hideAllSelection.setLabel(MessageManager - .getString("label.selected_region")); - showAllHidden.setLabel(MessageManager - .getString("label.all_sequences_columns")); + hideSequences + .setLabel(MessageManager.getString("label.selected_sequences")); + hideAllButSelection.setLabel( + MessageManager.getString("label.all_but_selected_region")); + hideAllSelection + .setLabel(MessageManager.getString("label.selected_region")); + showAllHidden.setLabel( + MessageManager.getString("label.all_sequences_columns")); showColumns.addActionListener(this); showSeqs.addActionListener(this); hideColumns.addActionListener(this); @@@ -3389,39 -3376,39 +3387,39 @@@ hideAllButSelection.addActionListener(this); hideAllSelection.addActionListener(this); showAllHidden.addActionListener(this); - featureSettings.setLabel(MessageManager - .getString("action.feature_settings")); + featureSettings + .setLabel(MessageManager.getString("action.feature_settings")); featureSettings.addActionListener(this); - sequenceFeatures.setLabel(MessageManager - .getString("label.show_sequence_features")); + sequenceFeatures.setLabel( + MessageManager.getString("label.show_sequence_features")); sequenceFeatures.addItemListener(this); sequenceFeatures.setState(false); - followMouseOverFlag.setLabel(MessageManager - .getString("label.automatic_scrolling")); + followMouseOverFlag.setLabel( + MessageManager.getString("label.automatic_scrolling")); followMouseOverFlag.addItemListener(this); alProperties.addActionListener(this); - overviewMenuItem.setLabel(MessageManager - .getString("label.overview_window")); + overviewMenuItem + .setLabel(MessageManager.getString("label.overview_window")); overviewMenuItem.addActionListener(this); /* * Configure Annotations menu items and actions */ - annotationPanelMenuItem.setLabel(MessageManager - .getString("label.show_annotations")); + annotationPanelMenuItem + .setLabel(MessageManager.getString("label.show_annotations")); annotationPanelMenuItem.addItemListener(this); - showGroupConsensus.setLabel(MessageManager - .getString("label.group_consensus")); - showGroupConservation.setLabel(MessageManager - .getString("label.group_conservation")); - showConsensusHistogram.setLabel(MessageManager - .getString("label.show_consensus_histogram")); - showSequenceLogo.setLabel(MessageManager - .getString("label.show_consensus_logo")); - normSequenceLogo.setLabel(MessageManager - .getString("label.norm_consensus_logo")); - applyAutoAnnotationSettings.setLabel(MessageManager - .getString("label.apply_all_groups")); + showGroupConsensus + .setLabel(MessageManager.getString("label.group_consensus")); + showGroupConservation + .setLabel(MessageManager.getString("label.group_conservation")); + showConsensusHistogram.setLabel( + MessageManager.getString("label.show_consensus_histogram")); + showSequenceLogo.setLabel( + MessageManager.getString("label.show_consensus_logo")); + normSequenceLogo.setLabel( + MessageManager.getString("label.norm_consensus_logo")); + applyAutoAnnotationSettings + .setLabel(MessageManager.getString("label.apply_all_groups")); applyAutoAnnotationSettings.setState(true); Menu autoAnnMenu = new Menu( MessageManager.getString("label.autocalculated_annotation")); @@@ -3476,44 -3463,44 +3474,44 @@@ viewTextMenuItem.setLabel(MessageManager.getString("action.text")); viewTextMenuItem.setState(true); viewTextMenuItem.addItemListener(this); - colourTextMenuItem.setLabel(MessageManager - .getString("label.colour_text")); + colourTextMenuItem + .setLabel(MessageManager.getString("label.colour_text")); colourTextMenuItem.addItemListener(this); - displayNonconservedMenuItem.setLabel(MessageManager - .getString("label.show_non_conserved")); + displayNonconservedMenuItem + .setLabel(MessageManager.getString("label.show_non_conserved")); displayNonconservedMenuItem.addItemListener(this); wrapMenuItem.setLabel(MessageManager.getString("action.wrap")); wrapMenuItem.addItemListener(this); - renderGapsMenuItem.setLabel(MessageManager - .getString("action.show_gaps")); + renderGapsMenuItem + .setLabel(MessageManager.getString("action.show_gaps")); renderGapsMenuItem.setState(true); renderGapsMenuItem.addItemListener(this); - centreColumnLabelFlag.setLabel(MessageManager - .getString("label.centre_column_labels")); + centreColumnLabelFlag.setLabel( + MessageManager.getString("label.centre_column_labels")); centreColumnLabelFlag.addItemListener(this); seqLimits.setState(true); - seqLimits.setLabel(MessageManager - .getString("label.show_sequence_limits")); + seqLimits.setLabel( + MessageManager.getString("label.show_sequence_limits")); seqLimits.addItemListener(this); /* * Configure Colour menu items and actions */ - applyToAllGroups.setLabel(MessageManager - .getString("label.apply_colour_to_all_groups")); + applyToAllGroups.setLabel( + MessageManager.getString("label.apply_colour_to_all_groups")); applyToAllGroups.setState(true); applyToAllGroups.addItemListener(this); - clustalColour.setLabel(MessageManager - .getString("label.colourScheme_clustal")); + clustalColour.setLabel( + MessageManager.getString("label.colourScheme_clustal")); clustalColour.addActionListener(this); - zappoColour.setLabel(MessageManager - .getString("label.colourScheme_zappo")); + zappoColour + .setLabel(MessageManager.getString("label.colourScheme_zappo")); zappoColour.addActionListener(this); - taylorColour.setLabel(MessageManager - .getString("label.colourScheme_taylor")); + taylorColour.setLabel( + MessageManager.getString("label.colourScheme_taylor")); taylorColour.addActionListener(this); - hydrophobicityColour.setLabel(MessageManager - .getString("label.colourScheme_hydrophobic")); + hydrophobicityColour.setLabel( + MessageManager.getString("label.colourScheme_hydrophobic")); hydrophobicityColour.addActionListener(this); helixColour.setLabel(MessageManager .getString("label.colourScheme_helix_propensity")); @@@ -3521,11 -3508,11 +3519,11 @@@ strandColour.setLabel(MessageManager .getString("label.colourScheme_strand_propensity")); strandColour.addActionListener(this); - turnColour.setLabel(MessageManager - .getString("label.colourScheme_turn_propensity")); + turnColour.setLabel( + MessageManager.getString("label.colourScheme_turn_propensity")); turnColour.addActionListener(this); - buriedColour.setLabel(MessageManager - .getString("label.colourScheme_buried_index")); + buriedColour.setLabel( + MessageManager.getString("label.colourScheme_buried_index")); buriedColour.addActionListener(this); purinePyrimidineColour.setLabel(MessageManager .getString("label.colourScheme_purine/pyrimidine")); @@@ -3533,81 -3520,82 +3531,82 @@@ // RNAInteractionColour.setLabel(MessageManager // .getString("label.rna_interaction")); // RNAInteractionColour.addActionListener(this); - RNAHelixColour.setLabel(MessageManager - .getString("label.colourScheme_rna_helices")); + RNAHelixColour.setLabel( + MessageManager.getString("label.colourScheme_rna_helices")); RNAHelixColour.addActionListener(this); - userDefinedColour.setLabel(MessageManager - .getString("action.user_defined")); + userDefinedColour + .setLabel(MessageManager.getString("action.user_defined")); userDefinedColour.addActionListener(this); - PIDColour.setLabel(MessageManager - .getString("label.colourScheme_%_identity")); + PIDColour.setLabel( + MessageManager.getString("label.colourScheme_%_identity")); PIDColour.addActionListener(this); - BLOSUM62Colour.setLabel(MessageManager - .getString("label.colourScheme_blosum62")); + BLOSUM62Colour.setLabel( + MessageManager.getString("label.colourScheme_blosum62")); BLOSUM62Colour.addActionListener(this); - tcoffeeColour.setLabel(MessageManager - .getString("label.colourScheme_t-coffee_scores")); + tcoffeeColour.setLabel( + MessageManager.getString("label.colourScheme_t-coffee_scores")); // it will be enabled only if a score file is provided tcoffeeColour.setEnabled(false); tcoffeeColour.addActionListener(this); - conservationMenuItem.setLabel(MessageManager - .getString("action.by_conservation")); + conservationMenuItem + .setLabel(MessageManager.getString("action.by_conservation")); conservationMenuItem.addItemListener(this); noColourmenuItem.setLabel(MessageManager.getString("label.none")); noColourmenuItem.addActionListener(this); - abovePIDThreshold.setLabel(MessageManager - .getString("label.above_identity_threshold")); + abovePIDThreshold.setLabel( + MessageManager.getString("label.above_identity_threshold")); abovePIDThreshold.addItemListener(this); - nucleotideColour.setLabel(MessageManager - .getString("label.colourScheme_nucleotide")); + nucleotideColour.setLabel( + MessageManager.getString("label.colourScheme_nucleotide")); nucleotideColour.addActionListener(this); - modifyPID.setLabel(MessageManager - .getString("label.modify_identity_threshold")); + modifyPID.setLabel( + MessageManager.getString("label.modify_identity_threshold")); modifyPID.setEnabled(abovePIDThreshold.getState()); modifyPID.addActionListener(this); modifyConservation.setLabel(MessageManager .getString("label.modify_conservation_threshold")); modifyConservation.setEnabled(conservationMenuItem.getState()); modifyConservation.addActionListener(this); - annotationColour.setLabel(MessageManager - .getString("action.by_annotation")); + annotationColour + .setLabel(MessageManager.getString("action.by_annotation")); annotationColour.addActionListener(this); /* * Configure Calculate menu items and actions */ - sortPairwiseMenuItem.setLabel(MessageManager - .getString("action.by_pairwise_id")); + sortPairwiseMenuItem + .setLabel(MessageManager.getString("action.by_pairwise_id")); sortPairwiseMenuItem.addActionListener(this); sortIDMenuItem.setLabel(MessageManager.getString("action.by_id")); sortIDMenuItem.addActionListener(this); - sortLengthMenuItem.setLabel(MessageManager - .getString("action.by_length")); + sortLengthMenuItem + .setLabel(MessageManager.getString("action.by_length")); sortLengthMenuItem.addActionListener(this); sortGroupMenuItem.setLabel(MessageManager.getString("action.by_group")); sortGroupMenuItem.addActionListener(this); - pairwiseAlignmentMenuItem.setLabel(MessageManager - .getString("action.pairwise_alignment")); + pairwiseAlignmentMenuItem.setLabel( + MessageManager.getString("action.pairwise_alignment")); pairwiseAlignmentMenuItem.addActionListener(this); - PCAMenuItem.setLabel(MessageManager - .getString("label.principal_component_analysis")); + PCAMenuItem.setLabel( + MessageManager.getString("label.principal_component_analysis")); PCAMenuItem.addActionListener(this); autoCalculate = new CheckboxMenuItem( - MessageManager.getString("label.autocalculate_consensus"), true); - averageDistanceTreeMenuItem.setLabel(MessageManager - .getString("label.average_distance_identity")); + MessageManager.getString("label.autocalculate_consensus"), + true); + averageDistanceTreeMenuItem.setLabel( + MessageManager.getString("label.average_distance_identity")); averageDistanceTreeMenuItem.addActionListener(this); - neighbourTreeMenuItem.setLabel(MessageManager - .getString("label.neighbour_joining_identity")); + neighbourTreeMenuItem.setLabel( + MessageManager.getString("label.neighbour_joining_identity")); neighbourTreeMenuItem.addActionListener(this); - avDistanceTreeBlosumMenuItem.setLabel(MessageManager - .getString("label.average_distance_blosum62")); + avDistanceTreeBlosumMenuItem.setLabel( + MessageManager.getString("label.average_distance_blosum62")); avDistanceTreeBlosumMenuItem.addActionListener(this); - njTreeBlosumMenuItem.setLabel(MessageManager - .getString("label.neighbour_blosum62")); + njTreeBlosumMenuItem + .setLabel(MessageManager.getString("label.neighbour_blosum62")); njTreeBlosumMenuItem.addActionListener(this); - sortByTreeMenu.setLabel(MessageManager - .getString("action.by_tree_order")); + sortByTreeMenu + .setLabel(MessageManager.getString("action.by_tree_order")); Menu sortMenu = new Menu(MessageManager.getString("action.sort")); Menu calculateTreeMenu = new Menu( MessageManager.getString("action.calculate_tree")); @@@ -3924,9 -3912,8 +3923,8 @@@ theApplet.add(embeddedMenu, BorderLayout.NORTH); theApplet.add(statusBar, BorderLayout.SOUTH); // TODO should size be left to the layout manager? - alignPanel.setSize(theApplet.getSize().width, - theApplet.getSize().height - embeddedMenu.getHeight() - - statusBar.getHeight()); + alignPanel.setSize(theApplet.getSize().width, theApplet.getSize().height + - embeddedMenu.getHeight() - statusBar.getHeight()); theApplet.add(alignPanel, BorderLayout.CENTER); final AlignFrame me = this; theApplet.addFocusListener(new FocusListener() @@@ -3972,8 -3959,8 +3970,8 @@@ viewer = (Viewer) jmolviewer; } catch (ClassCastException ex) { - System.err.println("Unsupported viewer object :" - + jmolviewer.getClass()); + System.err.println( + "Unsupported viewer object :" + jmolviewer.getClass()); } if (viewer == null) { @@@ -4068,8 -4055,8 +4066,8 @@@ } // resolve data source // TODO: this code should be a refactored to an io package - DataSourceType protocol = AppletFormatAdapter.resolveProtocol( - pdbFile, FileFormat.PDB); + DataSourceType protocol = AppletFormatAdapter.resolveProtocol(pdbFile, + FileFormat.PDB); if (protocol == null) { return false; @@@ -4094,8 -4081,9 +4092,9 @@@ { if (seqs[i] != null) { - sequences.addElement(new Object[] { seqs[i], - (chains != null) ? chains[i] : null }); + sequences + .addElement(new Object[] + { seqs[i], (chains != null) ? chains[i] : null }); } } seqs = new SequenceI[sequences.size()]; @@@ -4121,8 -4109,8 +4120,8 @@@ chains = (String[]) sqch[1]; if (seqs == null || seqs.length == 0) { - System.err - .println("JalviewLite.AlignFrame:newStructureView: No sequence to bind structure to."); + System.err.println( + "JalviewLite.AlignFrame:newStructureView: No sequence to bind structure to."); } if (protocol == null) { @@@ -4169,8 -4157,8 +4168,8 @@@ } if (ajm != null) { - System.err - .println("Incremental adding and aligning structure to existing Jmol view not yet implemented."); + System.err.println( + "Incremental adding and aligning structure to existing Jmol view not yet implemented."); // try and add the pdb structure // ajm.addS ajm = null; @@@ -4179,8 -4167,7 +4178,7 @@@ // otherwise, create a new window if (applet.jmolAvailable) { - new AppletJmol(pdb, seqs, chains, alignPanel, - protocol); + new AppletJmol(pdb, seqs, chains, alignPanel, protocol); applet.lastFrameX += 40; applet.lastFrameY += 40; } @@@ -4263,12 -4250,12 +4261,12 @@@ */ AlignmentI aln; if ((aln = viewport.getAlignment()) != null - && (aln.getHeight() != file.getHeight() || aln.getWidth() != file - .getWidth())) + && (aln.getHeight() != file.getHeight() + || aln.getWidth() != file.getWidth())) { // TODO: raise a dialog box here rather than bomb out. - System.err - .println("The scores matrix does not match the alignment dimensions"); + System.err.println( + "The scores matrix does not match the alignment dimensions"); } diff --combined src/jalview/appletgui/FeatureColourChooser.java index 98ade60,0d479f9..5a073c6 --- a/src/jalview/appletgui/FeatureColourChooser.java +++ b/src/jalview/appletgui/FeatureColourChooser.java @@@ -42,8 -42,6 +42,8 @@@ import java.awt.event.ActionEvent import java.awt.event.ActionListener; import java.awt.event.AdjustmentEvent; import java.awt.event.AdjustmentListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.MouseEvent; @@@ -158,8 -156,8 +158,8 @@@ public class FeatureColourChooser exten } catch (Exception ex) { } - threshold.select(cs.isAboveThreshold() ? 1 : (cs.isBelowThreshold() ? 2 - : 0)); + threshold.select( + cs.isAboveThreshold() ? 1 : (cs.isBelowThreshold() ? 2 : 0)); adjusting = false; changeColour(true); @@@ -167,9 -165,9 +167,9 @@@ slider.addAdjustmentListener(this); slider.addMouseListener(this); owner = (af != null) ? af : fs.frame; - frame = new JVDialog(owner, MessageManager.formatMessage( - "label.graduated_color_for_params", new String[] { type }), - true, 480, 248); + frame = new JVDialog(owner, MessageManager + .formatMessage("label.graduated_color_for_params", new String[] + { type }), true, 480, 248); frame.setMainPanel(this); validate(); frame.setVisible(true); @@@ -198,8 -196,8 +198,8 @@@ private void jbInit() throws Exception { - Label minLabel = new Label(MessageManager.getString("label.min")), maxLabel = new Label( - MessageManager.getString("label.max")); + Label minLabel = new Label(MessageManager.getString("label.min")), + maxLabel = new Label(MessageManager.getString("label.max")); minLabel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11)); maxLabel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11)); // minColour.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11)); @@@ -234,14 -232,6 +234,14 @@@ threshold.addItem(MessageManager .getString("label.threshold_feature_below_threshold")); thresholdValue.addActionListener(this); + thresholdValue.addFocusListener(new FocusAdapter() + { + @Override + public void focusLost(FocusEvent e) + { + thresholdValue_actionPerformed(); + } + }); slider.setBackground(Color.white); slider.setEnabled(false); slider.setSize(new Dimension(93, 21)); @@@ -253,13 -243,13 +253,13 @@@ jPanel3.setBackground(Color.white); colourFromLabel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11)); - colourFromLabel.setLabel(MessageManager - .getString("label.colour_by_label")); + colourFromLabel + .setLabel(MessageManager.getString("label.colour_by_label")); colourFromLabel.setSize(new Dimension(139, 22)); // threshold.setBounds(new Rectangle(11, 3, 139, 22)); thresholdIsMin.setBackground(Color.white); - thresholdIsMin.setLabel(MessageManager - .getString("label.threshold_minmax")); + thresholdIsMin + .setLabel(MessageManager.getString("label.threshold_minmax")); thresholdIsMin.setSize(new Dimension(135, 23)); // thresholdIsMin.setBounds(new Rectangle(328, 3, 135, 23)); jPanel1.add(minLabel); @@@ -282,7 -272,19 +282,7 @@@ { if (evt.getSource() == thresholdValue) { - try - { - float f = new Float(thresholdValue.getText()).floatValue(); - slider.setValue((int) (f * SCALE_FACTOR_1K)); - adjustmentValueChanged(null); - - /* - * force repaint of any Overview window or structure - */ - changeColour(true); - } catch (NumberFormatException ex) - { - } + thresholdValue_actionPerformed(); } else if (evt.getSource() == minColour) { @@@ -298,26 -300,6 +298,26 @@@ } } + /** + * Action on input of a value for colour score threshold + */ + protected void thresholdValue_actionPerformed() + { + try + { + float f = new Float(thresholdValue.getText()).floatValue(); + slider.setValue((int) (f * SCALE_FACTOR_1K)); + adjustmentValueChanged(null); + + /* + * force repaint of any Overview window or structure + */ + changeColour(true); + } catch (NumberFormatException ex) + { + } + } + @Override public void itemStateChanged(ItemEvent evt) { @@@ -356,9 -338,9 +356,9 @@@ { if (newCol == null) { - new UserDefinedColours(this, - minColour.getBackground(), owner, - MessageManager.getString("label.select_colour_minimum_value")); + new UserDefinedColours(this, minColour.getBackground(), owner, + MessageManager + .getString("label.select_colour_minimum_value")); } else { @@@ -374,9 -356,9 +374,9 @@@ { if (newCol == null) { - new UserDefinedColours(this, - maxColour.getBackground(), owner, - MessageManager.getString("label.select_colour_maximum_value")); + new UserDefinedColours(this, maxColour.getBackground(), owner, + MessageManager + .getString("label.select_colour_maximum_value")); } else { @@@ -434,8 -416,10 +434,10 @@@ adjusting = false; } - acg.setAboveThreshold(thresholdOption == AnnotationColourGradient.ABOVE_THRESHOLD); - acg.setBelowThreshold(thresholdOption == AnnotationColourGradient.BELOW_THRESHOLD); + acg.setAboveThreshold( + thresholdOption == AnnotationColourGradient.ABOVE_THRESHOLD); + acg.setBelowThreshold( + thresholdOption == AnnotationColourGradient.BELOW_THRESHOLD); if (thresholdIsMin.getState() && thresholdOption != AnnotationColourGradient.NO_THRESHOLD) diff --combined src/jalview/appletgui/FeatureRenderer.java index 8721ff4,194b18f..b35c079 --- a/src/jalview/appletgui/FeatureRenderer.java +++ b/src/jalview/appletgui/FeatureRenderer.java @@@ -61,8 -61,8 +61,8 @@@ import java.util.List * @author $author$ * @version $Revision$ */ - public class FeatureRenderer extends - jalview.renderer.seqfeatures.FeatureRenderer + public class FeatureRenderer + extends jalview.renderer.seqfeatures.FeatureRenderer { /* * creating a new feature defaults to the type and group as @@@ -269,8 -269,8 +269,8 @@@ FeatureColourI col = getFeatureStyle(name.getText()); if (col == null) { - Color generatedColour = ColorUtils.createColourFromName(name - .getText()); + Color generatedColour = ColorUtils + .createColourFromName(name.getText()); col = new FeatureColour(generatedColour); } @@@ -285,17 -285,20 +285,20 @@@ tmp = new Panel(); panel.add(tmp); - tmp.add(new Label(MessageManager.getString("label.name:"), Label.RIGHT)); + tmp.add(new Label(MessageManager.getString("label.name:"), + Label.RIGHT)); tmp.add(name); tmp = new Panel(); panel.add(tmp); - tmp.add(new Label(MessageManager.getString("label.group:"), Label.RIGHT)); + tmp.add(new Label(MessageManager.getString("label.group:"), + Label.RIGHT)); tmp.add(group); tmp = new Panel(); panel.add(tmp); - tmp.add(new Label(MessageManager.getString("label.colour"), Label.RIGHT)); + tmp.add(new Label(MessageManager.getString("label.colour"), + Label.RIGHT)); tmp.add(colourPanel); bigPanel.add(panel, BorderLayout.NORTH); @@@ -330,15 -333,16 +333,16 @@@ */ SequenceFeature firstFeature = features.get(0); boolean useLastDefaults = firstFeature.getType() == null; - String featureType = useLastDefaults ? lastFeatureAdded : firstFeature - .getType(); + String featureType = useLastDefaults ? lastFeatureAdded + : firstFeature.getType(); String featureGroup = useLastDefaults ? lastFeatureGroupAdded : firstFeature.getFeatureGroup(); - String title = create ? MessageManager - .getString("label.create_new_sequence_features") + String title = create + ? MessageManager.getString("label.create_new_sequence_features") : MessageManager.formatMessage("label.amend_delete_features", - new String[] { sequences.get(0).getName() }); + new String[] + { sequences.get(0).getName() }); final JVDialog dialog = new JVDialog(ap.alignFrame, title, true, 385, 240); @@@ -395,14 -399,11 +399,14 @@@ /* * only update default type and group if we used defaults */ - String enteredType = name.getText().trim(); + final String enteredType = name.getText().trim(); + final String enteredGroup = group.getText().trim(); + final String enteredDesc = description.getText().replace('\n', ' '); + if (dialog.accept && useLastDefaults) { lastFeatureAdded = enteredType; - lastFeatureGroupAdded = group.getText().trim(); + lastFeatureGroupAdded = enteredGroup; } if (!create) @@@ -410,36 -411,29 +414,36 @@@ SequenceFeature sf = features.get(featureIndex); if (dialog.accept) { if (!colourPanel.isGcol) { // update colour - otherwise its already done. - setColour(sf.type, + setColour(enteredType, new FeatureColour(colourPanel.getBackground())); } + int newBegin = sf.begin; + int newEnd = sf.end; try { - sf.begin = Integer.parseInt(start.getText()); - sf.end = Integer.parseInt(end.getText()); + newBegin = Integer.parseInt(start.getText()); + newEnd = Integer.parseInt(end.getText()); } catch (NumberFormatException ex) { - // + // } - boolean typeOrGroupChanged = (!featureType.equals(sf.type) - || !featureGroup.equals(sf.featureGroup)); + + /* + * replace the feature by deleting it and adding a new one + * (to ensure integrity of SequenceFeatures data store) + */ + sequences.get(0).deleteFeature(sf); + SequenceFeature newSf = new SequenceFeature(sf, enteredType, + newBegin, newEnd, enteredGroup, sf.getScore()); + newSf.setDescription(enteredDesc); + ffile.parseDescriptionHTML(newSf, false); + // amend features dialog only updates one sequence at a time + sequences.get(0).addSequenceFeature(newSf); + boolean typeOrGroupChanged = (!featureType.equals(newSf.getType()) || !featureGroup + .equals(newSf.getFeatureGroup())); ffile.parseDescriptionHTML(sf, false); if (typeOrGroupChanged) @@@ -463,11 -457,12 +467,11 @@@ { for (int i = 0; i < sequences.size(); i++) { - features.get(i).type = enteredType; - features.get(i).featureGroup = group.getText().trim(); - features.get(i).description = description.getText().replace('\n', - ' '); - sequences.get(i).addSequenceFeature(features.get(i)); - ffile.parseDescriptionHTML(features.get(i), false); + SequenceFeature sf = features.get(i); + SequenceFeature sf2 = new SequenceFeature(enteredType, + enteredDesc, sf.getBegin(), sf.getEnd(), enteredGroup); + ffile.parseDescriptionHTML(sf2, false); + sequences.get(i).addSequenceFeature(sf2); } Color newColour = colourPanel.getBackground(); diff --combined src/jalview/appletgui/FeatureSettings.java index f6f9727,5e15364..20d4d74 --- a/src/jalview/appletgui/FeatureSettings.java +++ b/src/jalview/appletgui/FeatureSettings.java @@@ -23,7 -23,7 +23,7 @@@ package jalview.appletgui import jalview.api.FeatureColourI; import jalview.api.FeatureSettingsControllerI; import jalview.datamodel.AlignmentI; -import jalview.datamodel.SequenceFeature; +import jalview.datamodel.SequenceI; import jalview.util.MessageManager; import java.awt.BorderLayout; @@@ -56,16 -56,17 +56,16 @@@ import java.awt.event.MouseListener import java.awt.event.MouseMotionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; +import java.util.ArrayList; import java.util.Arrays; -import java.util.Enumeration; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.Vector; - public class FeatureSettings extends Panel implements ItemListener, - MouseListener, MouseMotionListener, ActionListener, - AdjustmentListener, FeatureSettingsControllerI + public class FeatureSettings extends Panel + implements ItemListener, MouseListener, MouseMotionListener, + ActionListener, AdjustmentListener, FeatureSettingsControllerI { FeatureRenderer fr; @@@ -135,11 -136,18 +135,18 @@@ add(lowerPanel, BorderLayout.SOUTH); - groupPanel.setLayout(new GridLayout( - (fr.getFeatureGroupsSize()) / 4 + 1, 4)); // JBPNote - this was - // scaled on number of - // visible groups. seems - // broken + groupPanel.setLayout( + new GridLayout((fr.getFeatureGroupsSize()) / 4 + 1, 4)); // JBPNote + // - this + // was + // scaled + // on + // number + // of + // visible + // groups. + // seems + // broken groupPanel.validate(); add(groupPanel, BorderLayout.NORTH); @@@ -174,14 -182,12 +181,12 @@@ public void paint(Graphics g) { g.setColor(Color.black); - g.drawString(MessageManager - .getString("label.no_features_added_to_this_alignment"), 10, 20); - g.drawString(MessageManager - .getString("label.features_can_be_added_from_searches_1"), 10, - 40); - g.drawString(MessageManager - .getString("label.features_can_be_added_from_searches_2"), 10, - 60); + g.drawString(MessageManager.getString( + "label.no_features_added_to_this_alignment"), 10, 20); + g.drawString(MessageManager.getString( + "label.features_can_be_added_from_searches_1"), 10, 40); + g.drawString(MessageManager.getString( + "label.features_can_be_added_from_searches_2"), 10, 60); } protected void popupSort(final MyCheckbox check, @@@ -189,8 -195,9 +194,9 @@@ { final String type = check.type; final FeatureColourI typeCol = fr.getFeatureStyle(type); - PopupMenu men = new PopupMenu(MessageManager.formatMessage( - "label.settings_for_type", new String[] { type })); + PopupMenu men = new PopupMenu(MessageManager + .formatMessage("label.settings_for_type", new String[] + { type })); java.awt.MenuItem scr = new MenuItem( MessageManager.getString("label.sort_by_score")); men.add(scr); @@@ -201,8 -208,9 +207,9 @@@ @Override public void actionPerformed(ActionEvent e) { - me.ap.alignFrame.avc.sortAlignmentByFeatureScore(Arrays - .asList(new String[] { type })); + me.ap.alignFrame.avc + .sortAlignmentByFeatureScore(Arrays.asList(new String[] + { type })); } }); @@@ -214,8 -222,9 +221,9 @@@ @Override public void actionPerformed(ActionEvent e) { - me.ap.alignFrame.avc.sortAlignmentByFeatureDensity(Arrays - .asList(new String[] { type })); + me.ap.alignFrame.avc + .sortAlignmentByFeatureDensity(Arrays.asList(new String[] + { type })); } }); @@@ -279,8 -288,8 +287,8 @@@ }); men.add(selectContaining); - MenuItem selectNotContaining = new MenuItem( - MessageManager.getString("label.select_columns_not_containing")); + MenuItem selectNotContaining = new MenuItem(MessageManager + .getString("label.select_columns_not_containing")); selectNotContaining.addActionListener(new ActionListener() { @Override @@@ -369,38 -378,36 +377,38 @@@ // Group selection states void resetTable(boolean groupsChanged) { - SequenceFeature[] tmpfeatures; - String group = null, type; - Vector visibleChecks = new Vector(); + List displayableTypes = new ArrayList(); Set foundGroups = new HashSet(); + AlignmentI alignment = av.getAlignment(); for (int i = 0; i < alignment.getHeight(); i++) { - if (alignment.getSequenceAt(i).getSequenceFeatures() == null) - { - continue; - } + SequenceI seq = alignment.getSequenceAt(i); - tmpfeatures = alignment.getSequenceAt(i).getSequenceFeatures(); - int index = 0; - while (index < tmpfeatures.length) + /* + * get the sequence's groups for positional features + * and keep track of which groups are visible + */ + Set groups = seq.getFeatures().getFeatureGroups(true); + Set visibleGroups = new HashSet(); + for (String group : groups) { - group = tmpfeatures[index].featureGroup; - foundGroups.add(group); - + // if (group == null || fr.checkGroupVisibility(group, true)) if (group == null || checkGroupState(group)) { - type = tmpfeatures[index].getType(); - if (!visibleChecks.contains(type)) - { - visibleChecks.addElement(type); - } + visibleGroups.add(group); } - index++; } + foundGroups.addAll(groups); + + /* + * get distinct feature types for visible groups + * record distinct visible types + */ + Set types = seq.getFeatures().getFeatureTypesForGroups(true, + visibleGroups.toArray(new String[visibleGroups.size()])); + displayableTypes.addAll(types); } /* @@@ -417,7 -424,7 +425,7 @@@ { comps = featurePanel.getComponents(); check = (MyCheckbox) comps[i]; - if (!visibleChecks.contains(check.type)) + if (!displayableTypes.contains(check.type)) { featurePanel.remove(i); cSize--; @@@ -434,28 -441,28 +442,28 @@@ { String item = rol.get(ro); - if (!visibleChecks.contains(item)) + if (!displayableTypes.contains(item)) { continue; } - visibleChecks.removeElement(item); + displayableTypes.remove(item); addCheck(false, item); } } - // now add checkboxes which should be visible, - // if they have not already been added - Enumeration en = visibleChecks.elements(); - - while (en.hasMoreElements()) + /* + * now add checkboxes which should be visible, + * if they have not already been added + */ + for (String type : displayableTypes) { - addCheck(groupsChanged, en.nextElement().toString()); + addCheck(groupsChanged, type); } - featurePanel.setLayout(new GridLayout(featurePanel.getComponentCount(), - 1, 10, 5)); + featurePanel.setLayout( + new GridLayout(featurePanel.getComponentCount(), 1, 10, 5)); featurePanel.validate(); if (scrollPane != null) @@@ -634,8 -641,8 +642,8 @@@ } else { - comp = featurePanel.getComponentAt(evt.getX(), evt.getY() - + evt.getComponent().getLocation().y); + comp = featurePanel.getComponentAt(evt.getX(), + evt.getY() + evt.getComponent().getLocation().y); } if (comp != null && comp instanceof Checkbox) diff --combined src/jalview/appletgui/Finder.java index 41e2a64,3e089bd..675b862 --- a/src/jalview/appletgui/Finder.java +++ b/src/jalview/appletgui/Finder.java @@@ -122,7 -122,7 +122,7 @@@ public class Finder extends Panel imple for (SearchResultMatchI match : searchResults.getResults()) { seqs.add(match.getSequence().getDatasetSequence()); - features.add(new SequenceFeature(searchString, "Search Results", null, + features.add(new SequenceFeature(searchString, "Search Results", match.getStart(), match.getEnd(), "Search Results")); } @@@ -186,8 -186,8 +186,8 @@@ // 'SelectRegion' selection if (!haveResults) { - ap.alignFrame.statusBar.setText(MessageManager - .getString("label.finished_searching")); + ap.alignFrame.statusBar.setText( + MessageManager.getString("label.finished_searching")); resIndex = -1; seqIndex = 0; } @@@ -195,8 -195,8 +195,8 @@@ { if (findAll) { - String message = (idMatch.size() > 0) ? "" + idMatch.size() - + " IDs" : ""; + String message = (idMatch.size() > 0) ? "" + idMatch.size() + " IDs" + : ""; if (idMatch.size() > 0 && searchResults != null && searchResults.getSize() > 0) { @@@ -206,16 -206,17 +206,17 @@@ { message += searchResults.getSize() + " subsequence matches."; } - ap.alignFrame.statusBar.setText(MessageManager.formatMessage( - "label.search_results", new String[] { searchString, - message })); + ap.alignFrame.statusBar.setText(MessageManager + .formatMessage("label.search_results", new String[] + { searchString, message })); } else { // TODO: indicate sequence and matching position in status bar - ap.alignFrame.statusBar.setText(MessageManager.formatMessage( - "label.found_match_for", new String[] { searchString })); + ap.alignFrame.statusBar.setText(MessageManager + .formatMessage("label.found_match_for", new String[] + { searchString })); } } } @@@ -275,8 -276,8 +276,8 @@@ caseSensitive.setLabel(MessageManager.getString("label.match_case")); caseSensitive.setBounds(new Rectangle(30, 39, 126, 23)); - searchDescription.setLabel(MessageManager - .getString("label.include_description")); + searchDescription.setLabel( + MessageManager.getString("label.include_description")); searchDescription.setBounds(new Rectangle(30, 59, 170, 23)); actionsPanel.add(findNext, null); actionsPanel.add(findAll, null); diff --combined src/jalview/appletgui/IdPanel.java index a5c2e5a,8ac02be..7d9d278 --- a/src/jalview/appletgui/IdPanel.java +++ b/src/jalview/appletgui/IdPanel.java @@@ -20,6 -20,7 +20,6 @@@ */ package jalview.appletgui; -import jalview.datamodel.Sequence; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; @@@ -38,8 -39,8 +38,8 @@@ import java.util.ArrayList import java.util.HashMap; import java.util.List; - public class IdPanel extends Panel implements MouseListener, - MouseMotionListener + public class IdPanel extends Panel + implements MouseListener, MouseMotionListener { protected IdCanvas idCanvas; @@@ -56,11 -57,11 +56,11 @@@ UrlProviderI urlProvider = null; - public IdPanel(AlignViewport av, AlignmentPanel parent) + public IdPanel(AlignViewport viewport, AlignmentPanel parent) { - this.av = av; + this.av = viewport; alignPanel = parent; - idCanvas = new IdCanvas(av); + idCanvas = new IdCanvas(viewport); setLayout(new BorderLayout()); add(idCanvas, BorderLayout.CENTER); idCanvas.addMouseListener(this); @@@ -71,12 -72,12 +71,12 @@@ // make a list of label,url pairs HashMap urlList = new HashMap(); - if (av.applet != null) + if (viewport.applet != null) { for (int i = 1; i < 10; i++) { - label = av.applet.getParameter("linkLabel_" + i); - url = av.applet.getParameter("linkURL_" + i); + label = viewport.applet.getParameter("linkLabel_" + i); + url = viewport.applet.getParameter("linkURL_" + i); // only add non-null parameters if (label != null) @@@ -88,7 -89,7 +88,7 @@@ if (!urlList.isEmpty()) { // set default as first entry in list - String defaultUrl = av.applet.getParameter("linkLabel_1"); + String defaultUrl = viewport.applet.getParameter("linkLabel_1"); UrlProviderFactoryI factory = new AppletUrlProviderFactory( defaultUrl, urlList); urlProvider = factory.createUrlProvider(); @@@ -105,57 -106,64 +105,57 @@@ SequenceI sequence = av.getAlignment().getSequenceAt(seq); - // look for non-pos features StringBuffer tooltiptext = new StringBuffer(); - if (sequence != null) + if (sequence == null) { - if (sequence.getDescription() != null) + return; + } + if (sequence.getDescription() != null) + { + tooltiptext.append(sequence.getDescription()); + tooltiptext.append("\n"); + } + + for (SequenceFeature sf : sequence.getFeatures() + .getNonPositionalFeatures()) + { + boolean nl = false; + if (sf.getFeatureGroup() != null) { - tooltiptext.append(sequence.getDescription()); - tooltiptext.append("\n"); + tooltiptext.append(sf.getFeatureGroup()); + nl = true; } - - SequenceFeature sf[] = sequence.getSequenceFeatures(); - for (int sl = 0; sf != null && sl < sf.length; sl++) + if (sf.getType() != null) { - if (sf[sl].begin == sf[sl].end && sf[sl].begin == 0) - { - boolean nl = false; - if (sf[sl].getFeatureGroup() != null) - { - tooltiptext.append(sf[sl].getFeatureGroup()); - nl = true; - } - ; - if (sf[sl].getType() != null) - { - tooltiptext.append(" "); - tooltiptext.append(sf[sl].getType()); - nl = true; - } - ; - if (sf[sl].getDescription() != null) - { - tooltiptext.append(" "); - tooltiptext.append(sf[sl].getDescription()); - nl = true; - } - ; - if (!Float.isNaN(sf[sl].getScore()) && sf[sl].getScore() != 0f) - { - tooltiptext.append(" Score = "); - tooltiptext.append(sf[sl].getScore()); - nl = true; - } - ; - if (sf[sl].getStatus() != null && sf[sl].getStatus().length() > 0) - { - tooltiptext.append(" ("); - tooltiptext.append(sf[sl].getStatus()); - tooltiptext.append(")"); - nl = true; - } - ; - if (nl) - { - tooltiptext.append("\n"); - } - } + tooltiptext.append(" "); + tooltiptext.append(sf.getType()); + nl = true; + } + if (sf.getDescription() != null) + { + tooltiptext.append(" "); + tooltiptext.append(sf.getDescription()); + nl = true; + } + if (!Float.isNaN(sf.getScore()) && sf.getScore() != 0f) + { + tooltiptext.append(" Score = "); + tooltiptext.append(sf.getScore()); + nl = true; + } + if (sf.getStatus() != null && sf.getStatus().length() > 0) + { + tooltiptext.append(" ("); + tooltiptext.append(sf.getStatus()); + tooltiptext.append(")"); + nl = true; + } + if (nl) + { + tooltiptext.append("\n"); } } + if (tooltiptext.length() == 0) { // nothing to display - so clear tooltip if one is visible @@@ -169,13 -177,14 +169,14 @@@ } if (tooltip == null) { - tooltip = new Tooltip(sequence.getDisplayId(true) + "\n" - + tooltiptext.toString(), idCanvas); + tooltip = new Tooltip( + sequence.getDisplayId(true) + "\n" + tooltiptext.toString(), + idCanvas); } else { - tooltip.setTip(sequence.getDisplayId(true) + "\n" - + tooltiptext.toString()); + tooltip.setTip( + sequence.getDisplayId(true) + "\n" + tooltiptext.toString()); } tooltiptext = null; } @@@ -278,14 -287,13 +279,15 @@@ int seq = alignPanel.seqPanel.findSeq(e); - if ((e.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK) + if ((e.getModifiers() + & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK) { - Sequence sq = (Sequence) av.getAlignment().getSequenceAt(seq); + SequenceI sq = av.getAlignment().getSequenceAt(seq); - // build a new links menu based on the current links + any non-positional - // features + /* + * build a new links menu based on the current links + * and any non-positional features + */ List nlinks; if (urlProvider != null) { @@@ -295,14 -303,17 +297,14 @@@ { nlinks = new ArrayList(); } - SequenceFeature sf[] = sq == null ? null : sq.getSequenceFeatures(); - for (int sl = 0; sf != null && sl < sf.length; sl++) + + for (SequenceFeature sf : sq.getFeatures().getNonPositionalFeatures()) { - if (sf[sl].begin == sf[sl].end && sf[sl].begin == 0) + if (sf.links != null) { - if (sf[sl].links != null && sf[sl].links.size() > 0) + for (String link : sf.links) { - for (int l = 0, lSize = sf[sl].links.size(); l < lSize; l++) - { - nlinks.add(sf[sl].links.elementAt(l)); - } + nlinks.add(link); } } } @@@ -314,8 -325,8 +316,8 @@@ } if ((av.getSelectionGroup() == null) - || ((!jalview.util.Platform.isControlDown(e) && !e - .isShiftDown()) && av.getSelectionGroup() != null)) + || ((!jalview.util.Platform.isControlDown(e) + && !e.isShiftDown()) && av.getSelectionGroup() != null)) { av.setSelectionGroup(new SequenceGroup()); av.getSelectionGroup().setStartRes(0); @@@ -364,8 -375,8 +366,8 @@@ } for (int i = start; i <= end; i++) { - av.getSelectionGroup().addSequence( - av.getAlignment().getSequenceAt(i), i == end); + av.getSelectionGroup().addSequence(av.getAlignment().getSequenceAt(i), + i == end); } } @@@ -415,9 -426,9 +417,9 @@@ boolean up = true; - public ScrollThread(boolean up) + public ScrollThread(boolean isUp) { - this.up = up; + this.up = isUp; start(); } diff --combined src/jalview/appletgui/SeqCanvas.java index fe7abbb,28c5291..f59967d --- a/src/jalview/appletgui/SeqCanvas.java +++ b/src/jalview/appletgui/SeqCanvas.java @@@ -113,12 -113,12 +113,12 @@@ public class SeqCanvas extends Panel im { if (mstring != null) { - g.drawString(mstring, mpos * avcharWidth, ypos - - (avcharHeight / 2)); + g.drawString(mstring, mpos * avcharWidth, + ypos - (avcharHeight / 2)); } - g.drawLine((mpos * avcharWidth) + (avcharWidth / 2), (ypos + 2) - - (avcharHeight / 2), (mpos * avcharWidth) - + (avcharWidth / 2), ypos - 2); + g.drawLine((mpos * avcharWidth) + (avcharWidth / 2), + (ypos + 2) - (avcharHeight / 2), + (mpos * avcharWidth) + (avcharWidth / 2), ypos - 2); } } } @@@ -167,8 -167,8 +167,8 @@@ { int x = LABEL_WEST - fm.stringWidth(String.valueOf(value)) - avcharWidth / 2; - g.drawString(value + "", x, (ypos + (i * avcharHeight)) - - (avcharHeight / 5)); + g.drawString(value + "", x, + (ypos + (i * avcharHeight)) - (avcharHeight / 5)); } } } @@@ -207,8 -207,8 +207,8 @@@ if (value != -1) { - g.drawString(String.valueOf(value), 0, (ypos + (i * avcharHeight)) - - (avcharHeight / 5)); + g.drawString(String.valueOf(value), 0, + (ypos + (i * avcharHeight)) - (avcharHeight / 5)); } } } @@@ -237,14 -237,14 +237,14 @@@ lastsr = ranges.getStartRes(); fastPaint = true; - gg.copyArea(horizontal * avcharWidth, vertical * avcharHeight, imgWidth - - horizontal * avcharWidth, + gg.copyArea(horizontal * avcharWidth, vertical * avcharHeight, + imgWidth - horizontal * avcharWidth, imgHeight - vertical * avcharHeight, -horizontal * avcharWidth, -vertical * avcharHeight); - int sr = ranges.getStartRes(), er = ranges.getEndRes(), ss = ranges - .getStartSeq(), es = ranges - .getEndSeq(), transX = 0, transY = 0; + int sr = ranges.getStartRes(), er = ranges.getEndRes(), + ss = ranges.getStartSeq(), es = ranges.getEndSeq(), transX = 0, + transY = 0; if (horizontal > 0) // scrollbar pulled right, image to the left { @@@ -261,7 -261,7 +261,7 @@@ ss = es - vertical; if (ss < ranges.getStartSeq()) // ie scrolling too fast, more than a page // at a - // time + // time { ss = ranges.getStartSeq(); } @@@ -307,8 -307,8 +307,8 @@@ { if (img != null - && (fastPaint || (getSize().width != g.getClipBounds().width) || (getSize().height != g - .getClipBounds().height))) + && (fastPaint || (getSize().width != g.getClipBounds().width) + || (getSize().height != g.getClipBounds().height))) { g.drawImage(img, 0, 0, this); fastPaint = false; @@@ -501,11 -501,15 +501,15 @@@ continue; } - gg.fillPolygon(new int[] { res * avcharWidth - avcharHeight / 4, - res * avcharWidth + avcharHeight / 4, res * avcharWidth }, - new int[] { ypos - (avcharHeight / 2), - ypos - (avcharHeight / 2), - ypos - (avcharHeight / 2) + 8 }, 3); + gg.fillPolygon( + new int[] + { res * avcharWidth - avcharHeight / 4, + res * avcharWidth + avcharHeight / 4, + res * avcharWidth }, + new int[] + { ypos - (avcharHeight / 2), ypos - (avcharHeight / 2), + ypos - (avcharHeight / 2) + 8 }, + 3); } } @@@ -555,8 -559,8 +559,8 @@@ return annotations.adjustPanelHeight(); } - private void drawPanel(Graphics g1, int startRes, int endRes, - int startSeq, int endSeq, int offset) + private void drawPanel(Graphics g1, final int startRes, final int endRes, + final int startSeq, final int endSeq, final int offset) { if (!av.hasHiddenColumns()) @@@ -565,8 -569,8 +569,8 @@@ } else { - int screenY = 0; + final int screenYMax = endRes - startRes; int blockStart = startRes; int blockEnd = endRes; @@@ -584,42 -588,33 +588,42 @@@ continue; } - blockEnd = hideStart - 1; + /* + * draw up to just before the next hidden region, or the end of + * the visible region, whichever comes first + */ + blockEnd = Math.min(hideStart - 1, blockStart + screenYMax + - screenY); g1.translate(screenY * avcharWidth, 0); draw(g1, blockStart, blockEnd, startSeq, endSeq, offset); - if (av.getShowHiddenMarkers()) + /* + * draw the downline of the hidden column marker (ScalePanel draws the + * triangle on top) if we reached it + */ + if (av.getShowHiddenMarkers() && blockEnd == hideStart - 1) { g1.setColor(Color.blue); g1.drawLine((blockEnd - blockStart + 1) * avcharWidth - 1, - 0 + offset, (blockEnd - blockStart + 1) * avcharWidth - - 1, (endSeq - startSeq + 1) * avcharHeight - + offset); + 0 + offset, + (blockEnd - blockStart + 1) * avcharWidth - 1, + (endSeq - startSeq + 1) * avcharHeight + offset); } g1.translate(-screenY * avcharWidth, 0); screenY += blockEnd - blockStart + 1; blockStart = hideEnd + 1; - if (screenY > (endRes - startRes)) + if (screenY > screenYMax) { // already rendered last block return; } } } - if (screenY <= (endRes - startRes)) + if (screenY <= screenYMax) { // remaining visible region to render blockEnd = blockStart + (endRes - startRes) - screenY; @@@ -658,8 -653,8 +662,8 @@@ if (av.isShowSequenceFeatures()) { - fr.drawSequence(g, nextSeq, startRes, endRes, offset - + ((i - startSeq) * avcharHeight), false); + fr.drawSequence(g, nextSeq, startRes, endRes, + offset + ((i - startSeq) * avcharHeight), false); } // / Highlight search Results once all sequences have been drawn @@@ -667,16 -662,15 +671,15 @@@ if (av.hasSearchResults()) { int[] visibleResults = av.getSearchResults().getResults(nextSeq, - startRes, - endRes); + startRes, endRes); if (visibleResults != null) { for (int r = 0; r < visibleResults.length; r += 2) { sr.drawHighlightedText(nextSeq, visibleResults[r], - visibleResults[r + 1], (visibleResults[r] - startRes) - * avcharWidth, offset - + ((i - startSeq) * avcharHeight)); + visibleResults[r + 1], + (visibleResults[r] - startRes) * avcharWidth, + offset + ((i - startSeq) * avcharHeight)); } } } @@@ -732,7 -726,8 +735,8 @@@ { sx = (group.getStartRes() - startRes) * avcharWidth; sy = offset + ((i - startSeq) * avcharHeight); - ex = (((group.getEndRes() + 1) - group.getStartRes()) * avcharWidth) - 1; + ex = (((group.getEndRes() + 1) - group.getStartRes()) + * avcharWidth) - 1; if (sx + ex < 0 || sx > imgWidth) { @@@ -740,22 -735,20 +744,20 @@@ } if ((sx <= (endRes - startRes) * avcharWidth) - && group.getSequences(null).contains( - av.getAlignment().getSequenceAt(i))) + && group.getSequences(null) + .contains(av.getAlignment().getSequenceAt(i))) { if ((bottom == -1) - && (i >= alHeight || !group.getSequences(null) - .contains( - av.getAlignment().getSequenceAt(i + 1)))) + && (i >= alHeight || !group.getSequences(null).contains( + av.getAlignment().getSequenceAt(i + 1)))) { bottom = sy + avcharHeight; } if (!inGroup) { - if (((top == -1) && (i == 0)) - || !group.getSequences(null).contains( - av.getAlignment().getSequenceAt(i - 1))) + if (((top == -1) && (i == 0)) || !group.getSequences(null) + .contains(av.getAlignment().getSequenceAt(i - 1))) { top = sy; } diff --combined src/jalview/appletgui/SeqPanel.java index 21eb6a4,be4f9e6..fc7c46e --- a/src/jalview/appletgui/SeqPanel.java +++ b/src/jalview/appletgui/SeqPanel.java @@@ -54,8 -54,10 +54,8 @@@ import java.awt.event.InputEvent import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; -import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.ListIterator; import java.util.Vector; public class SeqPanel extends Panel implements MouseMotionListener, @@@ -132,8 -134,8 +132,8 @@@ if (editCommand != null && editCommand.getSize() > 0) { ap.alignFrame.addHistoryItem(editCommand); - av.firePropertyChange("alignment", null, av.getAlignment() - .getSequences()); + av.firePropertyChange("alignment", null, + av.getAlignment().getSequences()); } startseq = -1; @@@ -183,23 -185,21 +183,21 @@@ { seqCanvas.cursorX += dx; seqCanvas.cursorY += dy; - if (av.hasHiddenColumns() - && !av.getAlignment().getHiddenColumns() - .isVisible(seqCanvas.cursorX)) + if (av.hasHiddenColumns() && !av.getAlignment().getHiddenColumns() + .isVisible(seqCanvas.cursorX)) { int original = seqCanvas.cursorX - dx; int maxWidth = av.getAlignment().getWidth(); while (!av.getAlignment().getHiddenColumns() - .isVisible(seqCanvas.cursorX) - && seqCanvas.cursorX < maxWidth && seqCanvas.cursorX > 0) + .isVisible(seqCanvas.cursorX) && seqCanvas.cursorX < maxWidth + && seqCanvas.cursorX > 0) { seqCanvas.cursorX += dx; } - if (seqCanvas.cursorX >= maxWidth - || !av.getAlignment().getHiddenColumns() - .isVisible(seqCanvas.cursorX)) + if (seqCanvas.cursorX >= maxWidth || !av.getAlignment() + .getHiddenColumns().isVisible(seqCanvas.cursorX)) { seqCanvas.cursorX = original; } @@@ -244,8 -244,8 +242,8 @@@ { ranges.scrollUp(false); } - while (seqCanvas.cursorX < hidden.adjustForHiddenColumns(ranges - .getStartRes())) + while (seqCanvas.cursorX < hidden + .adjustForHiddenColumns(ranges.getStartRes())) { if (!ranges.scrollRight(false)) @@@ -253,8 -253,8 +251,8 @@@ break; } } - while (seqCanvas.cursorX > hidden.adjustForHiddenColumns(ranges - .getEndRes())) + while (seqCanvas.cursorX > hidden + .adjustForHiddenColumns(ranges.getEndRes())) { if (!ranges.scrollRight(true)) { @@@ -443,9 -443,9 +441,9 @@@ } else { - residue = "X".equalsIgnoreCase(displayChar) ? "X" : ("*" - .equals(displayChar) ? "STOP" : ResidueProperties.aa2Triplet - .get(displayChar)); + residue = "X".equalsIgnoreCase(displayChar) ? "X" + : ("*".equals(displayChar) ? "STOP" + : ResidueProperties.aa2Triplet.get(displayChar)); if (residue != null) { text.append(" Residue: ").append(residue); @@@ -507,7 -507,8 +505,8 @@@ // For now, ignore the mouseWheel font resizing on Macs // As the Button2_mask always seems to be true - if ((evt.getModifiers() & InputEvent.BUTTON2_MASK) == InputEvent.BUTTON2_MASK + if ((evt.getModifiers() + & InputEvent.BUTTON2_MASK) == InputEvent.BUTTON2_MASK && !av.MAC) { mouseWheelPressed = true; @@@ -529,7 -530,7 +528,7 @@@ } int seq = findSeq(evt); - int res = findRes(evt); + int res = findColumn(evt); if (seq < 0 || res < 0) { @@@ -565,20 -566,25 +564,20 @@@ av.setSelectionGroup(null); } - int column = findRes(evt); - boolean isGapped = Comparison.isGap(sequence.getCharAt(column)); - List features = findFeaturesAtRes(sequence, - sequence.findPosition(column)); - if (isGapped) - { - removeAdjacentFeatures(features, column + 1, sequence); - } + int column = findColumn(evt); + List features = findFeaturesAtColumn(sequence, + column + 1); if (!features.isEmpty()) { SearchResultsI highlight = new SearchResults(); - highlight.addResult(sequence, features.get(0).getBegin(), features - .get(0).getEnd()); + highlight.addResult(sequence, features.get(0).getBegin(), + features.get(0).getEnd()); seqCanvas.highlightSearchResults(highlight); seqCanvas.getFeatureRenderer().amendFeatures( Collections.singletonList(sequence), features, false, ap); - - seqCanvas.highlightSearchResults(null); + av.setSearchResults(null); // clear highlighting + seqCanvas.repaint(); // draw new/amended features } } } @@@ -604,14 -610,7 +603,14 @@@ int wrappedBlock = -1; - int findRes(MouseEvent evt) + /** + * Returns the aligned sequence position (base 0) at the mouse position, or + * the closest visible one + * + * @param evt + * @return + */ + int findColumn(MouseEvent evt) { int res = 0; int x = evt.getX(); @@@ -690,8 -689,8 +689,8 @@@ y -= hgap; - seq = Math.min((y % cHeight) / av.getCharHeight(), av.getAlignment() - .getHeight() - 1); + seq = Math.min((y % cHeight) / av.getCharHeight(), + av.getAlignment().getHeight() - 1); if (seq < 0) { seq = -1; @@@ -699,10 -698,9 +698,9 @@@ } else { - seq = Math.min((y / av.getCharHeight()) - + av.getRanges().getStartSeq(), - av - .getAlignment().getHeight() - 1); + seq = Math.min( + (y / av.getCharHeight()) + av.getRanges().getStartSeq(), + av.getAlignment().getHeight() - 1); if (seq < 0) { seq = -1; @@@ -716,7 -714,7 +714,7 @@@ { int seq = findSeq(evt); - int res = findRes(evt); + int res = findColumn(evt); if (seq < av.getAlignment().getHeight() && res < av.getAlignment().getSequenceAt(seq).getLength()) @@@ -788,7 -786,7 +786,7 @@@ @Override public void mouseMoved(MouseEvent evt) { - final int column = findRes(evt); + final int column = findColumn(evt); int seq = findSeq(evt); if (seq >= av.getAlignment().getHeight() || seq < 0 || column < 0) @@@ -834,8 -832,7 +832,7 @@@ else { String residue = (ch == 'x' || ch == 'X') ? "X" - : ResidueProperties.aa2Triplet - .get(String.valueOf(ch)); + : ResidueProperties.aa2Triplet.get(String.valueOf(ch)); text.append(" Residue: ").append(residue == null ? ch : residue); } text.append(" (").append(Integer.toString(respos)).append(")"); @@@ -849,7 -846,8 +846,8 @@@ { for (int g = 0; g < groups.length; g++) { - if (groups[g].getStartRes() <= column && groups[g].getEndRes() >= column) + if (groups[g].getStartRes() <= column + && groups[g].getEndRes() >= column) { if (!groups[g].getName().startsWith("JTreeGroup") && !groups[g].getName().startsWith("JGroup")) @@@ -871,8 -869,12 +869,8 @@@ */ if (av.isShowSequenceFeatures()) { - List allFeatures = findFeaturesAtRes(sequence, - sequence.findPosition(column)); - if (isGapped) - { - removeAdjacentFeatures(allFeatures, column + 1, sequence); - } + List allFeatures = findFeaturesAtColumn(sequence, + column + 1); for (SequenceFeature sf : allFeatures) { tooltipText.append(sf.getType() + " " + sf.begin + ":" + sf.end); @@@ -905,18 -907,63 +903,18 @@@ } /** - * Removes from the list of features any that start after, or end before, the - * given column position. This allows us to retain only those features - * adjacent to a gapped position that straddle the position. Contact features - * that 'straddle' the position are also removed, since they are not 'at' the - * position. + * Returns features at the specified aligned column on the given sequence. + * Non-positional features are not included. If the column has a gap, then + * enclosing features are included (but not contact features). * - * @param features - * @param column - * alignment column (1..) * @param sequence + * @param column + * (1..) + * @return */ - protected void removeAdjacentFeatures(List features, - int column, SequenceI sequence) - { - // TODO should this be an AlignViewController method (shared by gui)? - ListIterator it = features.listIterator(); - while (it.hasNext()) - { - SequenceFeature sf = it.next(); - if (sf.isContactFeature() - || sequence.findIndex(sf.getBegin()) > column - || sequence.findIndex(sf.getEnd()) < column) - { - it.remove(); - } - } - } - - List findFeaturesAtRes(SequenceI sequence, int res) + List findFeaturesAtColumn(SequenceI sequence, int column) { - List result = new ArrayList<>(); - SequenceFeature[] features = sequence.getSequenceFeatures(); - if (features != null) - { - for (int i = 0; i < features.length; i++) - { - if (av.getFeaturesDisplayed() == null || !av.getFeaturesDisplayed() - .isVisible(features[i].getType())) - { - continue; - } - - if (features[i].featureGroup != null && !seqCanvas.fr - .checkGroupVisibility(features[i].featureGroup, false)) - { - continue; - } - - if ((features[i].getBegin() <= res) - && (features[i].getEnd() >= res)) - { - result.add(features[i]); - } - } - } - - return result; + return seqCanvas.getFeatureRenderer().findFeaturesAtColumn(sequence, column); } Tooltip tooltip; @@@ -937,8 -984,8 +935,8 @@@ int oldWidth = av.getCharWidth(); // Which is bigger, left-right or up-down? - if (Math.abs(evt.getY() - lastMousePress.y) > Math.abs(evt.getX() - - lastMousePress.x)) + if (Math.abs(evt.getY() - lastMousePress.y) > Math + .abs(evt.getX() - lastMousePress.x)) { int fontSize = av.font.getSize(); @@@ -996,7 -1043,7 +994,7 @@@ return; } - int res = findRes(evt); + int res = findColumn(evt); if (res < 0) { @@@ -1047,8 -1094,8 +1045,8 @@@ StringBuffer message = new StringBuffer(); if (groupEditing) { - message.append(MessageManager.getString("action.edit_group")).append( - ":"); + message.append(MessageManager.getString("action.edit_group")) + .append(":"); if (editCommand == null) { editCommand = new EditCommand( @@@ -1066,8 -1113,9 +1064,9 @@@ } if (editCommand == null) { - editCommand = new EditCommand(MessageManager.formatMessage( - "label.edit_params", new String[] { label })); + editCommand = new EditCommand(MessageManager + .formatMessage("label.edit_params", new String[] + { label })); } } @@@ -1084,9 -1132,8 +1083,8 @@@ ap.alignFrame.statusBar.setText(message.toString()); // Are we editing within a selection group? - if (groupEditing - || (sg != null && sg.getSequences(av.getHiddenRepSequences()) - .contains(seq))) + if (groupEditing || (sg != null + && sg.getSequences(av.getHiddenRepSequences()).contains(seq))) { fixedColumns = true; @@@ -1178,7 -1225,7 +1176,7 @@@ // Find the next gap before the end // of the visible region boundary boolean blank = false; - for (fixedRight = fixedRight; fixedRight > lastres; fixedRight--) + for (; fixedRight > lastres; fixedRight--) { blank = true; @@@ -1186,8 -1233,8 +1184,8 @@@ { for (int j = 0; j < startres - lastres; j++) { - if (!jalview.util.Comparison.isGap(gs.getCharAt(fixedRight - - j))) + if (!jalview.util.Comparison + .isGap(gs.getCharAt(fixedRight - j))) { blank = false; break; @@@ -1308,9 -1355,8 +1306,8 @@@ } else { - editCommand.appendEdit(Action.INSERT_GAP, - new SequenceI[] { seq }, lastres, startres - lastres, - av.getAlignment(), true); + editCommand.appendEdit(Action.INSERT_GAP, new SequenceI[] { seq }, + lastres, startres - lastres, av.getAlignment(), true); } } else @@@ -1344,8 -1390,8 +1341,8 @@@ if (max > 0) { editCommand.appendEdit(Action.DELETE_GAP, - new SequenceI[] { seq }, startres, max, - av.getAlignment(), true); + new SequenceI[] + { seq }, startres, max, av.getAlignment(), true); } } } @@@ -1409,7 -1455,7 +1406,7 @@@ scrollThread = null; } - int res = findRes(evt); + int column = findColumn(evt); int seq = findSeq(evt); oldSeq = seq; startWrapBlock = wrappedBlock; @@@ -1421,16 -1467,16 +1418,16 @@@ SequenceI sequence = av.getAlignment().getSequenceAt(seq); - if (sequence == null || res > sequence.getLength()) + if (sequence == null || column > sequence.getLength()) { return; } stretchGroup = av.getSelectionGroup(); - if (stretchGroup == null || !stretchGroup.contains(sequence, res)) + if (stretchGroup == null || !stretchGroup.contains(sequence, column)) { - stretchGroup = av.getAlignment().findGroup(sequence, res); + stretchGroup = av.getAlignment().findGroup(sequence, column); if (stretchGroup != null) { // only update the current selection if the popup menu has a group to @@@ -1440,10 -1486,11 +1437,11 @@@ } // DETECT RIGHT MOUSE BUTTON IN AWT - if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK) + if ((evt.getModifiers() + & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK) { - List allFeatures = findFeaturesAtRes(sequence, - sequence.findPosition(res)); + List allFeatures = findFeaturesAtColumn(sequence, + sequence.findPosition(column + 1)); Vector links = null; for (SequenceFeature sf : allFeatures) @@@ -1452,9 -1499,12 +1450,9 @@@ { if (links == null) { - links = new Vector<>(); - } - for (int j = 0; j < sf.links.size(); j++) - { - links.addElement(sf.links.elementAt(j)); + links = new Vector(); } + links.addAll(sf.links); } } APopupMenu popup = new APopupMenu(ap, null, links); @@@ -1465,7 -1515,7 +1463,7 @@@ if (av.cursorMode) { - seqCanvas.cursorX = findRes(evt); + seqCanvas.cursorX = findColumn(evt); seqCanvas.cursorY = findSeq(evt); seqCanvas.repaint(); return; @@@ -1477,8 -1527,8 +1475,8 @@@ { // define a new group here SequenceGroup sg = new SequenceGroup(); - sg.setStartRes(res); - sg.setEndRes(res); + sg.setStartRes(column); + sg.setEndRes(column); sg.addSequence(sequence, false); av.setSelectionGroup(sg); stretchGroup = sg; @@@ -1536,7 -1586,7 +1534,7 @@@ public void doMouseDraggedDefineMode(MouseEvent evt) { - int res = findRes(evt); + int res = findColumn(evt); int y = findSeq(evt); if (wrappedBlock != startWrapBlock) @@@ -1750,9 -1800,8 +1748,8 @@@ running = av.getRanges().scrollUp(true); } - if (mouseDragging && evt.getY() >= getSize().height - && av.getAlignment().getHeight() > av.getRanges() - .getEndSeq()) + if (mouseDragging && evt.getY() >= getSize().height && av + .getAlignment().getHeight() > av.getRanges().getEndSeq()) { running = av.getRanges().scrollUp(false); } @@@ -1789,9 -1838,10 +1786,10 @@@ // handles selection messages... // TODO: extend config options to allow user to control if selections may be // shared between viewports. - if (av != null - && (av == source || !av.followSelection || (source instanceof AlignViewport && ((AlignmentViewport) source) - .getSequenceSetId().equals(av.getSequenceSetId())))) + if (av != null && (av == source || !av.followSelection + || (source instanceof AlignViewport + && ((AlignmentViewport) source).getSequenceSetId() + .equals(av.getSequenceSetId())))) { return; } @@@ -1820,11 -1870,9 +1818,9 @@@ { if (av.getAlignment() == null) { - System.out - .println("Selection message: alignviewport av SeqSetId=" - + av.getSequenceSetId() + " ViewId=" - + av.getViewId() - + " 's alignment is NULL! returning immediatly."); + System.out.println("Selection message: alignviewport av SeqSetId=" + + av.getSequenceSetId() + " ViewId=" + av.getViewId() + + " 's alignment is NULL! returning immediatly."); return; } sgroup = seqsel.intersect(av.getAlignment(), @@@ -1844,9 -1892,8 +1840,8 @@@ } repaint = av.isSelectionGroupChanged(true); } - if (copycolsel - && (av.getColumnSelection() == null || !av - .isColSelChanged(true))) + if (copycolsel && (av.getColumnSelection() == null + || !av.isColSelChanged(true))) { // the current selection is unset or from a previous message // so import the new colsel. @@@ -1872,8 -1919,7 +1867,7 @@@ } repaint |= av.isColSelChanged(true); } - if (copycolsel - && av.hasHiddenColumns() + if (copycolsel && av.hasHiddenColumns() && (av.getColumnSelection() == null)) { System.err.println("Bad things"); @@@ -1908,8 -1954,8 +1902,8 @@@ { row = row < 0 ? ap.av.getRanges().getStartSeq() : row; - ap.scrollTo(ap.av.getRanges().getStartRes(), ap.av.getRanges() - .getStartRes(), row, true, true); + ap.scrollTo(ap.av.getRanges().getStartRes(), + ap.av.getRanges().getStartRes(), row, true, true); } /** @@@ -1921,7 -1967,8 +1915,8 @@@ { column = column < 0 ? ap.av.getRanges().getStartRes() : column; - ap.scrollTo(column, column, ap.av.getRanges().getStartSeq(), true, true); + ap.scrollTo(column, column, ap.av.getRanges().getStartSeq(), true, + true); } /** diff --combined src/jalview/commands/EditCommand.java index 9eaeb7a,d319249..cac843f --- a/src/jalview/commands/EditCommand.java +++ b/src/jalview/commands/EditCommand.java @@@ -122,15 -122,15 +122,15 @@@ public class EditCommand implements Com { } - public EditCommand(String description) + public EditCommand(String desc) { - this.description = description; + this.description = desc; } - public EditCommand(String description, Action command, SequenceI[] seqs, + public EditCommand(String desc, Action command, SequenceI[] seqs, int position, int number, AlignmentI al) { - this.description = description; + this.description = desc; if (command == Action.CUT || command == Action.PASTE) { setEdit(new Edit(command, seqs, position, number, al)); @@@ -139,10 -139,10 +139,10 @@@ performEdit(0, null); } - public EditCommand(String description, Action command, String replace, + public EditCommand(String desc, Action command, String replace, SequenceI[] seqs, int position, int number, AlignmentI al) { - this.description = description; + this.description = desc; if (command == Action.REPLACE) { setEdit(new Edit(command, seqs, position, number, al, replace)); @@@ -222,14 -222,16 +222,16 @@@ /** * Check a contiguous edit; either *
      - *
    • a new Insert positions to the right of the last , or
    • + *
    • a new Insert positions to the right of the last , + * or
    • *
    • a new Delete gaps which is positions to the left of the last * delete.
    • *
    */ - boolean contiguous = (action == Action.INSERT_GAP && e.position == lastEdit.position - + lastEdit.number) - || (action == Action.DELETE_GAP && e.position + e.number == lastEdit.position); + boolean contiguous = (action == Action.INSERT_GAP + && e.position == lastEdit.position + lastEdit.number) + || (action == Action.DELETE_GAP + && e.position + e.number == lastEdit.position); if (contiguous) { /* @@@ -475,7 -477,8 +477,8 @@@ { command.seqs[s].insertCharAt(command.position, command.number, command.gapChar); - // System.out.println("pos: "+command.position+" number: "+command.number); + // System.out.println("pos: "+command.position+" number: + // "+command.number); } adjustAnnotations(command, true, false, null); @@@ -504,8 -507,8 +507,8 @@@ { for (int s = 0; s < command.seqs.length; s++) { - command.seqs[s].deleteChars(command.position, command.position - + command.number); + command.seqs[s].deleteChars(command.position, + command.position + command.number); } adjustAnnotations(command, false, false, null); @@@ -536,8 -539,8 +539,8 @@@ // we are redoing an undone cut. sequence.setDatasetSequence(null); } - sequence.deleteChars(command.position, command.position - + command.number); + sequence.deleteChars(command.position, + command.position + command.number); if (command.oldds != null && command.oldds[i] != null) { // oldds entry contains the cut dataset sequence. @@@ -548,19 -551,17 +551,19 @@@ { // modify the oldds if necessary if (oldds != sequence.getDatasetSequence() - || sequence.getSequenceFeatures() != null) + || sequence.getFeatures().hasFeatures()) { if (command.oldds == null) { command.oldds = new SequenceI[command.seqs.length]; } command.oldds[i] = oldds; - adjustFeatures(command, i, + // FIXME JAL-2541 JAL-2526 get correct positions if on a gap + adjustFeatures( + command, + i, sequence.findPosition(command.position), - sequence.findPosition( - command.position + command.number), + sequence.findPosition(command.position + command.number), false); } } @@@ -647,8 -648,8 +650,8 @@@ { newDSNeeded = true; start = command.seqs[i].findPosition(command.position); - end = command.seqs[i].findPosition(command.position - + command.number); + end = command.seqs[i] + .findPosition(command.position + command.number); } if (command.seqs[i].getStart() == start) { @@@ -732,16 -733,16 +735,16 @@@ tmp = new StringBuffer(oldstring.substring(0, start)); tmp.append(command.string[i]); String nogaprep = jalview.analysis.AlignSeq.extractGaps( - jalview.util.Comparison.GapChars, new String( - command.string[i])); + jalview.util.Comparison.GapChars, + new String(command.string[i])); int ipos = command.seqs[i].findPosition(start) - command.seqs[i].getStart(); tmp.append(oldstring.substring(end)); command.seqs[i].setSequence(tmp.toString()); command.string[i] = oldstring.substring(start, end).toCharArray(); String nogapold = jalview.analysis.AlignSeq.extractGaps( - jalview.util.Comparison.GapChars, new String( - command.string[i])); + jalview.util.Comparison.GapChars, + new String(command.string[i])); if (!nogaprep.toLowerCase().equals(nogapold.toLowerCase())) { if (newDSWasNeeded) @@@ -798,8 -799,6 +801,8 @@@ AlignmentAnnotation[] tmp; for (int s = 0; s < command.seqs.length; s++) { + command.seqs[s].sequenceChanged(); + if (modifyVisibility) { // Rows are only removed or added to sequence object. @@@ -836,7 -835,8 +839,8 @@@ tmp = saved; command.deletedAnnotationRows.put(command.seqs[s], saved); // and then remove any annotation in the other views - for (int alview = 0; views != null && alview < views.length; alview++) + for (int alview = 0; views != null + && alview < views.length; alview++) { if (views[alview] != command.al) { @@@ -888,7 -888,8 +892,8 @@@ } // and then duplicate added annotation on every other alignment // view - for (int vnum = 0; views != null && vnum < views.length; vnum++) + for (int vnum = 0; views != null + && vnum < views.length; vnum++) { if (views[vnum] != command.al) { @@@ -1015,8 -1016,8 +1020,8 @@@ } System.arraycopy(annotations[a].annotations, command.position, - temp, command.position + command.number, aSize - - command.position); + temp, command.position + command.number, + aSize - command.position); } else { @@@ -1059,8 -1060,8 +1064,8 @@@ annotations[a].annotations.length - command.position); if (copylen > 0) { - System.arraycopy(annotations[a].annotations, - command.position, deleted, 0, copylen); // command.number); + System.arraycopy(annotations[a].annotations, command.position, + deleted, 0, copylen); // command.number); } } @@@ -1069,10 -1070,10 +1074,10 @@@ if (annotations[a].annotations.length > command.position + command.number) { - System.arraycopy(annotations[a].annotations, command.position - + command.number, temp, command.position, - annotations[a].annotations.length - command.position - - command.number); // aSize + System.arraycopy(annotations[a].annotations, + command.position + command.number, temp, + command.position, annotations[a].annotations.length + - command.position - command.number); // aSize } } else @@@ -1104,8 -1105,8 +1109,8 @@@ } } - final static void adjustFeatures(Edit command, int index, int i, int j, - boolean insert) + final static void adjustFeatures(Edit command, int index, final int i, + final int j, boolean insert) { SequenceI seq = command.seqs[index]; SequenceI sequence = seq.getDatasetSequence(); @@@ -1125,73 -1126,56 +1130,73 @@@ return; } - SequenceFeature[] sf = sequence.getSequenceFeatures(); + List sf = sequence.getFeatures() + .getPositionalFeatures(); - if (sf == null) + if (sf.isEmpty()) { return; } - SequenceFeature[] oldsf = new SequenceFeature[sf.length]; + List oldsf = new ArrayList(); int cSize = j - i; - for (int s = 0; s < sf.length; s++) + for (SequenceFeature feature : sf) { - SequenceFeature copy = new SequenceFeature(sf[s]); + SequenceFeature copy = new SequenceFeature(feature); - oldsf[s] = copy; + oldsf.add(copy); - if (sf[s].getEnd() < i) + if (feature.getEnd() < i) { continue; } - if (sf[s].getBegin() > j) + if (feature.getBegin() > j) { - sf[s].setBegin(copy.getBegin() - cSize); - sf[s].setEnd(copy.getEnd() - cSize); + int newBegin = copy.getBegin() - cSize; + int newEnd = copy.getEnd() - cSize; + SequenceFeature newSf = new SequenceFeature(feature, newBegin, + newEnd, feature.getFeatureGroup(), feature.getScore()); + sequence.deleteFeature(feature); + sequence.addSequenceFeature(newSf); + // feature.setBegin(newBegin); + // feature.setEnd(newEnd); continue; } - if (sf[s].getBegin() >= i) + int newBegin = feature.getBegin(); + int newEnd = feature.getEnd(); + if (newBegin >= i) { - sf[s].setBegin(i); + newBegin = i; + // feature.setBegin(i); } - if (sf[s].getEnd() < j) + if (newEnd < j) { - sf[s].setEnd(j - 1); + newEnd = j - 1; + // feature.setEnd(j - 1); } + newEnd = newEnd - cSize; + // feature.setEnd(feature.getEnd() - (cSize)); - sf[s].setEnd(sf[s].getEnd() - (cSize)); - - if (sf[s].getBegin() > sf[s].getEnd()) + sequence.deleteFeature(feature); + if (newEnd >= newBegin) { - sequence.deleteFeature(sf[s]); + sequence.addSequenceFeature(new SequenceFeature(feature, newBegin, + newEnd, feature.getFeatureGroup(), feature.getScore())); } + // if (feature.getBegin() > feature.getEnd()) + // { + // sequence.deleteFeature(feature); + // } } if (command.editedFeatures == null) { - command.editedFeatures = new Hashtable(); + command.editedFeatures = new Hashtable>(); } command.editedFeatures.put(seq, oldsf); @@@ -1318,7 -1302,7 +1323,7 @@@ Hashtable deletedAnnotations; - Hashtable editedFeatures; + Hashtable> editedFeatures; AlignmentI al; @@@ -1334,51 -1318,51 +1339,51 @@@ char gapChar; - public Edit(Action command, SequenceI[] seqs, int position, int number, - char gapChar) + public Edit(Action cmd, SequenceI[] sqs, int pos, int count, + char gap) { - this.command = command; - this.seqs = seqs; - this.position = position; - this.number = number; - this.gapChar = gapChar; + this.command = cmd; + this.seqs = sqs; + this.position = pos; + this.number = count; + this.gapChar = gap; } - Edit(Action command, SequenceI[] seqs, int position, int number, - AlignmentI al) + Edit(Action cmd, SequenceI[] sqs, int pos, int count, + AlignmentI align) { - this.gapChar = al.getGapCharacter(); - this.command = command; - this.seqs = seqs; - this.position = position; - this.number = number; - this.al = al; - - alIndex = new int[seqs.length]; - for (int i = 0; i < seqs.length; i++) + this.gapChar = align.getGapCharacter(); + this.command = cmd; + this.seqs = sqs; + this.position = pos; + this.number = count; + this.al = align; + + alIndex = new int[sqs.length]; + for (int i = 0; i < sqs.length; i++) { - alIndex[i] = al.findIndex(seqs[i]); + alIndex[i] = align.findIndex(sqs[i]); } - fullAlignmentHeight = (al.getHeight() == seqs.length); + fullAlignmentHeight = (align.getHeight() == sqs.length); } - Edit(Action command, SequenceI[] seqs, int position, int number, - AlignmentI al, String replace) + Edit(Action cmd, SequenceI[] sqs, int pos, int count, + AlignmentI align, String replace) { - this.command = command; - this.seqs = seqs; - this.position = position; - this.number = number; - this.al = al; - this.gapChar = al.getGapCharacter(); - string = new char[seqs.length][]; - for (int i = 0; i < seqs.length; i++) + this.command = cmd; + this.seqs = sqs; + this.position = pos; + this.number = count; + this.al = align; + this.gapChar = align.getGapCharacter(); + string = new char[sqs.length][]; + for (int i = 0; i < sqs.length; i++) { string[i] = replace.toCharArray(); } - fullAlignmentHeight = (al.getHeight() == seqs.length); + fullAlignmentHeight = (align.getHeight() == sqs.length); } public SequenceI[] getSequences() diff --combined src/jalview/controller/AlignViewController.java index 5c1f403,24fc181..dd05843 --- a/src/jalview/controller/AlignViewController.java +++ b/src/jalview/controller/AlignViewController.java @@@ -85,10 -85,11 +85,11 @@@ public class AlignViewController implem SequenceGroup[] gps = null; if (sg != null && (cs == null || cs.isEmpty())) { - gps = jalview.analysis.Grouping.makeGroupsFrom(viewport - .getSequenceSelection(), viewport.getAlignmentView(true) - .getSequenceStrings(viewport.getGapCharacter()), viewport - .getAlignment().getGroups()); + gps = jalview.analysis.Grouping.makeGroupsFrom( + viewport.getSequenceSelection(), + viewport.getAlignmentView(true) + .getSequenceStrings(viewport.getGapCharacter()), + viewport.getAlignment().getGroups()); } else { @@@ -96,8 -97,8 +97,8 @@@ { gps = jalview.analysis.Grouping.makeGroupsFromCols( (sg == null) ? viewport.getAlignment().getSequencesArray() - : sg.getSequences().toArray(new SequenceI[0]), cs, - viewport.getAlignment().getGroups()); + : sg.getSequences().toArray(new SequenceI[0]), + cs, viewport.getAlignment().getGroups()); } } if (gps != null) @@@ -170,8 -171,9 +171,9 @@@ // JBPNote this routine could also mark rows, not just columns. // need a decent query structure to allow all types of feature searches BitSet bs = new BitSet(); - SequenceCollectionI sqcol = (viewport.getSelectionGroup() == null || extendCurrent) ? viewport - .getAlignment() : viewport.getSelectionGroup(); + SequenceCollectionI sqcol = (viewport.getSelectionGroup() == null + || extendCurrent) ? viewport.getAlignment() + : viewport.getSelectionGroup(); int nseq = findColumnsWithFeature(featureType, sqcol, bs); @@@ -189,14 -191,14 +191,14 @@@ { viewport.setColumnSelection(cs); alignPanel.paintAlignment(true); - int columnCount = invert ? (sqcol.getEndRes() - sqcol.getStartRes() + 1) - - bs.cardinality() + int columnCount = invert + ? (sqcol.getEndRes() - sqcol.getStartRes() + 1) + - bs.cardinality() : bs.cardinality(); avcg.setStatus(MessageManager.formatMessage( - "label.view_controller_toggled_marked", - new String[] { - toggle ? MessageManager.getString("label.toggled") - : MessageManager.getString("label.marked"), + "label.view_controller_toggled_marked", new String[] + { toggle ? MessageManager.getString("label.toggled") + : MessageManager.getString("label.marked"), String.valueOf(columnCount), invert ? MessageManager .getString("label.not_containing") @@@ -207,9 -209,9 +209,9 @@@ } else { - avcg.setStatus(MessageManager.formatMessage( - "label.no_feature_of_type_found", - new String[] { featureType })); + avcg.setStatus(MessageManager + .formatMessage("label.no_feature_of_type_found", new String[] + { featureType })); if (!extendCurrent) { cs.clear(); @@@ -232,66 -234,91 +234,66 @@@ static int findColumnsWithFeature(String featureType, SequenceCollectionI sqcol, BitSet bs) { - final int startPosition = sqcol.getStartRes() + 1; // converted to base 1 - final int endPosition = sqcol.getEndRes() + 1; + final int startColumn = sqcol.getStartRes() + 1; // converted to base 1 + final int endColumn = sqcol.getEndRes() + 1; List seqs = sqcol.getSequences(); int nseq = 0; for (SequenceI sq : seqs) { - boolean sequenceHasFeature = false; if (sq != null) { - SequenceFeature[] sfs = sq.getSequenceFeatures(); - if (sfs != null) - { - int ist = sq.findIndex(sq.getStart()); - int iend = sq.findIndex(sq.getEnd()); - if (iend < startPosition || ist > endPosition) - { - // sequence not in region - continue; - } - for (SequenceFeature sf : sfs) - { - // future functionality - featureType == null means mark columns - // containing all displayed features - if (sf != null && (featureType.equals(sf.getType()))) - { - // optimisation - could consider 'spos,apos' like cursor argument - // - findIndex wastes time by starting from first character and - // counting + // int ist = sq.findPosition(sqcol.getStartRes()); + List sfs = sq.findFeatures(startColumn, + endColumn, featureType); - int sfStartCol = sq.findIndex(sf.getBegin()); - int sfEndCol = sq.findIndex(sf.getEnd()); + if (!sfs.isEmpty()) + { + nseq++; + } - if (sf.isContactFeature()) - { - /* - * 'contact' feature - check for 'start' or 'end' - * position within the selected region - */ - if (sfStartCol >= startPosition - && sfStartCol <= endPosition) - { - bs.set(sfStartCol - 1); - sequenceHasFeature = true; - } - if (sfEndCol >= startPosition && sfEndCol <= endPosition) - { - bs.set(sfEndCol - 1); - sequenceHasFeature = true; - } - continue; - } + for (SequenceFeature sf : sfs) + { + int sfStartCol = sq.findIndex(sf.getBegin()); + int sfEndCol = sq.findIndex(sf.getEnd()); - /* - * contiguous feature - select feature positions (if any) - * within the selected region - */ - if (sfStartCol > endPosition || sfEndCol < startPosition) - { - // feature is outside selected region - continue; - } - sequenceHasFeature = true; - if (sfStartCol < startPosition) - { - sfStartCol = startPosition; - } - if (sfStartCol < ist) - { - sfStartCol = ist; - } - if (sfEndCol > endPosition) - { - sfEndCol = endPosition; - } - for (; sfStartCol <= sfEndCol; sfStartCol++) - { - bs.set(sfStartCol - 1); // convert to base 0 - } + if (sf.isContactFeature()) + { + /* + * 'contact' feature - check for 'start' or 'end' + * position within the selected region + */ + if (sfStartCol >= startColumn && sfStartCol <= endColumn) + { + bs.set(sfStartCol - 1); } + if (sfEndCol >= startColumn && sfEndCol <= endColumn) + { + bs.set(sfEndCol - 1); + } + continue; } - } - if (sequenceHasFeature) - { - nseq++; + /* + * contiguous feature - select feature positions (if any) + * within the selected region + */ + if (sfStartCol < startColumn) + { + sfStartCol = startColumn; + } + // not sure what the point of this is + // if (sfStartCol < ist) + // { + // sfStartCol = ist; + // } + if (sfEndCol > endColumn) + { + sfEndCol = endColumn; + } + for (; sfStartCol <= sfEndCol; sfStartCol++) + { + bs.set(sfStartCol - 1); // convert to base 0 + } } } } @@@ -333,8 -360,8 +335,8 @@@ } SequenceI[] oldOrder = al.getSequencesArray(); AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method); - avcg.addHistoryItem(new OrderCommand(methodText, oldOrder, viewport - .getAlignment())); + avcg.addHistoryItem(new OrderCommand(methodText, oldOrder, + viewport.getAlignment())); alignPanel.paintAlignment(true); } @@@ -352,9 -379,10 +354,10 @@@ boolean featuresFile = false; try { - featuresFile = new FeaturesFile(false, file, protocol).parse(viewport - .getAlignment().getDataset(), alignPanel.getFeatureRenderer() - .getFeatureColours(), false, relaxedIdMatching); + featuresFile = new FeaturesFile(false, file, protocol).parse( + viewport.getAlignment().getDataset(), + alignPanel.getFeatureRenderer().getFeatureColours(), false, + relaxedIdMatching); } catch (Exception ex) { ex.printStackTrace(); @@@ -390,8 -418,9 +393,9 @@@ } // JBPNote this routine could also mark rows, not just columns. BitSet bs = new BitSet(); - SequenceCollectionI sqcol = (viewport.getSelectionGroup() == null || extendCurrent) ? viewport - .getAlignment() : viewport.getSelectionGroup(); + SequenceCollectionI sqcol = (viewport.getSelectionGroup() == null + || extendCurrent) ? viewport.getAlignment() + : viewport.getSelectionGroup(); // this could be a lambda... - the remains of the method is boilerplate, // except for the different messages for reporting selection. @@@ -411,14 -440,14 +415,14 @@@ { viewport.setColumnSelection(cs); alignPanel.paintAlignment(true); - int columnCount = invert ? (sqcol.getEndRes() - sqcol.getStartRes() + 1) - - bs.cardinality() + int columnCount = invert + ? (sqcol.getEndRes() - sqcol.getStartRes() + 1) + - bs.cardinality() : bs.cardinality(); avcg.setStatus(MessageManager.formatMessage( - "label.view_controller_toggled_marked", - new String[] { - toggle ? MessageManager.getString("label.toggled") - : MessageManager.getString("label.marked"), + "label.view_controller_toggled_marked", new String[] + { toggle ? MessageManager.getString("label.toggled") + : MessageManager.getString("label.marked"), String.valueOf(columnCount), invert ? MessageManager .getString("label.not_containing") diff --combined src/jalview/datamodel/AlignedCodonFrame.java index 54f41f8,83eeb3d..ec11fc1 --- a/src/jalview/datamodel/AlignedCodonFrame.java +++ b/src/jalview/datamodel/AlignedCodonFrame.java @@@ -90,10 -90,11 +90,11 @@@ public class AlignedCodonFram return that.mapping == null; } // TODO: can simplify by asserting fromSeq is a dataset sequence - return (this.fromSeq == that.fromSeq || (this.fromSeq != null - && that.fromSeq != null - && this.fromSeq.getDatasetSequence() != null && this.fromSeq - .getDatasetSequence() == that.fromSeq.getDatasetSequence())) + return (this.fromSeq == that.fromSeq + || (this.fromSeq != null && that.fromSeq != null + && this.fromSeq.getDatasetSequence() != null + && this.fromSeq.getDatasetSequence() == that.fromSeq + .getDatasetSequence())) && this.mapping.equals(that.mapping); } @@@ -149,8 -150,8 +150,8 @@@ SequenceI fromSeq = (dnaseq.getDatasetSequence() == null) ? dnaseq : dnaseq.getDatasetSequence(); - SequenceI toSeq = (aaseq.getDatasetSequence() == null) ? aaseq : aaseq - .getDatasetSequence(); + SequenceI toSeq = (aaseq.getDatasetSequence() == null) ? aaseq + : aaseq.getDatasetSequence(); /* * if we already hold a mapping between these sequences, just add to it @@@ -434,8 -435,8 +435,8 @@@ { SequenceI targetDs = target.getDatasetSequence() == null ? target : target.getDatasetSequence(); - SequenceI queryDs = query.getDatasetSequence() == null ? query : query - .getDatasetSequence(); + SequenceI queryDs = query.getDatasetSequence() == null ? query + : query.getDatasetSequence(); if (targetDs == null || queryDs == null /*|| dnaToProt == null*/) { return null; @@@ -504,11 -505,12 +505,11 @@@ * Read off the mapped nucleotides (converting to position base 0) */ codonPos = MappingUtils.flattenRanges(codonPos); - char[] dna = dnaSeq.getSequence(); int start = dnaSeq.getStart(); - result.add( - new char[] - { dna[codonPos[0] - start], dna[codonPos[1] - start], - dna[codonPos[2] - start] }); + char c1 = dnaSeq.getCharAt(codonPos[0] - start); + char c2 = dnaSeq.getCharAt(codonPos[1] - start); + char c3 = dnaSeq.getCharAt(codonPos[2] - start); + result.add(new char[] { c1, c2, c3 }); } } return result.isEmpty() ? null : result; @@@ -580,8 -582,9 +581,9 @@@ */ protected int realiseWith(SequenceI seq, boolean doUpdate) { - SequenceI ds = seq.getDatasetSequence() != null ? seq - .getDatasetSequence() : seq; + SequenceI ds = seq.getDatasetSequence() != null + ? seq.getDatasetSequence() + : seq; int count = 0; /* @@@ -655,8 -658,8 +657,8 @@@ { int start = replacement.getStart(); int end = replacement.getEnd(); - boolean mappingOverlapsSequence = (mapStart >= start && mapStart <= end) - || (mapEnd >= start && mapEnd <= end); + boolean mappingOverlapsSequence = (mapStart >= start + && mapStart <= end) || (mapEnd >= start && mapEnd <= end); if (mappingOverlapsSequence) { return true; @@@ -733,8 -736,8 +735,8 @@@ { SequenceI dssFrom = fromSeq.getDatasetSequence() == null ? fromSeq : fromSeq.getDatasetSequence(); - SequenceI dssTo = toSeq.getDatasetSequence() == null ? toSeq : toSeq - .getDatasetSequence(); + SequenceI dssTo = toSeq.getDatasetSequence() == null ? toSeq + : toSeq.getDatasetSequence(); for (SequenceToSequenceMapping mapping : mappings) { diff --combined src/jalview/datamodel/Alignment.java index 26e8db1,5733719..8c5e4ac --- a/src/jalview/datamodel/Alignment.java +++ b/src/jalview/datamodel/Alignment.java @@@ -143,9 -143,8 +143,8 @@@ public class Alignment implements Align */ public static AlignmentI createAlignment(CigarArray compactAlignment) { - throw new Error( - MessageManager - .getString("error.alignment_cigararray_not_implemented")); + throw new Error(MessageManager + .getString("error.alignment_cigararray_not_implemented")); // this(compactAlignment.refCigars); } @@@ -188,7 -187,6 +187,6 @@@ return AlignmentUtils.getSequencesByName(this); } - @Override public SequenceI getSequenceAt(int i) { @@@ -475,7 -473,9 +473,9 @@@ return; } // remove annotation very quickly - AlignmentAnnotation[] t, todelete = new AlignmentAnnotation[annotations.length], tokeep = new AlignmentAnnotation[annotations.length]; + AlignmentAnnotation[] t, + todelete = new AlignmentAnnotation[annotations.length], + tokeep = new AlignmentAnnotation[annotations.length]; int i, p, k; if (gp == null) { @@@ -608,7 -608,7 +608,7 @@@ sqname = sq.getName(); if (sqname.equals(token) // exact match || (b && // allow imperfect matches - case varies - (sqname.equalsIgnoreCase(token)))) + (sqname.equalsIgnoreCase(token)))) { return getSequenceAt(i); } @@@ -689,7 -689,6 +689,6 @@@ return -1; } - @Override public int getHeight() { @@@ -1096,10 -1095,9 +1095,9 @@@ } if (dbr.getMap().getTo().getDatasetSequence() != null) { - throw new Error( - "Implementation error: Map.getTo() for dbref " + dbr - + " from " + curDs.getName() - + " is not a dataset sequence."); + throw new Error("Implementation error: Map.getTo() for dbref " + + dbr + " from " + curDs.getName() + + " is not a dataset sequence."); } // we recurse to add all forward references to dataset sequences via // DBRefs/etc @@@ -1236,8 -1234,8 +1234,8 @@@ current = getSequenceAt(i); // This should really be a sequence method ends[i * 2] = current.findIndex(current.getStart()); - ends[i * 2 + 1] = current.findIndex(current.getStart() - + current.getLength()); + ends[i * 2 + 1] = current + .findIndex(current.getStart() + current.getLength()); boolean hitres = false; for (int j = 0, rs = 0, ssiz = current.getLength(); j < ssiz; j++) { @@@ -1473,13 -1471,15 +1471,15 @@@ { // TODO JAL-1270 needs test coverage // currently tested for use in jalview.gui.SequenceFetcher - boolean samegap = toappend.getGapCharacter() == getGapCharacter(); char oldc = toappend.getGapCharacter(); + boolean samegap = oldc == getGapCharacter(); boolean hashidden = toappend.getHiddenSequences() != null && toappend.getHiddenSequences().hiddenSequences != null; // get all sequences including any hidden ones - List sqs = (hashidden) ? toappend.getHiddenSequences() - .getFullAlignment().getSequences() : toappend.getSequences(); + List sqs = (hashidden) + ? toappend.getHiddenSequences().getFullAlignment() + .getSequences() + : toappend.getSequences(); if (sqs != null) { // avoid self append deadlock by @@@ -1490,7 -1490,14 +1490,7 @@@ { if (!samegap) { - char[] oldseq = addedsq.getSequence(); - for (int c = 0; c < oldseq.length; c++) - { - if (oldseq[c] == oldc) - { - oldseq[c] = gapCharacter; - } - } + addedsq.replace(oldc, gapCharacter); } toappendsq.add(addedsq); } @@@ -1554,8 -1561,8 +1554,8 @@@ if (ourval instanceof String) { // append strings - this.setProperty(k, ((String) ourval) + "; " - + ((String) toapprop)); + this.setProperty(k, + ((String) ourval) + "; " + ((String) toapprop)); } else { @@@ -1623,9 -1630,8 +1623,8 @@@ { for (AlignmentAnnotation a : alignmentAnnotation) { - if (a.getCalcId() == calcId - || (a.getCalcId() != null && calcId != null && a - .getCalcId().equals(calcId))) + if (a.getCalcId() == calcId || (a.getCalcId() != null + && calcId != null && a.getCalcId().equals(calcId))) { aa.add(a); } @@@ -1641,11 -1647,12 +1640,12 @@@ ArrayList aa = new ArrayList<>(); for (AlignmentAnnotation ann : getAlignmentAnnotation()) { - if ((calcId == null || (ann.getCalcId() != null && ann.getCalcId() - .equals(calcId))) - && (seq == null || (ann.sequenceRef != null && ann.sequenceRef == seq)) - && (label == null || (ann.label != null && ann.label - .equals(label)))) + if ((calcId == null || (ann.getCalcId() != null + && ann.getCalcId().equals(calcId))) + && (seq == null || (ann.sequenceRef != null + && ann.sequenceRef == seq)) + && (label == null + || (ann.label != null && ann.label.equals(label)))) { aa.add(ann); } diff --combined src/jalview/datamodel/AlignmentAnnotation.java index 56bfd74,6bbd566..c464af2 --- a/src/jalview/datamodel/AlignmentAnnotation.java +++ b/src/jalview/datamodel/AlignmentAnnotation.java @@@ -96,13 -96,14 +96,13 @@@ public class AlignmentAnnotatio * Updates the _rnasecstr field Determines the positions that base pair and * the positions of helices based on secondary structure from a Stockholm file * - * @param RNAannot + * @param rnaAnnotation */ - private void _updateRnaSecStr(CharSequence RNAannot) + private void _updateRnaSecStr(CharSequence rnaAnnotation) { try { - bps = Rna.getModeleBP(RNAannot); - _rnasecstr = Rna.getBasePairs(bps); + _rnasecstr = Rna.getHelixMap(rnaAnnotation); invalidrnastruc = -1; } catch (WUSSParseException px) { @@@ -113,6 -114,8 +113,6 @@@ { return; } - Rna.HelixMap(_rnasecstr); - // setRNAStruc(RNAannot); if (_rnasecstr != null && _rnasecstr.length > 0) { @@@ -270,6 -273,12 +270,6 @@@ } } - // JBPNote: what does this do ? - public void ConcenStru(CharSequence RNAannot) throws WUSSParseException - { - bps = Rna.getModeleBP(RNAannot); - } - /** * Creates a new AlignmentAnnotation object. * @@@ -370,49 -379,25 +370,25 @@@ firstChar = annotations[i].displayCharacter.charAt(0); // check to see if it looks like a sequence or is secondary structure // labelling. - if (annotations[i].secondaryStructure != ' ' - && !hasIcons - && - // Uncomment to only catch case where - // displayCharacter==secondary - // Structure - // to correctly redisplay SS annotation imported from Stockholm, - // exported to JalviewXML and read back in again. - // && - // annotations[i].displayCharacter.charAt(0)==annotations[i].secondaryStructure - firstChar != ' ' - && firstChar != '$' - && firstChar != 0xCE - && firstChar != '(' - && firstChar != '[' - && firstChar != '>' - && firstChar != '{' - && firstChar != 'A' - && firstChar != 'B' - && firstChar != 'C' - && firstChar != 'D' - && firstChar != 'E' - && firstChar != 'F' - && firstChar != 'G' - && firstChar != 'H' - && firstChar != 'I' - && firstChar != 'J' - && firstChar != 'K' - && firstChar != 'L' - && firstChar != 'M' - && firstChar != 'N' - && firstChar != 'O' - && firstChar != 'P' - && firstChar != 'Q' - && firstChar != 'R' - && firstChar != 'S' - && firstChar != 'T' - && firstChar != 'U' - && firstChar != 'V' - && firstChar != 'W' - && firstChar != 'X' - && firstChar != 'Y' - && firstChar != 'Z' + if (annotations[i].secondaryStructure != ' ' && !hasIcons && + // Uncomment to only catch case where + // displayCharacter==secondary + // Structure + // to correctly redisplay SS annotation imported from Stockholm, + // exported to JalviewXML and read back in again. + // && + // annotations[i].displayCharacter.charAt(0)==annotations[i].secondaryStructure + firstChar != ' ' && firstChar != '$' && firstChar != 0xCE + && firstChar != '(' && firstChar != '[' && firstChar != '>' + && firstChar != '{' && firstChar != 'A' && firstChar != 'B' + && firstChar != 'C' && firstChar != 'D' && firstChar != 'E' + && firstChar != 'F' && firstChar != 'G' && firstChar != 'H' + && firstChar != 'I' && firstChar != 'J' && firstChar != 'K' + && firstChar != 'L' && firstChar != 'M' && firstChar != 'N' + && firstChar != 'O' && firstChar != 'P' && firstChar != 'Q' + && firstChar != 'R' && firstChar != 'S' && firstChar != 'T' + && firstChar != 'U' && firstChar != 'V' && firstChar != 'W' + && firstChar != 'X' && firstChar != 'Y' && firstChar != 'Z' && firstChar != '-' && firstChar < jalview.schemes.ResidueProperties.aaIndex.length) { @@@ -503,12 -488,17 +479,17 @@@ { return ((index + offset < 0) || (index + offset) >= max || annotations[index + offset] == null - || (annotations[index + offset].secondaryStructure <= ' ') ? ' ' - : annotations[index + offset].displayCharacter == null - || annotations[index + offset].displayCharacter - .length() == 0 ? annotations[index + offset].secondaryStructure - : annotations[index + offset].displayCharacter - .charAt(0)); + || (annotations[index + offset].secondaryStructure <= ' ') + ? ' ' + : annotations[index + offset].displayCharacter == null + || annotations[index + + offset].displayCharacter + .length() == 0 + ? annotations[index + + offset].secondaryStructure + : annotations[index + + offset].displayCharacter + .charAt(0)); } @Override @@@ -519,10 -509,15 +500,15 @@@ for (int i = offset; i < mx; i++) { - string[i] = (annotations[i] == null || (annotations[i].secondaryStructure <= 32)) ? ' ' - : (annotations[i].displayCharacter == null - || annotations[i].displayCharacter.length() == 0 ? annotations[i].secondaryStructure - : annotations[i].displayCharacter.charAt(0)); + string[i] = (annotations[i] == null + || (annotations[i].secondaryStructure <= 32)) + ? ' ' + : (annotations[i].displayCharacter == null + || annotations[i].displayCharacter + .length() == 0 + ? annotations[i].secondaryStructure + : annotations[i].displayCharacter + .charAt(0)); } return new String(string); } @@@ -798,8 -793,8 +784,8 @@@ Annotation[] temp = new Annotation[endRes - startRes + 1]; if (startRes < annotations.length) { - System.arraycopy(annotations, startRes, temp, 0, endRes - startRes - + 1); + System.arraycopy(annotations, startRes, temp, 0, + endRes - startRes + 1); } if (sequenceRef != null) { @@@ -1019,8 -1014,8 +1005,8 @@@ { if (i + 1 < iSize) { - System.arraycopy(annotations, i + 1, annotations, i, iSize - i - - 1); + System.arraycopy(annotations, i + 1, annotations, i, + iSize - i - 1); } iSize--; } @@@ -1052,14 -1047,16 +1038,16 @@@ { if (sequenceRef != null) { - boolean rIsDs = sequenceRef.getDatasetSequence() == null, tIsDs = sequenceI - .getDatasetSequence() == null; + boolean rIsDs = sequenceRef.getDatasetSequence() == null, + tIsDs = sequenceI.getDatasetSequence() == null; if (sequenceRef != sequenceI - && (rIsDs && !tIsDs && sequenceRef != sequenceI - .getDatasetSequence()) - && (!rIsDs && tIsDs && sequenceRef.getDatasetSequence() != sequenceI) - && (!rIsDs && !tIsDs && sequenceRef.getDatasetSequence() != sequenceI - .getDatasetSequence()) + && (rIsDs && !tIsDs + && sequenceRef != sequenceI.getDatasetSequence()) + && (!rIsDs && tIsDs + && sequenceRef.getDatasetSequence() != sequenceI) + && (!rIsDs && !tIsDs + && sequenceRef.getDatasetSequence() != sequenceI + .getDatasetSequence()) && !sequenceRef.equals(sequenceI)) { // if sequenceRef isn't intersecting with sequenceI @@@ -1254,8 -1251,10 +1242,10 @@@ throw new Error( "liftOver currently not implemented for transfer of annotation between different types of seqeunce"); } - boolean mapIsTo = (sp2sq != null) ? (sp2sq.getTo() == sq || sp2sq - .getTo() == sq.getDatasetSequence()) : false; + boolean mapIsTo = (sp2sq != null) + ? (sp2sq.getTo() == sq + || sp2sq.getTo() == sq.getDatasetSequence()) + : false; // TODO build a better annotation element map and get rid of annotations[] Map mapForsq = new HashMap(); @@@ -1265,9 -1264,9 +1255,9 @@@ { for (Entry ie : sequenceMapping.entrySet()) { - Integer mpos = Integer.valueOf(mapIsTo ? sp2sq - .getMappedPosition(ie.getKey()) : sp2sq.getPosition(ie - .getKey())); + Integer mpos = Integer + .valueOf(mapIsTo ? sp2sq.getMappedPosition(ie.getKey()) + : sp2sq.getPosition(ie.getKey())); if (mpos >= sq.getStart() && mpos <= sq.getEnd()) { mapForsq.put(mpos, ie.getValue()); @@@ -1454,8 -1453,8 +1444,8 @@@ * up to and excluding the target column; if the count is less * than 1, the opening bracket is unmatched, so return its match */ - String closer = String.valueOf(Rna - .getMatchingClosingParenthesis(symbol)); + String closer = String + .valueOf(Rna.getMatchingClosingParenthesis(symbol)); String opener = String.valueOf(symbol); int count = 0; for (int j = col + 1; j < column; j++) diff --combined src/jalview/datamodel/BinarySequence.java index 477f4a7,53bffa9..c33abb3 --- a/src/jalview/datamodel/BinarySequence.java +++ b/src/jalview/datamodel/BinarySequence.java @@@ -70,7 -70,7 +70,7 @@@ public class BinarySequence extends Seq int nores = (isNa) ? ResidueProperties.maxNucleotideIndex : ResidueProperties.maxProteinIndex; - dbinary = new double[getSequence().length * nores]; + dbinary = new double[getLength() * nores]; return nores; } @@@ -88,7 -88,7 +88,7 @@@ { int nores = initMatrixGetNoRes(); final int[] sindex = getSymbolmatrix(); - for (int i = 0; i < getSequence().length; i++) + for (int i = 0; i < getLength(); i++) { int aanum = nores - 1; @@@ -119,10 -119,10 +119,10 @@@ { if (isNa != smtrx.isDNA()) { - throw new InvalidSequenceTypeException("matrix " - + smtrx.getClass().getCanonicalName() - + " is not a valid matrix for " - + (isNa ? "nucleotide" : "protein") + "sequences"); + throw new InvalidSequenceTypeException( + "matrix " + smtrx.getClass().getCanonicalName() + + " is not a valid matrix for " + + (isNa ? "nucleotide" : "protein") + "sequences"); } matrixEncode(smtrx.isDNA() ? ResidueProperties.nucleotideIndex : ResidueProperties.aaIndex, smtrx.getMatrix()); @@@ -132,7 -132,7 +132,7 @@@ { int nores = initMatrixGetNoRes(); - for (int i = 0, iSize = getSequence().length; i < iSize; i++) + for (int i = 0, iSize = getLength(); i < iSize; i++) { int aanum = nores - 1; diff --combined src/jalview/datamodel/Mapping.java index 66425d2,fe396ce..328b96a --- a/src/jalview/datamodel/Mapping.java +++ b/src/jalview/datamodel/Mapping.java @@@ -46,7 -46,7 +46,7 @@@ public class Mappin /* * The characters of the aligned sequence e.g. "-cGT-ACgTG-" */ - private final char[] alignedSeq; + private final SequenceI alignedSeq; /* * the sequence start residue @@@ -102,7 -102,7 +102,7 @@@ */ public AlignedCodonIterator(SequenceI seq, char gapChar) { - this.alignedSeq = seq.getSequence(); + this.alignedSeq = seq; this.start = seq.getStart(); this.gap = gapChar; fromRanges = map.getFromRanges().iterator(); @@@ -176,14 -176,14 +176,14 @@@ if (toPosition <= currentToRange[1]) { SequenceI seq = Mapping.this.to; - char pep = seq.getSequence()[toPosition - seq.getStart()]; + char pep = seq.getCharAt(toPosition - seq.getStart()); toPosition++; return String.valueOf(pep); } if (!toRanges.hasNext()) { - throw new NoSuchElementException("Ran out of peptide at position " - + toPosition); + throw new NoSuchElementException( + "Ran out of peptide at position " + toPosition); } currentToRange = toRanges.next(); toPosition = currentToRange[0]; @@@ -257,10 -257,9 +257,10 @@@ * allow for offset e.g. treat pos 8 as 2 if sequence starts at 7 */ int truePos = sequencePos - (start - 1); - while (alignedBases < truePos && alignedColumn < alignedSeq.length) + int length = alignedSeq.getLength(); + while (alignedBases < truePos && alignedColumn < length) { - char c = alignedSeq[alignedColumn++]; + char c = alignedSeq.getCharAt(alignedColumn++); if (c != gap && !Comparison.isGap(c)) { alignedBases++; @@@ -531,8 -530,9 +531,8 @@@ SequenceFeature[] vf = new SequenceFeature[frange.length / 2]; for (int i = 0, v = 0; i < frange.length; i += 2, v++) { - vf[v] = new SequenceFeature(f); - vf[v].setBegin(frange[i]); - vf[v].setEnd(frange[i + 1]); + vf[v] = new SequenceFeature(f, frange[i], frange[i + 1], + f.getFeatureGroup(), f.getScore()); if (frange.length > 2) { vf[v].setDescription(f.getDescription() + "\nPart " + (v + 1)); @@@ -541,7 -541,27 +541,7 @@@ return vf; } } - if (false) // else - { - int[] word = getWord(f.getBegin()); - if (word[0] < word[1]) - { - f.setBegin(word[0]); - } - else - { - f.setBegin(word[1]); - } - word = getWord(f.getEnd()); - if (word[0] > word[1]) - { - f.setEnd(word[0]); - } - else - { - f.setEnd(word[1]); - } - } + // give up and just return the feature. return new SequenceFeature[] { f }; } @@@ -667,8 -687,8 +667,8 @@@ to[f * 2] = r[0]; to[f * 2 + 1] = r[1]; } - copy.setMap(new MapList(from, to, map.getFromRatio(), map - .getToRatio())); + copy.setMap( + new MapList(from, to, map.getFromRatio(), map.getToRatio())); } return copy; } @@@ -715,7 -735,8 +715,8 @@@ * @param gapChar * @return */ - public Iterator getCodonIterator(SequenceI seq, char gapChar) + public Iterator getCodonIterator(SequenceI seq, + char gapChar) { return new AlignedCodonIterator(seq, gapChar); } @@@ -726,8 -747,8 +727,8 @@@ @Override public String toString() { - return String.format("%s %s", this.map.toString(), this.to == null ? "" - : this.to.getName()); + return String.format("%s %s", this.map.toString(), + this.to == null ? "" : this.to.getName()); } /** diff --combined src/jalview/datamodel/SearchResults.java index 8ed47dc,a270e37..cde50e5 --- a/src/jalview/datamodel/SearchResults.java +++ b/src/jalview/datamodel/SearchResults.java @@@ -34,7 -34,7 +34,7 @@@ import java.util.List public class SearchResults implements SearchResultsI { - private List matches = new ArrayList(); + private List matches = new ArrayList<>(); /** * One match consists of a sequence reference, start and end positions. @@@ -42,17 -42,17 +42,17 @@@ */ public class Match implements SearchResultMatchI { - SequenceI sequence; + final SequenceI sequence; /** * Start position of match in sequence (base 1) */ - int start; + final int start; /** * End position (inclusive) (base 1) */ - int end; + final int end; /** * create a Match on a range of sequence. Match always holds region in @@@ -133,6 -133,11 +133,6 @@@ return sb.toString(); } - public void setSequence(SequenceI seq) - { - this.sequence = seq; - } - /** * Hashcode is the hashcode of the matched sequence plus a hash of start and * end positions. Match objects that pass the test for equals are guaranteed @@@ -159,8 -164,8 +159,8 @@@ return false; } SearchResultMatchI m = (SearchResultMatchI) obj; - return (sequence == m.getSequence() && start == m.getStart() && end == m - .getEnd()); + return (sequence == m.getSequence() && start == m.getStart() + && end == m.getEnd()); } } @@@ -214,15 -219,20 +214,15 @@@ m = (Match) _m; mfound = false; - if (m.sequence == sequence) - { - mfound = true; - // locate aligned position - matchStart = sequence.findIndex(m.start) - 1; - matchEnd = sequence.findIndex(m.end) - 1; - } - else if (m.sequence == sequence.getDatasetSequence()) + if (m.sequence == sequence + || m.sequence == sequence.getDatasetSequence()) { mfound = true; - // locate region in local context matchStart = sequence.findIndex(m.start) - 1; - matchEnd = sequence.findIndex(m.end) - 1; + matchEnd = m.start == m.end ? matchStart : sequence + .findIndex(m.end) - 1; } + if (mfound) { if (matchStart <= end && matchEnd >= start) @@@ -254,7 -264,7 +254,7 @@@ else { // debug - // System.err.println("Outwith bounds!" + matchStart+">"+end +" or " + // System.err.println("Outwith bounds!" + matchStart+">"+end +" or " // + matchEnd+"<"+start); } } @@@ -353,10 -363,4 +353,10 @@@ SearchResultsI sr = (SearchResultsI) obj; return matches.equals(sr.getResults()); } + + @Override + public void addSearchResults(SearchResultsI toAdd) + { + matches.addAll(toAdd.getResults()); + } } diff --combined src/jalview/datamodel/Sequence.java index a01d185,0103237..2f1da7f --- a/src/jalview/datamodel/Sequence.java +++ b/src/jalview/datamodel/Sequence.java @@@ -22,8 -22,6 +22,8 @@@ package jalview.datamodel import jalview.analysis.AlignSeq; import jalview.api.DBRefEntryI; +import jalview.datamodel.features.SequenceFeatures; +import jalview.datamodel.features.SequenceFeaturesI; import jalview.util.Comparison; import jalview.util.DBRefUtils; import jalview.util.MapList; @@@ -35,11 -33,8 +35,11 @@@ import java.util.BitSet import java.util.Collections; import java.util.Enumeration; import java.util.List; +import java.util.ListIterator; import java.util.Vector; +import com.stevesoft.pat.Regex; + import fr.orsay.lri.varna.models.rna.RNA; /** @@@ -51,11 -46,6 +51,11 @@@ */ public class Sequence extends ASequence implements SequenceI { + private static final Regex limitrx = new Regex( + "[/][0-9]{1,}[-][0-9]{1,}$"); + + private static final Regex endrx = new Regex("[0-9]{1,}$"); + SequenceI datasetSequence; String name; @@@ -89,22 -79,10 +89,22 @@@ */ int index = -1; - /** - * array of sequence features - may not be null for a valid sequence object + private SequenceFeatures sequenceFeatureStore; + + /* + * A cursor holding the approximate current view position to the sequence, + * as determined by findIndex or findPosition or findPositions. + * Using a cursor as a hint allows these methods to be more performant for + * large sequences. + */ + private SequenceCursor cursor; + + /* + * A number that should be incremented whenever the sequence is edited. + * If the value matches the cursor token, then we can trust the cursor, + * if not then it should be recomputed. */ - public SequenceFeature[] sequenceFeatures; + private int changeCount; /** * Creates a new Sequence object. @@@ -121,13 -99,11 +121,13 @@@ */ public Sequence(String name, String sequence, int start, int end) { + this(); initSeqAndName(name, sequence.toCharArray(), start, end); } public Sequence(String name, char[] sequence, int start, int end) { + this(); initSeqAndName(name, sequence, start, end); } @@@ -151,12 -127,17 +151,12 @@@ checkValidRange(); } - com.stevesoft.pat.Regex limitrx = new com.stevesoft.pat.Regex( - "[/][0-9]{1,}[-][0-9]{1,}$"); - - com.stevesoft.pat.Regex endrx = new com.stevesoft.pat.Regex("[0-9]{1,}$"); - void parseId() { if (name == null) { - System.err - .println("POSSIBLE IMPLEMENTATION ERROR: null sequence name passed to constructor."); + System.err.println( + "POSSIBLE IMPLEMENTATION ERROR: null sequence name passed to constructor."); name = ""; } // Does sequence have the /start-end signature? @@@ -197,14 -178,6 +197,14 @@@ } /** + * default constructor + */ + private Sequence() + { + sequenceFeatureStore = new SequenceFeatures(); + } + + /** * Creates a new Sequence object. * * @param name @@@ -243,8 -216,8 +243,8 @@@ */ public Sequence(SequenceI seq, AlignmentAnnotation[] alAnnotation) { + this(); initSeqFrom(seq, alAnnotation); - } /** @@@ -260,38 -233,33 +260,38 @@@ protected void initSeqFrom(SequenceI seq, AlignmentAnnotation[] alAnnotation) { - { - char[] oseq = seq.getSequence(); - initSeqAndName(seq.getName(), Arrays.copyOf(oseq, oseq.length), - seq.getStart(), seq.getEnd()); - } + char[] oseq = seq.getSequence(); // returns a copy of the array + initSeqAndName(seq.getName(), oseq, seq.getStart(), seq.getEnd()); + description = seq.getDescription(); if (seq != datasetSequence) { setDatasetSequence(seq.getDatasetSequence()); } - if (datasetSequence == null && seq.getDBRefs() != null) + + /* + * only copy DBRefs and seqfeatures if we really are a dataset sequence + */ + if (datasetSequence == null) { - // only copy DBRefs and seqfeatures if we really are a dataset sequence - DBRefEntry[] dbr = seq.getDBRefs(); - for (int i = 0; i < dbr.length; i++) - { - addDBRef(new DBRefEntry(dbr[i])); - } - if (seq.getSequenceFeatures() != null) + if (seq.getDBRefs() != null) { - SequenceFeature[] sf = seq.getSequenceFeatures(); - for (int i = 0; i < sf.length; i++) + DBRefEntry[] dbr = seq.getDBRefs(); + for (int i = 0; i < dbr.length; i++) { - addSequenceFeature(new SequenceFeature(sf[i])); + addDBRef(new DBRefEntry(dbr[i])); } } + + /* + * make copies of any sequence features + */ + for (SequenceFeature sf : seq.getSequenceFeatures()) + { + addSequenceFeature(new SequenceFeature(sf)); + } } + if (seq.getAnnotation() != null) { AlignmentAnnotation[] sqann = seq.getAnnotation(); @@@ -328,67 -296,123 +328,67 @@@ } @Override - public void setSequenceFeatures(SequenceFeature[] features) + public void setSequenceFeatures(List features) { - if (datasetSequence == null) - { - sequenceFeatures = features; - } - else + if (datasetSequence != null) { - if (datasetSequence.getSequenceFeatures() != features - && datasetSequence.getSequenceFeatures() != null - && datasetSequence.getSequenceFeatures().length > 0) - { - new Exception( - "Warning: JAL-2046 side effect ? Possible implementation error: overwriting dataset sequence features by setting sequence features on alignment") - .printStackTrace(); - } datasetSequence.setSequenceFeatures(features); + return; } + sequenceFeatureStore = new SequenceFeatures(features); } @Override public synchronized boolean addSequenceFeature(SequenceFeature sf) { - if (sequenceFeatures == null && datasetSequence != null) - { - return datasetSequence.addSequenceFeature(sf); - } - if (sequenceFeatures == null) + if (sf.getType() == null) { - sequenceFeatures = new SequenceFeature[0]; + System.err.println("SequenceFeature type may not be null: " + + sf.toString()); + return false; } - for (int i = 0; i < sequenceFeatures.length; i++) + if (datasetSequence != null) { - if (sequenceFeatures[i].equals(sf)) - { - return false; - } + return datasetSequence.addSequenceFeature(sf); } - SequenceFeature[] temp = new SequenceFeature[sequenceFeatures.length - + 1]; - System.arraycopy(sequenceFeatures, 0, temp, 0, sequenceFeatures.length); - temp[sequenceFeatures.length] = sf; - - sequenceFeatures = temp; - return true; + return sequenceFeatureStore.add(sf); } @Override public void deleteFeature(SequenceFeature sf) { - if (sequenceFeatures == null) - { - if (datasetSequence != null) - { - datasetSequence.deleteFeature(sf); - } - return; - } - - int index = 0; - for (index = 0; index < sequenceFeatures.length; index++) - { - if (sequenceFeatures[index].equals(sf)) - { - break; - } - } - - if (index == sequenceFeatures.length) - { - return; - } - - int sfLength = sequenceFeatures.length; - if (sfLength < 2) + if (datasetSequence != null) { - sequenceFeatures = null; + datasetSequence.deleteFeature(sf); } else { - SequenceFeature[] temp = new SequenceFeature[sfLength - 1]; - System.arraycopy(sequenceFeatures, 0, temp, 0, index); - - if (index < sfLength) - { - System.arraycopy(sequenceFeatures, index + 1, temp, index, - sequenceFeatures.length - index - 1); - } - - sequenceFeatures = temp; + sequenceFeatureStore.delete(sf); } } /** - * Returns the sequence features (if any), looking first on the sequence, then - * on its dataset sequence, and so on until a non-null value is found (or - * none). This supports retrieval of sequence features stored on the sequence - * (as in the applet) or on the dataset sequence (as in the Desktop version). + * {@inheritDoc} * * @return */ @Override - public SequenceFeature[] getSequenceFeatures() + public List getSequenceFeatures() { - SequenceFeature[] features = sequenceFeatures; - - SequenceI seq = this; - int count = 0; // failsafe against loop in sequence.datasetsequence... - while (features == null && seq.getDatasetSequence() != null - && count++ < 10) + if (datasetSequence != null) { - seq = seq.getDatasetSequence(); - features = ((Sequence) seq).sequenceFeatures; + return datasetSequence.getSequenceFeatures(); } - return features; + return sequenceFeatureStore.getAllFeatures(); + } + + @Override + public SequenceFeaturesI getFeatures() + { + return datasetSequence != null ? datasetSequence.getFeatures() + : sequenceFeatureStore; } @Override @@@ -544,7 -568,6 +544,7 @@@ { this.sequence = seq.toCharArray(); checkValidRange(); + sequenceChanged(); } @Override @@@ -562,9 -585,7 +562,9 @@@ @Override public char[] getSequence() { - return sequence; + // return sequence; + return sequence == null ? null : Arrays.copyOf(sequence, + sequence.length); } /* @@@ -667,370 -688,58 +667,370 @@@ return this.description; } - /* - * (non-Javadoc) - * - * @see jalview.datamodel.SequenceI#findIndex(int) + /** + * {@inheritDoc} */ @Override public int findIndex(int pos) { - // returns the alignment position for a residue + /* + * use a valid, hopefully nearby, cursor if available + */ + if (isValidCursor(cursor)) + { + return findIndex(pos, cursor); + } + int j = start; int i = 0; - // Rely on end being at least as long as the length of the sequence. + int startColumn = 0; + + /* + * traverse sequence from the start counting gaps; make a note of + * the column of the first residue to save in the cursor + */ while ((i < sequence.length) && (j <= end) && (j <= pos)) { - if (!jalview.util.Comparison.isGap(sequence[i])) + if (!Comparison.isGap(sequence[i])) { + if (j == start) + { + startColumn = i; + } j++; } i++; } - if ((j == end) && (j < pos)) + if (j == end && j < pos) { return end + 1; } - else + + updateCursor(pos, i, startColumn); + return i; + } + + /** + * Updates the cursor to the latest found residue and column position + * + * @param residuePos + * (start..) + * @param column + * (1..) + * @param startColumn + * column position of the first sequence residue + */ + protected void updateCursor(int residuePos, int column, int startColumn) + { + /* + * preserve end residue column provided cursor was valid + */ + int endColumn = isValidCursor(cursor) ? cursor.lastColumnPosition : 0; + if (residuePos == this.end) { - return i; + endColumn = column; } + + cursor = new SequenceCursor(this, residuePos, column, startColumn, + endColumn, this.changeCount); } + /** + * Answers the aligned column position (1..) for the given residue position + * (start..) given a 'hint' of a residue/column location in the neighbourhood. + * The hint may be left of, at, or to the right of the required position. + * + * @param pos + * @param curs + * @return + */ + protected int findIndex(int pos, SequenceCursor curs) + { + if (!isValidCursor(curs)) + { + /* + * wrong or invalidated cursor, compute de novo + */ + return findIndex(pos); + } + + if (curs.residuePosition == pos) + { + return curs.columnPosition; + } + + /* + * move left or right to find pos from hint.position + */ + int col = curs.columnPosition - 1; // convert from base 1 to 0-based array + // index + int newPos = curs.residuePosition; + int delta = newPos > pos ? -1 : 1; + + while (newPos != pos) + { + col += delta; // shift one column left or right + if (col < 0 || col == sequence.length) + { + break; + } + if (!Comparison.isGap(sequence[col])) + { + newPos += delta; + } + } + + col++; // convert back to base 1 + updateCursor(pos, col, curs.firstColumnPosition); + + return col; + } + + /** + * {@inheritDoc} + */ @Override - public int findPosition(int i) + public int findPosition(final int column) { + /* + * use a valid, hopefully nearby, cursor if available + */ + if (isValidCursor(cursor)) + { + return findPosition(column + 1, cursor); + } + + // TODO recode this more naturally i.e. count residues only + // as they are found, not 'in anticipation' + + /* + * traverse the sequence counting gaps; note the column position + * of the first residue, to save in the cursor + */ + int firstResidueColumn = 0; + int lastPosFound = 0; + int lastPosFoundColumn = 0; + int seqlen = sequence.length; + + if (seqlen > 0 && !Comparison.isGap(sequence[0])) + { + lastPosFound = start; + lastPosFoundColumn = 0; + } + int j = 0; int pos = start; - int seqlen = sequence.length; - while ((j < i) && (j < seqlen)) + + while (j < column && j < seqlen) { - if (!jalview.util.Comparison.isGap(sequence[j])) + if (!Comparison.isGap(sequence[j])) { + lastPosFound = pos; + lastPosFoundColumn = j; + if (pos == this.start) + { + firstResidueColumn = j; + } pos++; } - j++; } + if (j < seqlen && !Comparison.isGap(sequence[j])) + { + lastPosFound = pos; + lastPosFoundColumn = j; + if (pos == this.start) + { + firstResidueColumn = j; + } + } + + /* + * update the cursor to the last residue position found (if any) + * (converting column position to base 1) + */ + if (lastPosFound != 0) + { + updateCursor(lastPosFound, lastPosFoundColumn + 1, + firstResidueColumn + 1); + } return pos; } /** + * Answers true if the given cursor is not null, is for this sequence object, + * and has a token value that matches this object's changeCount, else false. + * This allows us to ignore a cursor as 'stale' if the sequence has been + * modified since the cursor was created. + * + * @param curs + * @return + */ + protected boolean isValidCursor(SequenceCursor curs) + { + if (curs == null || curs.sequence != this || curs.token != changeCount) + { + return false; + } + /* + * sanity check against range + */ + if (curs.columnPosition < 0 || curs.columnPosition > sequence.length) + { + return false; + } + if (curs.residuePosition < start || curs.residuePosition > end) + { + return false; + } + return true; + } + + /** + * Answers the sequence position (start..) for the given aligned column + * position (1..), given a hint of a cursor in the neighbourhood. The cursor + * may lie left of, at, or to the right of the column position. + * + * @param col + * @param curs + * @return + */ + protected int findPosition(final int col, SequenceCursor curs) + { + if (!isValidCursor(curs)) + { + /* + * wrong or invalidated cursor, compute de novo + */ + return findPosition(col - 1);// ugh back to base 0 + } + + if (curs.columnPosition == col) + { + cursor = curs; // in case this method becomes public + return curs.residuePosition; // easy case :-) + } + + if (curs.lastColumnPosition > 0 && curs.lastColumnPosition < col) + { + /* + * sequence lies entirely to the left of col + * - return last residue + 1 + */ + return end + 1; + } + + if (curs.firstColumnPosition > 0 && curs.firstColumnPosition > col) + { + /* + * sequence lies entirely to the right of col + * - return first residue + */ + return start; + } + + // todo could choose closest to col out of column, + // firstColumnPosition, lastColumnPosition as a start point + + /* + * move left or right to find pos from cursor position + */ + int firstResidueColumn = curs.firstColumnPosition; + int column = curs.columnPosition - 1; // to base 0 + int newPos = curs.residuePosition; + int delta = curs.columnPosition > col ? -1 : 1; + boolean gapped = false; + int lastFoundPosition = curs.residuePosition; + int lastFoundPositionColumn = curs.columnPosition; + + while (column != col - 1) + { + column += delta; // shift one column left or right + if (column < 0 || column == sequence.length) + { + break; + } + gapped = Comparison.isGap(sequence[column]); + if (!gapped) + { + newPos += delta; + lastFoundPosition = newPos; + lastFoundPositionColumn = column + 1; + if (lastFoundPosition == this.start) + { + firstResidueColumn = column + 1; + } + } + } + + if (cursor == null || lastFoundPosition != cursor.residuePosition) + { + updateCursor(lastFoundPosition, lastFoundPositionColumn, + firstResidueColumn); + } + + /* + * hack to give position to the right if on a gap + * or beyond the length of the sequence (see JAL-2562) + */ + if (delta > 0 && (gapped || column >= sequence.length)) + { + newPos++; + } + + return newPos; + } + + /** + * {@inheritDoc} + */ + @Override + public Range findPositions(int fromColumn, int toColumn) + { + if (toColumn < fromColumn || fromColumn < 1) + { + return null; + } + + /* + * find the first non-gapped position, if any + */ + int firstPosition = 0; + int col = fromColumn - 1; + int length = sequence.length; + while (col < length && col < toColumn) + { + if (!Comparison.isGap(sequence[col])) + { + firstPosition = findPosition(col++); + break; + } + col++; + } + + if (firstPosition == 0) + { + return null; + } + + /* + * find the last non-gapped position + */ + int lastPosition = firstPosition; + while (col < length && col < toColumn) + { + if (!Comparison.isGap(sequence[col++])) + { + lastPosition++; + } + } + + return new Range(firstPosition, lastPosition); + } + + /** * Returns an int array where indices correspond to each residue in the * sequence and the element value gives its position in the alignment * @@@ -1220,7 -929,6 +1220,7 @@@ start = newstart; end = newend; sequence = tmp; + sequenceChanged(); } @Override @@@ -1251,7 -959,6 +1251,7 @@@ } sequence = tmp; + sequenceChanged(); } @Override @@@ -1364,8 -1071,9 +1364,9 @@@ @Override public AlignmentAnnotation[] getAnnotation() { - return annotation == null ? null : annotation - .toArray(new AlignmentAnnotation[annotation.size()]); + return annotation == null ? null + : annotation + .toArray(new AlignmentAnnotation[annotation.size()]); } @Override @@@ -1446,7 -1154,7 +1447,7 @@@ private boolean _isNa; - private long _seqhash = 0; + private int _seqhash = 0; /** * Answers false if the sequence is more than 85% nucleotide (ACGTU), else @@@ -1477,16 -1185,17 +1478,17 @@@ { if (datasetSequence == null) { - Sequence dsseq = new Sequence(getName(), AlignSeq.extractGaps( - jalview.util.Comparison.GapChars, getSequenceAsString()), + Sequence dsseq = new Sequence(getName(), + AlignSeq.extractGaps(jalview.util.Comparison.GapChars, + getSequenceAsString()), getStart(), getEnd()); datasetSequence = dsseq; dsseq.setDescription(description); // move features and database references onto dataset sequence - dsseq.sequenceFeatures = sequenceFeatures; - sequenceFeatures = null; + dsseq.sequenceFeatureStore = sequenceFeatureStore; + sequenceFeatureStore = null; dsseq.dbrefs = dbrefs; dbrefs = null; // TODO: search and replace any references to this sequence with @@@ -1545,11 -1254,11 +1547,11 @@@ return null; } - Vector subset = new Vector(); - Enumeration e = annotation.elements(); + Vector subset = new Vector(); + Enumeration e = annotation.elements(); while (e.hasMoreElements()) { - AlignmentAnnotation ann = (AlignmentAnnotation) e.nextElement(); + AlignmentAnnotation ann = e.nextElement(); if (ann.label != null && ann.label.equals(label)) { subset.addElement(ann); @@@ -1564,7 -1273,7 +1566,7 @@@ e = subset.elements(); while (e.hasMoreElements()) { - anns[i++] = (AlignmentAnnotation) e.nextElement(); + anns[i++] = e.nextElement(); } subset.removeAllElements(); return anns; @@@ -1617,12 -1326,13 +1619,12 @@@ if (entry.getSequenceFeatures() != null) { - SequenceFeature[] sfs = entry.getSequenceFeatures(); - for (int si = 0; si < sfs.length; si++) + List sfs = entry.getSequenceFeatures(); + for (SequenceFeature feature : sfs) { - SequenceFeature sf[] = (mp != null) ? mp.locateFeature(feature) - SequenceFeature sf[] = (mp != null) ? mp.locateFeature(sfs[si]) - : new SequenceFeature[] - { new SequenceFeature(sfs[si]) }; - if (sf != null && sf.length > 0) ++ SequenceFeature sf[] = (mp != null) ? mp.locateFeature(feature) + : new SequenceFeature[] { new SequenceFeature(feature) }; + if (sf != null) { for (int sfi = 0; sfi < sf.length; sfi++) { @@@ -1635,10 -1345,10 +1637,10 @@@ // transfer PDB entries if (entry.getAllPDBEntries() != null) { - Enumeration e = entry.getAllPDBEntries().elements(); + Enumeration e = entry.getAllPDBEntries().elements(); while (e.hasMoreElements()) { - PDBEntry pdb = (PDBEntry) e.nextElement(); + PDBEntry pdb = e.nextElement(); addPDBId(pdb); } } @@@ -1777,8 -1487,8 +1779,8 @@@ } } // whilst it looks like it is a primary ref, we also sanity check type - if (DBRefUtils.getCanonicalName(DBRefSource.PDB).equals( - DBRefUtils.getCanonicalName(ref.getSource()))) + if (DBRefUtils.getCanonicalName(DBRefSource.PDB) + .equals(DBRefUtils.getCanonicalName(ref.getSource()))) { // PDB dbrefs imply there should be a PDBEntry associated // TODO: tighten PDB dbrefs @@@ -1806,97 -1516,4 +1808,97 @@@ } } + /** + * {@inheritDoc} + */ + @Override + public List findFeatures(int fromColumn, int toColumn, + String... types) + { + int startPos = findPosition(fromColumn - 1); // convert base 1 to base 0 + int endPos = fromColumn == toColumn ? startPos + : findPosition(toColumn - 1); + + List result = getFeatures().findFeatures(startPos, + endPos, types); + + /* + * if end column is gapped, endPos may be to the right, + * and we may have included adjacent or enclosing features; + * remove any that are not enclosing, non-contact features + */ + if (endPos > this.end || Comparison.isGap(sequence[toColumn - 1])) + { + ListIterator it = result.listIterator(); + while (it.hasNext()) + { + SequenceFeature sf = it.next(); + int sfBegin = sf.getBegin(); + int sfEnd = sf.getEnd(); + int featureStartColumn = findIndex(sfBegin); + if (featureStartColumn > toColumn) + { + it.remove(); + } + else if (featureStartColumn < fromColumn) + { + int featureEndColumn = sfEnd == sfBegin ? featureStartColumn + : findIndex(sfEnd); + if (featureEndColumn < fromColumn) + { + it.remove(); + } + else if (featureEndColumn > toColumn && sf.isContactFeature()) + { + /* + * remove an enclosing feature if it is a contact feature + */ + it.remove(); + } + } + } + } + + return result; + } + + /** + * Invalidates any stale cursors (forcing recalculation) by incrementing the + * token that has to match the one presented by the cursor + */ + @Override + public void sequenceChanged() + { + changeCount++; + } + + /** + * {@inheritDoc} + */ + @Override + public int replace(char c1, char c2) + { + if (c1 == c2) + { + return 0; + } + int count = 0; + synchronized (sequence) + { + for (int c = 0; c < sequence.length; c++) + { + if (sequence[c] == c1) + { + sequence[c] = c2; + count++; + } + } + } + if (count > 0) + { + sequenceChanged(); + } + + return count; + } } diff --combined src/jalview/datamodel/SequenceFeature.java index ba7412c,71732aa..9c4087e --- a/src/jalview/datamodel/SequenceFeature.java +++ b/src/jalview/datamodel/SequenceFeature.java @@@ -20,11 -20,8 +20,11 @@@ */ package jalview.datamodel; +import jalview.datamodel.features.FeatureLocationI; + import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; import java.util.Vector; /** @@@ -33,14 -30,8 +33,14 @@@ * @author $author$ * @version $Revision$ */ -public class SequenceFeature +public class SequenceFeature implements FeatureLocationI { + /* + * score value if none is set; preferably Float.Nan, but see + * JAL-2060 and JAL-2554 for a couple of blockers to that + */ + private static final float NO_SCORE = 0f; + private static final String STATUS = "status"; private static final String STRAND = "STRAND"; @@@ -57,22 -48,13 +57,22 @@@ */ private static final String ATTRIBUTES = "ATTRIBUTES"; - public int begin; + /* + * type, begin, end, featureGroup, score and contactFeature are final + * to ensure that the integrity of SequenceFeatures data store + * can't be broken by direct update of these fields + */ + public final String type; - public int end; + public final int begin; - public float score; + public final int end; - public String type; + public final String featureGroup; + + public final float score; + + private final boolean contactFeature; public String description; @@@ -84,6 -66,14 +84,6 @@@ public Vector links; - // Feature group can be set from a features file - // as a group of features between STARTGROUP and ENDGROUP markers - public String featureGroup; - - public SequenceFeature() - { - } - /** * Constructs a duplicate feature. Note: Uses makes a shallow copy of the * otherDetails map, so the new and original SequenceFeature may reference the @@@ -93,99 -83,96 +93,99 @@@ */ public SequenceFeature(SequenceFeature cpy) { - if (cpy != null) - { - begin = cpy.begin; - end = cpy.end; - score = cpy.score; - if (cpy.type != null) - { - type = new String(cpy.type); - } - if (cpy.description != null) - { - description = new String(cpy.description); - } - if (cpy.featureGroup != null) - { - featureGroup = new String(cpy.featureGroup); - } - if (cpy.otherDetails != null) - { - try - { - otherDetails = (Map) ((HashMap) cpy.otherDetails) - .clone(); - } catch (Exception e) - { - // ignore - } - } - if (cpy.links != null && cpy.links.size() > 0) - { - links = new Vector(); - for (int i = 0, iSize = cpy.links.size(); i < iSize; i++) - { - links.addElement(cpy.links.elementAt(i)); - } - } - } + this(cpy, cpy.getBegin(), cpy.getEnd(), cpy.getFeatureGroup(), cpy + .getScore()); } /** - * Constructor including a Status value + * Constructor * - * @param type - * @param desc - * @param status - * @param begin - * @param end - * @param featureGroup + * @param theType + * @param theDesc + * @param theBegin + * @param theEnd + * @param group */ - public SequenceFeature(String type, String desc, String status, int begin, - int end, String featureGroup) + public SequenceFeature(String theType, String theDesc, int theBegin, + int theEnd, String group) { - this(type, desc, begin, end, featureGroup); - setStatus(status); + this(theType, theDesc, theBegin, theEnd, NO_SCORE, group); } /** - * Constructor + * Constructor including a score value * - * @param type - * @param desc - * @param begin - * @param end - * @param featureGroup + * @param theType + * @param theDesc + * @param theBegin + * @param theEnd + * @param theScore + * @param group */ - SequenceFeature(String type, String desc, int begin, int end, - String featureGroup) + public SequenceFeature(String theType, String theDesc, int theBegin, + int theEnd, float theScore, String group) { - this.type = type; - this.description = desc; - this.begin = begin; - this.end = end; - this.featureGroup = featureGroup; + this.type = theType; + this.description = theDesc; + this.begin = theBegin; + this.end = theEnd; + this.featureGroup = group; + this.score = theScore; + + /* + * for now, only "Disulfide/disulphide bond" is treated as a contact feature + */ + this.contactFeature = "disulfide bond".equalsIgnoreCase(type) + || "disulphide bond".equalsIgnoreCase(type); } /** - * Constructor including a score value + * A copy constructor that allows the value of final fields to be 'modified' + * + * @param sf + * @param newType + * @param newBegin + * @param newEnd + * @param newGroup + * @param newScore + */ + public SequenceFeature(SequenceFeature sf, String newType, int newBegin, + int newEnd, String newGroup, float newScore) + { + this(newType, sf.getDescription(), newBegin, newEnd, newScore, + newGroup); + + if (sf.otherDetails != null) + { + otherDetails = new HashMap(); + for (Entry entry : sf.otherDetails.entrySet()) + { + otherDetails.put(entry.getKey(), entry.getValue()); + } + } + if (sf.links != null && sf.links.size() > 0) + { + links = new Vector(); + for (int i = 0, iSize = sf.links.size(); i < iSize; i++) + { + links.addElement(sf.links.elementAt(i)); + } + } + } + + /** + * A copy constructor that allows the value of final fields to be 'modified' * - * @param type - * @param desc - * @param begin - * @param end - * @param score - * @param featureGroup + * @param sf + * @param newBegin + * @param newEnd + * @param newGroup + * @param newScore */ - public SequenceFeature(String type, String desc, int begin, int end, - float score, String featureGroup) + public SequenceFeature(SequenceFeature sf, int newBegin, int newEnd, + String newGroup, float newScore) { - this(type, desc, begin, end, featureGroup); - this.score = score; + this(sf, sf.getType(), newBegin, newEnd, newGroup, newScore); } /** @@@ -233,8 -220,8 +233,8 @@@ return false; } - if (!(type + description + featureGroup + getPhase()).equals(sf.type - + sf.description + sf.featureGroup + sf.getPhase())) + if (!(type + description + featureGroup + getPhase()).equals( + sf.type + sf.description + sf.featureGroup + sf.getPhase())) { return false; } @@@ -281,23 -268,31 +281,23 @@@ * * @return DOCUMENT ME! */ + @Override public int getBegin() { return begin; } - public void setBegin(int start) - { - this.begin = start; - } - /** * DOCUMENT ME! * * @return DOCUMENT ME! */ + @Override public int getEnd() { return end; } - public void setEnd(int end) - { - this.end = end; - } - /** * DOCUMENT ME! * @@@ -308,6 -303,11 +308,6 @@@ return type; } - public void setType(String type) - { - this.type = type; - } - /** * DOCUMENT ME! * @@@ -328,6 -328,11 +328,6 @@@ return featureGroup; } - public void setFeatureGroup(String featureGroup) - { - this.featureGroup = featureGroup; - } - public void addLink(String labelLink) { if (links == null) @@@ -335,10 -340,7 +335,10 @@@ links = new Vector(); } - links.insertElementAt(labelLink, 0); + if (!links.contains(labelLink)) + { + links.insertElementAt(labelLink, 0); + } } public float getScore() @@@ -346,6 -348,11 +346,6 @@@ return score; } - public void setScore(float value) - { - score = value; - } - /** * Used for getting values which are not in the basic set. eg STRAND, PHASE * for GFF file @@@ -425,6 -432,17 +425,6 @@@ return (String) getValue(ATTRIBUTES); } - public void setPosition(int pos) - { - begin = pos; - end = pos; - } - - public int getPosition() - { - return begin; - } - /** * Return 1 for forward strand ('+' in GFF), -1 for reverse strand ('-' in * GFF), and 0 for unknown or not (validly) specified @@@ -520,19 -538,14 +520,19 @@@ * positions, rather than ends of a range. Such features may be visualised or * reported differently to features on a range. */ + @Override public boolean isContactFeature() { - // TODO abstract one day to a FeatureType class - if ("disulfide bond".equalsIgnoreCase(type) - || "disulphide bond".equalsIgnoreCase(type)) - { - return true; - } - return false; + return contactFeature; + } + + /** + * Answers true if the sequence has zero start and end position + * + * @return + */ + public boolean isNonPositional() + { + return begin == 0 && end == 0; } } diff --combined src/jalview/datamodel/xdb/embl/EmblEntry.java index 5784f04,fe3f6ef..8cc81d9 --- a/src/jalview/datamodel/xdb/embl/EmblEntry.java +++ b/src/jalview/datamodel/xdb/embl/EmblEntry.java @@@ -191,13 -191,15 +191,15 @@@ public class EmblEntr return null; } dna.setDescription(description); - DBRefEntry retrievedref = new DBRefEntry(sourceDb, - getSequenceVersion(), accession); + DBRefEntry retrievedref = new DBRefEntry(sourceDb, getSequenceVersion(), + accession); dna.addDBRef(retrievedref); // add map to indicate the sequence is a valid coordinate frame for the // dbref - retrievedref.setMap(new Mapping(null, new int[] { 1, dna.getLength() }, - new int[] { 1, dna.getLength() }, 1, 1)); + retrievedref + .setMap(new Mapping(null, new int[] + { 1, dna.getLength() }, new int[] { 1, dna.getLength() }, 1, + 1)); /* * transform EMBL Database refs to canonical form @@@ -242,8 -244,8 +244,8 @@@ { if (sequence == null) { - System.err.println("No sequence was returned for ENA accession " - + accession); + System.err.println( + "No sequence was returned for ENA accession " + accession); return null; } SequenceI dna = new Sequence(sourceDb + "|" + accession, @@@ -267,7 -269,8 +269,8 @@@ * helper to match xrefs in already retrieved sequences */ void parseCodingFeature(EmblFeature feature, String sourceDb, - SequenceI dna, List peptides, SequenceIdMatcher matcher) + SequenceI dna, List peptides, + SequenceIdMatcher matcher) { boolean isEmblCdna = sourceDb.equals(DBRefSource.EMBLCDS); @@@ -296,8 -299,8 +299,8 @@@ if (qname.equals("translation")) { // remove all spaces (precompiled String.replaceAll(" ", "")) - translation = SPACE_PATTERN.matcher(q.getValues()[0]).replaceAll( - ""); + translation = SPACE_PATTERN.matcher(q.getValues()[0]) + .replaceAll(""); } else if (qname.equals("protein_id")) { @@@ -310,8 -313,8 +313,8 @@@ codonStart = Integer.parseInt(q.getValues()[0].trim()); } catch (NumberFormatException e) { - System.err.println("Invalid codon_start in XML for " - + accession + ": " + e.getMessage()); + System.err.println("Invalid codon_start in XML for " + accession + + ": " + e.getMessage()); } } else if (qname.equals("product")) @@@ -348,9 -351,10 +351,10 @@@ product = matcher.findIdMatch(proteinId); if (product == null) { - product = new Sequence(proteinId, translation, 1, translationLength); - product.setDescription(((proteinName.length() == 0) ? "Protein Product from " - + sourceDb + product = new Sequence(proteinId, translation, 1, + translationLength); + product.setDescription(((proteinName.length() == 0) + ? "Protein Product from " + sourceDb : proteinName)); peptides.add(product); matcher.add(product); @@@ -364,28 -368,31 +368,30 @@@ * workaround until we handle dna location for CDS sequence * e.g. location="X53828.1:60..1058" correctly */ - System.err - .println("Implementation Notice: EMBLCDS records not properly supported yet - Making up the CDNA region of this sequence... may be incorrect (" + System.err.println( + "Implementation Notice: EMBLCDS records not properly supported yet - Making up the CDNA region of this sequence... may be incorrect (" + sourceDb + ":" + getAccession() + ")"); - if (translationLength - * 3 == (1 - codonStart + dna.getSequence().length)) + int dnaLength = dna.getLength(); + if (translationLength * 3 == (1 - codonStart + dnaLength)) { - System.err - .println("Not allowing for additional stop codon at end of cDNA fragment... !"); + System.err.println( + "Not allowing for additional stop codon at end of cDNA fragment... !"); // this might occur for CDS sequences where no features are marked exons = new int[] { dna.getStart() + (codonStart - 1), dna.getEnd() }; - dnaToProteinMapping = new Mapping(product, exons, new int[] { 1, - translationLength }, 3, 1); + dnaToProteinMapping = new Mapping(product, exons, + new int[] + { 1, translationLength }, 3, 1); } - if ((translationLength + 1) - * 3 == (1 - codonStart + dna.getSequence().length)) + if ((translationLength + 1) * 3 == (1 - codonStart + dnaLength)) { - System.err - .println("Allowing for additional stop codon at end of cDNA fragment... will probably cause an error in VAMSAs!"); + System.err.println( + "Allowing for additional stop codon at end of cDNA fragment... will probably cause an error in VAMSAs!"); exons = new int[] { dna.getStart() + (codonStart - 1), dna.getEnd() - 3 }; - dnaToProteinMapping = new Mapping(product, exons, new int[] { 1, - translationLength }, 3, 1); + dnaToProteinMapping = new Mapping(product, exons, + new int[] + { 1, translationLength }, 3, 1); } } else @@@ -404,26 -411,32 +410,32 @@@ else { // final product length truncation check - int[] cdsRanges = adjustForProteinLength(translationLength, exons); - dnaToProteinMapping = new Mapping(product, cdsRanges, new int[] { - 1, translationLength }, 3, 1); + int[] cdsRanges = adjustForProteinLength(translationLength, + exons); + dnaToProteinMapping = new Mapping(product, cdsRanges, + new int[] + { 1, translationLength }, 3, 1); if (product != null) { /* * make xref with mapping from protein to EMBL dna */ DBRefEntry proteinToEmblRef = new DBRefEntry(DBRefSource.EMBL, - getSequenceVersion(), proteinId, new Mapping( - dnaToProteinMapping.getMap().getInverse())); + getSequenceVersion(), proteinId, + new Mapping(dnaToProteinMapping.getMap().getInverse())); product.addDBRef(proteinToEmblRef); /* * make xref from protein to EMBLCDS; we assume here that the * CDS sequence version is same as dna sequence (?!) */ - MapList proteinToCdsMapList = new MapList(new int[] { 1, - translationLength }, new int[] { 1 + (codonStart - 1), - (codonStart - 1) + 3 * translationLength }, 1, 3); + MapList proteinToCdsMapList = new MapList( + new int[] + { 1, translationLength }, + new int[] + { 1 + (codonStart - 1), + (codonStart - 1) + 3 * translationLength }, + 1, 3); DBRefEntry proteinToEmblCdsRef = new DBRefEntry( DBRefSource.EMBLCDS, getSequenceVersion(), proteinId, new Mapping(proteinToCdsMapList)); @@@ -443,27 -456,13 +455,27 @@@ /* * add cds features to dna sequence */ - for (int xint = 0; exons != null && xint < exons.length; xint += 2) + String cds = feature.getName(); // "CDS" + for (int xint = 0; exons != null && xint < exons.length - 1; xint += 2) { - SequenceFeature sf = makeCdsFeature(exons, xint, proteinName, - proteinId, vals, codonStart); - sf.setType(feature.getName()); // "CDS" + int exonStart = exons[xint]; + int exonEnd = exons[xint + 1]; + int begin = Math.min(exonStart, exonEnd); + int end = Math.max(exonStart, exonEnd); + int exonNumber = xint / 2 + 1; + String desc = String.format("Exon %d for protein '%s' EMBLCDS:%s", + exonNumber, proteinName, proteinId); + + SequenceFeature sf = makeCdsFeature(cds, desc, begin, end, + sourceDb, vals); + sf.setEnaLocation(feature.getLocation()); - sf.setFeatureGroup(sourceDb); + boolean forwardStrand = exonStart <= exonEnd; + sf.setStrand(forwardStrand ? "+" : "-"); + sf.setPhase(String.valueOf(codonStart - 1)); + sf.setValue(FeatureProperties.EXONPOS, exonNumber); + sf.setValue(FeatureProperties.EXONPRODUCT, proteinName); + dna.addSequenceFeature(sf); } } @@@ -532,8 -531,8 +544,8 @@@ // Add converse mapping reference if (dnaToProteinMapping != null) { - Mapping pmap = new Mapping(dna, dnaToProteinMapping.getMap() - .getInverse()); + Mapping pmap = new Mapping(dna, + dnaToProteinMapping.getMap().getInverse()); pref = new DBRefEntry(sourceDb, getSequenceVersion(), this.getAccession()); pref.setMap(pmap); @@@ -557,8 -556,8 +569,8 @@@ if (proteinToEmblProteinRef == null) { // assuming CDSPROTEIN sequence version = dna version (?!) - proteinToEmblProteinRef = new DBRefEntry( - DBRefSource.EMBLCDSProduct, getSequenceVersion(), proteinId); + proteinToEmblProteinRef = new DBRefEntry(DBRefSource.EMBLCDSProduct, + getSequenceVersion(), proteinId); } product.addDBRef(proteinToEmblProteinRef); @@@ -566,7 -565,8 +578,8 @@@ && dnaToProteinMapping.getTo() != null) { DBRefEntry dnaToEmblProteinRef = new DBRefEntry( - DBRefSource.EMBLCDSProduct, getSequenceVersion(), proteinId); + DBRefSource.EMBLCDSProduct, getSequenceVersion(), + proteinId); dnaToEmblProteinRef.setMap(dnaToProteinMapping); dnaToProteinMapping.setMappedFromId(proteinId); dna.addDBRef(dnaToEmblProteinRef); @@@ -577,25 -577,33 +590,24 @@@ /** * Helper method to construct a SequenceFeature for one cds range * - * @param exons - * array of cds [start, end, ...] positions - * @param exonStartIndex - * offset into the exons array - * @param proteinName - * @param proteinAccessionId + * @param type + * feature type ("CDS") + * @param desc + * description + * @param begin + * start position + * @param end + * end position + * @param group + * feature group * @param vals * map of 'miscellaneous values' for feature - * @param codonStart - * codon start position for CDS (1/2/3, normally 1) * @return */ - protected SequenceFeature makeCdsFeature(int[] exons, int exonStartIndex, - String proteinName, String proteinAccessionId, - Map vals, int codonStart) + protected SequenceFeature makeCdsFeature(String type, String desc, + int begin, int end, String group, Map vals) { - int exonNumber = exonStartIndex / 2 + 1; - SequenceFeature sf = new SequenceFeature(); - sf.setBegin(Math.min(exons[exonStartIndex], exons[exonStartIndex + 1])); - sf.setEnd(Math.max(exons[exonStartIndex], exons[exonStartIndex + 1])); - sf.setDescription(String.format("Exon %d for protein '%s' EMBLCDS:%s", - exonNumber, proteinName, proteinAccessionId)); - sf.setPhase(String.valueOf(codonStart - 1)); - sf.setStrand( - exons[exonStartIndex] <= exons[exonStartIndex + 1] ? "+" : "-"); - sf.setValue(FeatureProperties.EXONPOS, exonNumber); - sf.setValue(FeatureProperties.EXONPRODUCT, proteinName); + SequenceFeature sf = new SequenceFeature(type, desc, begin, end, group); - if (!vals.isEmpty()) { StringBuilder sb = new StringBuilder(); @@@ -635,9 -643,9 +647,9 @@@ return listToArray(ranges); } catch (ParseException e) { - Cache.log.warn(String.format( - "Not parsing inexact CDS location %s in ENA %s", - feature.location, this.accession)); + Cache.log.warn( + String.format("Not parsing inexact CDS location %s in ENA %s", + feature.location, this.accession)); return new int[] {}; } } diff --combined src/jalview/ext/ensembl/EnsemblGene.java index 915fa0a,edeeedd..365c1c2 --- a/src/jalview/ext/ensembl/EnsemblGene.java +++ b/src/jalview/ext/ensembl/EnsemblGene.java @@@ -26,7 -26,6 +26,7 @@@ import jalview.datamodel.AlignmentI import jalview.datamodel.Sequence; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; +import jalview.datamodel.features.SequenceFeatures; import jalview.io.gff.SequenceOntologyFactory; import jalview.io.gff.SequenceOntologyI; import jalview.schemes.FeatureColour; @@@ -110,7 -109,8 +110,8 @@@ public class EnsemblGene extends Ensemb *
  • resolves an external identifier by looking up xref-ed gene ids
  • *
  • fetches the gene sequence
  • *
  • fetches features on the sequence
  • - *
  • identifies "transcript" features whose Parent is the requested gene
  • + *
  • identifies "transcript" features whose Parent is the requested + * gene
  • *
  • fetches the transcript sequence for each transcript
  • *
  • makes a mapping from the gene to each transcript
  • *
  • copies features from gene to transcript sequences
  • @@@ -283,20 -283,22 +284,20 @@@ */ protected void clearGeneFeatures(SequenceI gene) { - SequenceFeature[] sfs = gene.getSequenceFeatures(); - if (sfs != null) + /* + * Note we include NMD_transcript_variant here because it behaves like + * 'transcript' in Ensembl, although strictly speaking it is not + * (it is a sub-type of sequence_variant) + */ + String[] soTerms = new String[] { + SequenceOntologyI.NMD_TRANSCRIPT_VARIANT, + SequenceOntologyI.TRANSCRIPT, SequenceOntologyI.EXON, + SequenceOntologyI.CDS }; + List sfs = gene.getFeatures().getFeaturesByOntology( + soTerms); + for (SequenceFeature sf : sfs) { - SequenceOntologyI so = SequenceOntologyFactory.getInstance(); - List filtered = new ArrayList(); - for (SequenceFeature sf : sfs) - { - String type = sf.getType(); - if (!isTranscript(type) && !so.isA(type, SequenceOntologyI.EXON) - && !so.isA(type, SequenceOntologyI.CDS)) - { - filtered.add(sf); - } - } - gene.setSequenceFeatures( - filtered.toArray(new SequenceFeature[filtered.size()])); + gene.deleteFeature(sf); } } @@@ -313,8 -315,8 +314,8 @@@ * the parent gene sequence, with features * @return */ - SequenceI makeTranscript(SequenceFeature transcriptFeature, - AlignmentI al, SequenceI gene) + SequenceI makeTranscript(SequenceFeature transcriptFeature, AlignmentI al, + SequenceI gene) { String accId = getTranscriptId(transcriptFeature); if (accId == null) @@@ -346,7 -348,6 +347,7 @@@ { splices = findFeatures(gene, SequenceOntologyI.CDS, parentId); } + SequenceFeatures.sortFeatures(splices, true); int transcriptLength = 0; final char[] geneChars = gene.getSequence(); @@@ -363,7 -364,8 +364,8 @@@ mappedFrom.add(new int[] { sf.getBegin(), sf.getEnd() }); } - Sequence transcript = new Sequence(accId, seqChars, 1, transcriptLength); + Sequence transcript = new Sequence(accId, seqChars, 1, + transcriptLength); /* * Ensembl has gene name as transcript Name @@@ -396,7 -398,7 +398,7 @@@ mapTo.add(new int[] { 1, transcriptLength }); MapList mapping = new MapList(mappedFrom, mapTo, 1, 1); EnsemblCdna cdna = new EnsemblCdna(getDomain()); - cdna.transferFeatures(gene.getSequenceFeatures(), + cdna.transferFeatures(gene.getFeatures().getPositionalFeatures(), transcript.getDatasetSequence(), mapping, parentId); /* @@@ -437,18 -439,19 +439,18 @@@ List transcriptFeatures = new ArrayList(); String parentIdentifier = GENE_PREFIX + accId; - SequenceFeature[] sfs = geneSequence.getSequenceFeatures(); + // todo optimise here by transcript type! + List sfs = geneSequence.getFeatures() + .getPositionalFeatures(); - if (sfs != null) + for (SequenceFeature sf : sfs) { - for (SequenceFeature sf : sfs) + if (isTranscript(sf.getType())) { - if (isTranscript(sf.getType())) + String parent = (String) sf.getValue(PARENT); + if (parentIdentifier.equals(parent)) { - String parent = (String) sf.getValue(PARENT); - if (parentIdentifier.equals(parent)) - { - transcriptFeatures.add(sf); - } + transcriptFeatures.add(sf); } } } @@@ -566,8 -569,8 +568,8 @@@ @Override public boolean isFeatureDisplayed(String type) { - return (so.isA(type, SequenceOntologyI.EXON) || so.isA(type, - SequenceOntologyI.SEQUENCE_VARIANT)); + return (so.isA(type, SequenceOntologyI.EXON) + || so.isA(type, SequenceOntologyI.SEQUENCE_VARIANT)); } @Override diff --combined src/jalview/ext/ensembl/EnsemblSeqProxy.java index 79d6c0a,16b858a..4da4f15 --- a/src/jalview/ext/ensembl/EnsemblSeqProxy.java +++ b/src/jalview/ext/ensembl/EnsemblSeqProxy.java @@@ -30,7 -30,6 +30,7 @@@ import jalview.datamodel.DBRefSource import jalview.datamodel.Mapping; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; +import jalview.datamodel.features.SequenceFeatures; import jalview.exceptions.JalviewException; import jalview.io.FastaFile; import jalview.io.FileParse; @@@ -38,8 -37,8 +38,8 @@@ import jalview.io.gff.SequenceOntologyF import jalview.io.gff.SequenceOntologyI; import jalview.util.Comparison; import jalview.util.DBRefUtils; +import jalview.util.IntRangeComparator; import jalview.util.MapList; -import jalview.util.RangeComparator; import java.io.IOException; import java.net.MalformedURLException; @@@ -47,9 -46,8 +47,9 @@@ import java.net.URL import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.Comparator; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; /** * Base class for Ensembl sequence fetchers @@@ -139,8 -137,8 +139,8 @@@ public abstract class EnsemblSeqProxy e // danger: accession separator used as a regex here, a string elsewhere // in this case it is ok (it is just a space), but (e.g.) '\' would not be - List allIds = Arrays.asList(query - .split(getAccessionSeparator())); + List allIds = Arrays + .asList(query.split(getAccessionSeparator())); AlignmentI alignment = null; inProgress = true; @@@ -238,8 -236,8 +238,8 @@@ } } catch (IOException e) { - System.err.println("Error transferring Ensembl features: " - + e.getMessage()); + System.err.println( + "Error transferring Ensembl features: " + e.getMessage()); } } @@@ -277,8 -275,8 +277,8 @@@ proteinSeq.createDatasetSequence(); querySeq.createDatasetSequence(); - MapList mapList = AlignmentUtils - .mapCdsToProtein(querySeq, proteinSeq); + MapList mapList = AlignmentUtils.mapCdsToProtein(querySeq, + proteinSeq); if (mapList != null) { // clunky: ensure Uniprot xref if we have one is on mapped sequence @@@ -289,9 -287,11 +289,11 @@@ getEnsemblDataVersion(), proteinSeq.getName(), map); querySeq.getDatasetSequence().addDBRef(dbr); DBRefEntry[] uprots = DBRefUtils.selectRefs(ds.getDBRefs(), - new String[] { DBRefSource.UNIPROT }); + new String[] + { DBRefSource.UNIPROT }); DBRefEntry[] upxrefs = DBRefUtils.selectRefs(querySeq.getDBRefs(), - new String[] { DBRefSource.UNIPROT }); + new String[] + { DBRefSource.UNIPROT }); if (uprots != null) { for (DBRefEntry up : uprots) @@@ -306,8 -306,8 +308,8 @@@ if (upx.size() > 1) { - Cache.log - .warn("Implementation issue - multiple uniprot acc on product sequence."); + Cache.log.warn( + "Implementation issue - multiple uniprot acc on product sequence."); } } else @@@ -332,8 -332,8 +334,8 @@@ * copy exon features to protein, compute peptide variants from dna * variants and add as features on the protein sequence ta-da */ - AlignmentUtils - .computeProteinFeatures(querySeq, proteinSeq, mapList); + AlignmentUtils.computeProteinFeatures(querySeq, proteinSeq, + mapList); } } catch (Exception e) { @@@ -366,8 -366,8 +368,8 @@@ /* * and add a reference to itself */ - DBRefEntry self = new DBRefEntry(getDbSource(), - getEnsemblDataVersion(), seq.getName()); + DBRefEntry self = new DBRefEntry(getDbSource(), getEnsemblDataVersion(), + seq.getName()); seq.addDBRef(self); } @@@ -381,8 -381,8 +383,8 @@@ * @throws JalviewException * @throws IOException */ - protected AlignmentI fetchSequences(List ids, AlignmentI alignment) - throws JalviewException, IOException + protected AlignmentI fetchSequences(List ids, + AlignmentI alignment) throws JalviewException, IOException { if (!isEnsemblAvailable()) { @@@ -398,15 -398,15 +400,15 @@@ FastaFile fr = new FastaFile(fp); if (fr.hasWarningMessage()) { - System.out.println(String.format( - "Warning when retrieving %d ids %s\n%s", ids.size(), - ids.toString(), fr.getWarningMessage())); + System.out.println( + String.format("Warning when retrieving %d ids %s\n%s", + ids.size(), ids.toString(), fr.getWarningMessage())); } else if (fr.getSeqs().size() != ids.size()) { System.out.println(String.format( - "Only retrieved %d sequences for %d query strings", fr - .getSeqs().size(), ids.size())); + "Only retrieved %d sequences for %d query strings", + fr.getSeqs().size(), ids.size())); } if (fr.getSeqs().size() == 1 && fr.getSeqs().get(0).getLength() == 0) @@@ -470,31 -470,11 +472,31 @@@ urlstring.append("?type=").append(getSourceEnsemblType().getType()); urlstring.append(("&Accept=text/x-fasta")); + Map params = getAdditionalParameters(); + if (params != null) + { + for (Entry entry : params.entrySet()) + { + urlstring.append("&").append(entry.getKey()).append("=") + .append(entry.getValue()); + } + } + URL url = new URL(urlstring.toString()); return url; } /** + * Override this method to add any additional x=y URL parameters needed + * + * @return + */ + protected Map getAdditionalParameters() + { + return null; + } + + /** * A sequence/id POST request currently allows up to 50 queries * * @see http://rest.ensembl.org/documentation/info/sequence_id_post @@@ -558,10 -538,8 +560,10 @@@ protected MapList getGenomicRangesFromFeatures(SequenceI sourceSequence, String accId, int start) { - SequenceFeature[] sfs = sourceSequence.getSequenceFeatures(); - if (sfs == null) + // SequenceFeature[] sfs = sourceSequence.getSequenceFeatures(); + List sfs = sourceSequence.getFeatures() + .getPositionalFeatures(); + if (sfs.isEmpty()) { return null; } @@@ -589,8 -567,8 +591,8 @@@ if (directionSet && strand != direction) { // abort - mix of forward and backward - System.err.println("Error: forward and backward strand for " - + accId); + System.err.println( + "Error: forward and backward strand for " + accId); return null; } direction = strand; @@@ -631,11 -609,11 +633,12 @@@ * a final sort is needed since Ensembl returns CDS sorted within source * (havana / ensembl_havana) */ - Collections.sort(regions, new RangeComparator(direction == 1)); + Collections.sort(regions, direction == 1 ? IntRangeComparator.ASCENDING + : IntRangeComparator.DESCENDING); - List to = Arrays.asList(new int[] { start, - start + mappedLength - 1 }); + List to = Arrays + .asList(new int[] + { start, start + mappedLength - 1 }); return new MapList(regions, to, 1, 1); } @@@ -683,24 -661,21 +686,23 @@@ if (mappedRange != null) { - SequenceFeature copy = new SequenceFeature(sf); - copy.setBegin(Math.min(mappedRange[0], mappedRange[1])); - copy.setEnd(Math.max(mappedRange[0], mappedRange[1])); - if (".".equals(copy.getFeatureGroup())) + String group = sf.getFeatureGroup(); + if (".".equals(group)) { - copy.setFeatureGroup(getDbSource()); + group = getDbSource(); } + int newBegin = Math.min(mappedRange[0], mappedRange[1]); + int newEnd = Math.max(mappedRange[0], mappedRange[1]); + SequenceFeature copy = new SequenceFeature(sf, newBegin, newEnd, + group, sf.getScore()); targetSequence.addSequenceFeature(copy); /* * for sequence_variant on reverse strand, have to convert the allele * values to their complements */ - if (!forwardStrand - && SequenceOntologyFactory.getInstance().isA(sf.getType(), - SequenceOntologyI.SEQUENCE_VARIANT)) + if (!forwardStrand && SequenceOntologyFactory.getInstance() + .isA(sf.getType(), SequenceOntologyI.SEQUENCE_VARIANT)) { reverseComplementAlleles(copy); } @@@ -790,10 -765,8 +792,10 @@@ return false; } - // long start = System.currentTimeMillis(); - SequenceFeature[] sfs = sourceSequence.getSequenceFeatures(); + long start = System.currentTimeMillis(); + // SequenceFeature[] sfs = sourceSequence.getSequenceFeatures(); + List sfs = sourceSequence.getFeatures() + .getPositionalFeatures(); MapList mapping = getGenomicRangesFromFeatures(sourceSequence, accessionId, targetSequence.getStart()); if (mapping == null) @@@ -803,10 -776,10 +805,10 @@@ boolean result = transferFeatures(sfs, targetSequence, mapping, accessionId); - // System.out.println("transferFeatures (" + (sfs.length) + " --> " - // + targetSequence.getSequenceFeatures().length + ") to " - // + targetSequence.getName() - // + " took " + (System.currentTimeMillis() - start) + "ms"); + System.out.println("transferFeatures (" + (sfs.size()) + " --> " + + targetSequence.getFeatures().getFeatureCount(true) + ") to " + + targetSequence.getName() + " took " + + (System.currentTimeMillis() - start) + "ms"); return result; } @@@ -815,13 -788,13 +817,13 @@@ * converted using the mapping. Features which do not overlap are ignored. * Features whose parent is not the specified identifier are also ignored. * - * @param features + * @param sfs * @param targetSequence * @param mapping * @param parentId * @return */ - protected boolean transferFeatures(SequenceFeature[] features, + protected boolean transferFeatures(List sfs, SequenceI targetSequence, MapList mapping, String parentId) { final boolean forwardStrand = mapping.isFromForwardStrand(); @@@ -831,10 -804,10 +833,10 @@@ * position descending if reverse strand) so as to add them in * 'forwards' order to the target sequence */ - sortFeatures(features, forwardStrand); + SequenceFeatures.sortFeatures(sfs, forwardStrand); boolean transferred = false; - for (SequenceFeature sf : features) + for (SequenceFeature sf : sfs) { if (retainFeature(sf, parentId)) { @@@ -846,6 -819,33 +848,6 @@@ } /** - * Sort features by start position ascending (if on forward strand), or end - * position descending (if on reverse strand) - * - * @param features - * @param forwardStrand - */ - protected static void sortFeatures(SequenceFeature[] features, - final boolean forwardStrand) - { - Arrays.sort(features, new Comparator() - { - @Override - public int compare(SequenceFeature o1, SequenceFeature o2) - { - if (forwardStrand) - { - return Integer.compare(o1.getBegin(), o2.getBegin()); - } - else - { - return Integer.compare(o2.getEnd(), o1.getEnd()); - } - } - }); - } - - /** * Answers true if the feature type is one we want to keep for the sequence. * Some features are only retrieved in order to identify the sequence range, * and may then be discarded as redundant information (e.g. "CDS" feature for @@@ -887,30 -887,35 +889,30 @@@ /** * Returns a (possibly empty) list of features on the sequence which have the - * specified sequence ontology type (or a sub-type of it), and the given + * specified sequence ontology term (or a sub-type of it), and the given * identifier as parent * * @param sequence - * @param type + * @param term * @param parentId * @return */ protected List findFeatures(SequenceI sequence, - String type, String parentId) + String term, String parentId) { List result = new ArrayList(); - SequenceFeature[] sfs = sequence.getSequenceFeatures(); - if (sfs != null) + List sfs = sequence.getFeatures() + .getFeaturesByOntology(term); + for (SequenceFeature sf : sfs) { - SequenceOntologyI so = SequenceOntologyFactory.getInstance(); - for (SequenceFeature sf : sfs) + String parent = (String) sf.getValue(PARENT); + if (parent != null && parent.equals(parentId)) { - if (so.isA(sf.getType(), type)) - { - String parent = (String) sf.getValue(PARENT); - if (parent.equals(parentId)) - { - result.add(sf); - } - } + result.add(sf); } } + return result; } diff --combined src/jalview/ext/jmol/JmolParser.java index beaaf79,ddf3b1a..dc3d0ee --- a/src/jalview/ext/jmol/JmolParser.java +++ b/src/jalview/ext/jmol/JmolParser.java @@@ -105,8 -105,9 +105,9 @@@ public class JmolParser extends Structu // } // ; // instead, we distinguish .cif from non-.cif by filename - setStructureFileType(getDataName().toLowerCase().endsWith(".cif") ? PDBEntry.Type.MMCIF - .toString() : "PDB"); + setStructureFileType(getDataName().toLowerCase().endsWith(".cif") + ? PDBEntry.Type.MMCIF.toString() + : "PDB"); transformJmolModelToJalview(jmolModel.ms); } @@@ -135,7 -136,8 +136,8 @@@ { throw new Error(MessageManager.formatMessage( "error.jmol_version_not_compatible_with_jalview_version", - new String[] { JmolViewer.getJmolVersion() }), x); + new String[] + { JmolViewer.getJmolVersion() }), x); } } return viewer; @@@ -205,11 -207,10 +207,10 @@@ } } catch (OutOfMemoryError er) { - System.out - .println("OUT OF MEMORY LOADING TRANSFORMING JMOL MODEL TO JALVIEW MODEL"); - throw new IOException( - MessageManager - .getString("exception.outofmemory_loading_mmcif_file")); + System.out.println( + "OUT OF MEMORY LOADING TRANSFORMING JMOL MODEL TO JALVIEW MODEL"); + throw new IOException(MessageManager + .getString("exception.outofmemory_loading_mmcif_file")); } } @@@ -236,8 -237,9 +237,9 @@@ curAtom.number = atom.getAtomNumber(); curAtom.resName = atom.getGroup3(true); curAtom.resNumber = atom.getResno(); - curAtom.occupancy = ms.occupancies != null ? ms.occupancies[atom - .getIndex()] : Float.valueOf(atom.getOccupancy100()); + curAtom.occupancy = ms.occupancies != null + ? ms.occupancies[atom.getIndex()] + : Float.valueOf(atom.getOccupancy100()); String fmt = new Format("%4i").form(curAtom.resNumber); curAtom.resNumIns = (fmt + curAtom.insCode); curAtom.tfactor = atom.getBfactor100() / 100f; @@@ -259,7 -261,7 +261,7 @@@ HashMap chainTerMap) { // System.out.println("Atom: " + curAtom.getAtomNumber() - // + " Last atom index " + curAtom.group.lastAtomIndex); + // + " Last atom index " + curAtom.group.lastAtomIndex); if (chainTerMap == null || prevAtom == null) { return true; @@@ -282,7 -284,8 +284,8 @@@ { return false; } - if ((curAtom.getResno() - chainTerMap.get(curAtomChId).getResno()) < 5) + if ((curAtom.getResno() + - chainTerMap.get(curAtomChId).getResno()) < 5) { chainTerMap.put(curAtomChId, curAtom); return true; @@@ -297,7 -300,8 +300,8 @@@ { return false; } - if ((curAtom.getResno() - chainTerMap.get(curAtomChId).getResno()) < 5) + if ((curAtom.getResno() + - chainTerMap.get(curAtomChId).getResno()) < 5) { chainTerMap.put(curAtomChId, curAtom); return true; @@@ -305,8 -309,8 +309,8 @@@ return false; } // HETATM with resNum jump > 2 - return !(curAtom.isHetero() && ((curAtom.getResno() - prevAtom - .getResno()) > 2)); + return !(curAtom.isHetero() + && ((curAtom.getResno() - prevAtom.getResno()) > 2)); } private void createAnnotation(SequenceI sequence, PDBChain chain, @@@ -351,10 -355,10 +355,10 @@@ SequenceI sq, char[] secstr, char[] secstrcode, String chainId, int firstResNum) { - char[] seq = sq.getSequence(); + int length = sq.getLength(); boolean ssFound = false; - Annotation asecstr[] = new Annotation[seq.length + firstResNum - 1]; - for (int p = 0; p < seq.length; p++) + Annotation asecstr[] = new Annotation[length + firstResNum - 1]; + for (int p = 0; p < length; p++) { if (secstr[p] >= 'A' && secstr[p] <= 'z') { @@@ -411,8 -415,8 +415,8 @@@ * @param secstr * @param secstrcode */ - protected void setSecondaryStructure(STR proteinStructureSubType, - int pos, char[] secstr, char[] secstrcode) + protected void setSecondaryStructure(STR proteinStructureSubType, int pos, + char[] secstr, char[] secstrcode) { switch (proteinStructureSubType) { @@@ -489,8 -493,8 +493,8 @@@ @Override public void notifyCallback(CBK cbType, Object[] data) { - String strInfo = (data == null || data[1] == null ? null : data[1] - .toString()); + String strInfo = (data == null || data[1] == null ? null + : data[1].toString()); switch (cbType) { case ECHO: @@@ -590,7 -594,8 +594,8 @@@ * Not implemented - returns null */ @Override - public float[][][] functionXYZ(String functionName, int nx, int ny, int nz) + public float[][][] functionXYZ(String functionName, int nx, int ny, + int nz) { return null; } @@@ -642,7 -647,8 +647,8 @@@ return predictSecondaryStructure; } - public void setPredictSecondaryStructure(boolean predictSecondaryStructure) + public void setPredictSecondaryStructure( + boolean predictSecondaryStructure) { this.predictSecondaryStructure = predictSecondaryStructure; } diff --combined src/jalview/ext/rbvi/chimera/AtomSpecModel.java index f3c9c1e,8c0ea66..f923f7f --- a/src/jalview/ext/rbvi/chimera/AtomSpecModel.java +++ b/src/jalview/ext/rbvi/chimera/AtomSpecModel.java @@@ -1,6 -1,26 +1,26 @@@ + /* + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors + * + * This file is part of Jalview. + * + * Jalview is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * Jalview is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. + */ package jalview.ext.rbvi.chimera; -import jalview.util.RangeComparator; +import jalview.util.IntRangeComparator; import java.util.ArrayList; import java.util.Collections; @@@ -26,7 -46,7 +46,7 @@@ import java.util.TreeMap *
* *
-  * @see http://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/midas/frameatom_spec.html
+  * @see http://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/midas/frameatom_spec.html
   * 
*/ public class AtomSpecModel @@@ -107,7 -127,7 +127,7 @@@ /* * sort ranges into ascending start position order */ - Collections.sort(rangeList, new RangeComparator(true)); + Collections.sort(rangeList, IntRangeComparator.ASCENDING); int start = rangeList.isEmpty() ? 0 : rangeList.get(0)[0]; int end = rangeList.isEmpty() ? 0 : rangeList.get(0)[1]; diff --combined src/jalview/ext/rbvi/chimera/ChimeraCommands.java index e9ce49b,dd91087..dad8511 --- a/src/jalview/ext/rbvi/chimera/ChimeraCommands.java +++ b/src/jalview/ext/rbvi/chimera/ChimeraCommands.java @@@ -269,8 -269,8 +269,8 @@@ public class ChimeraCommand // final colour range if (lastColour != null) { - addColourRange(colourMap, lastColour, pdbfnum, startPos, lastPos, - lastChain); + addColourRange(colourMap, lastColour, pdbfnum, startPos, + lastPos, lastChain); } // break; } @@@ -318,8 -318,8 +318,8 @@@ * @return */ public static StructureMappingcommandSet getSetAttributeCommandsForFeatures( - StructureSelectionManager ssm, String[] files, - SequenceI[][] seqs, AlignmentViewPanel viewPanel) + StructureSelectionManager ssm, String[] files, SequenceI[][] seqs, + AlignmentViewPanel viewPanel) { Map> featureMap = buildFeaturesMap( ssm, files, seqs, viewPanel); @@@ -346,8 -346,8 +346,8 @@@ * @return */ protected static Map> buildFeaturesMap( - StructureSelectionManager ssm, String[] files, - SequenceI[][] seqs, AlignmentViewPanel viewPanel) + StructureSelectionManager ssm, String[] files, SequenceI[][] seqs, + AlignmentViewPanel viewPanel) { Map> theMap = new LinkedHashMap>(); @@@ -411,8 -411,12 +411,8 @@@ StructureMapping mapping, SequenceI seq, Map> theMap, int modelNumber) { - SequenceFeature[] sfs = seq.getSequenceFeatures(); - if (sfs == null) - { - return; - } - + List sfs = seq.getFeatures().getPositionalFeatures( + visibleFeatures.toArray(new String[visibleFeatures.size()])); for (SequenceFeature sf : sfs) { String type = sf.getType(); @@@ -423,7 -427,7 +423,7 @@@ */ boolean isFromViewer = JalviewChimeraBinding.CHIMERA_FEATURE_GROUP .equals(sf.getFeatureGroup()); - if (isFromViewer || !visibleFeatures.contains(type)) + if (isFromViewer) { continue; } @@@ -450,8 -454,8 +450,8 @@@ } for (int[] range : mappedRanges) { - addColourRange(featureValues, value, modelNumber, range[0], range[1], - mapping.getChain()); + addColourRange(featureValues, value, modelNumber, range[0], + range[1], mapping.getChain()); } } } @@@ -513,9 -517,11 +513,11 @@@ * to an underscore. * * @param featureType - * @return
-    * @see https://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/midas/setattr.html
-    * 
+ * @return + * + *
+    * @see https://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/midas/setattr.html
+    *         
*/ protected static String makeAttributeName(String featureType) { diff --combined src/jalview/gui/AlignFrame.java index 8a59a4b,c78abdc..1bd1541 --- a/src/jalview/gui/AlignFrame.java +++ b/src/jalview/gui/AlignFrame.java @@@ -234,8 -234,8 +234,8 @@@ public class AlignFrame extends GAlignF * @param height * height of frame. */ - public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, - int width, int height) + public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width, + int height) { this(al, hiddenColumns, width, height, null); } @@@ -251,8 -251,8 +251,8 @@@ * @param sequenceSetId * (may be null) */ - public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, - int width, int height, String sequenceSetId) + public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width, + int height, String sequenceSetId) { this(al, hiddenColumns, width, height, sequenceSetId, null); } @@@ -270,8 -270,8 +270,8 @@@ * @param viewId * (may be null) */ - public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, - int width, int height, String sequenceSetId, String viewId) + public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width, + int height, String sequenceSetId, String viewId) { setSize(width, height); @@@ -510,9 -510,10 +510,10 @@@ public void keyPressed(KeyEvent evt) { if (viewport.cursorMode - && ((evt.getKeyCode() >= KeyEvent.VK_0 && evt.getKeyCode() <= KeyEvent.VK_9) || (evt - .getKeyCode() >= KeyEvent.VK_NUMPAD0 && evt - .getKeyCode() <= KeyEvent.VK_NUMPAD9)) + && ((evt.getKeyCode() >= KeyEvent.VK_0 + && evt.getKeyCode() <= KeyEvent.VK_9) + || (evt.getKeyCode() >= KeyEvent.VK_NUMPAD0 + && evt.getKeyCode() <= KeyEvent.VK_NUMPAD9)) && Character.isDigit(evt.getKeyChar())) { alignPanel.getSeqPanel().numberPressed(evt.getKeyChar()); @@@ -552,7 -553,8 +553,8 @@@ case KeyEvent.VK_LEFT: if (evt.isAltDown() || !viewport.cursorMode) { - slideSequences(false, alignPanel.getSeqPanel().getKeyboardNo1()); + slideSequences(false, + alignPanel.getSeqPanel().getKeyboardNo1()); } else { @@@ -575,9 -577,8 +577,8 @@@ case KeyEvent.VK_SPACE: if (viewport.cursorMode) { - alignPanel.getSeqPanel().insertGapAtCursor( - evt.isControlDown() || evt.isShiftDown() - || evt.isAltDown()); + alignPanel.getSeqPanel().insertGapAtCursor(evt.isControlDown() + || evt.isShiftDown() || evt.isAltDown()); } break; @@@ -600,9 -601,8 +601,8 @@@ } else { - alignPanel.getSeqPanel().deleteGapAtCursor( - evt.isControlDown() || evt.isShiftDown() - || evt.isAltDown()); + alignPanel.getSeqPanel().deleteGapAtCursor(evt.isControlDown() + || evt.isShiftDown() || evt.isAltDown()); } break; @@@ -649,9 -649,9 +649,9 @@@ case KeyEvent.VK_F2: viewport.cursorMode = !viewport.cursorMode; - statusBar.setText(MessageManager.formatMessage( - "label.keyboard_editing_mode", - new String[] { (viewport.cursorMode ? "on" : "off") })); + statusBar.setText(MessageManager + .formatMessage("label.keyboard_editing_mode", new String[] + { (viewport.cursorMode ? "on" : "off") })); if (viewport.cursorMode) { alignPanel.getSeqPanel().seqCanvas.cursorX = vpRanges @@@ -705,16 -705,16 +705,16 @@@ case KeyEvent.VK_LEFT: if (evt.isAltDown() || !viewport.cursorMode) { - viewport.firePropertyChange("alignment", null, viewport - .getAlignment().getSequences()); + viewport.firePropertyChange("alignment", null, + viewport.getAlignment().getSequences()); } break; case KeyEvent.VK_RIGHT: if (evt.isAltDown() || !viewport.cursorMode) { - viewport.firePropertyChange("alignment", null, viewport - .getAlignment().getSequences()); + viewport.firePropertyChange("alignment", null, + viewport.getAlignment().getSequences()); } break; } @@@ -800,8 -800,8 +800,8 @@@ @Override public void run() { - System.err - .println("Rebuild WS Menu for service change"); + System.err.println( + "Rebuild WS Menu for service change"); BuildWebServiceMenu(); } @@@ -845,13 -845,13 +845,13 @@@ showReverse.setVisible(nucleotide); showReverseComplement.setVisible(nucleotide); conservationMenuItem.setEnabled(!nucleotide); - modifyConservation.setEnabled(!nucleotide - && conservationMenuItem.isSelected()); + modifyConservation + .setEnabled(!nucleotide && conservationMenuItem.isSelected()); showGroupConservation.setEnabled(!nucleotide); - showComplementMenuItem.setText(nucleotide ? MessageManager - .getString("label.protein") : MessageManager - .getString("label.nucleotide")); + showComplementMenuItem + .setText(nucleotide ? MessageManager.getString("label.protein") + : MessageManager.getString("label.nucleotide")); } /** @@@ -1025,7 -1025,8 +1025,8 @@@ Desktop.instance.closeAssociatedWindows(); FileLoader loader = new FileLoader(); - DataSourceType protocol = fileName.startsWith("http:") ? DataSourceType.URL + DataSourceType protocol = fileName.startsWith("http:") + ? DataSourceType.URL : DataSourceType.FILE; loader.LoadFile(viewport, fileName, protocol, currentFileFormat); } @@@ -1034,7 -1035,8 +1035,8 @@@ Rectangle bounds = this.getBounds(); FileLoader loader = new FileLoader(); - DataSourceType protocol = fileName.startsWith("http:") ? DataSourceType.URL + DataSourceType protocol = fileName.startsWith("http:") + ? DataSourceType.URL : DataSourceType.FILE; AlignFrame newframe = loader.LoadFileWaitTillLoaded(fileName, protocol, currentFileFormat); @@@ -1066,8 -1068,8 +1068,8 @@@ @Override public void addFromText_actionPerformed(ActionEvent e) { - Desktop.instance.inputTextboxMenuItem_actionPerformed(viewport - .getAlignPanel()); + Desktop.instance + .inputTextboxMenuItem_actionPerformed(viewport.getAlignPanel()); } @Override @@@ -1099,14 -1101,14 +1101,14 @@@ @Override public void saveAs_actionPerformed(ActionEvent e) { - String format = currentFileFormat == null ? null : currentFileFormat - .getName(); - JalviewFileChooser chooser = JalviewFileChooser.forWrite( - Cache.getProperty("LAST_DIRECTORY"), format); + String format = currentFileFormat == null ? null + : currentFileFormat.getName(); + JalviewFileChooser chooser = JalviewFileChooser + .forWrite(Cache.getProperty("LAST_DIRECTORY"), format); chooser.setFileView(new JalviewFileView()); - chooser.setDialogTitle(MessageManager - .getString("label.save_alignment_to_file")); + chooser.setDialogTitle( + MessageManager.getString("label.save_alignment_to_file")); chooser.setToolTipText(MessageManager.getString("action.save")); int value = chooser.showSaveDialog(this); @@@ -1116,14 -1118,11 +1118,11 @@@ currentFileFormat = chooser.getSelectedFormat(); while (currentFileFormat == null) { - JvOptionPane - .showInternalMessageDialog( - Desktop.desktop, - MessageManager - .getString("label.select_file_format_before_saving"), - MessageManager - .getString("label.file_format_not_specified"), - JvOptionPane.WARNING_MESSAGE); + JvOptionPane.showInternalMessageDialog(Desktop.desktop, + MessageManager.getString( + "label.select_file_format_before_saving"), + MessageManager.getString("label.file_format_not_specified"), + JvOptionPane.WARNING_MESSAGE); currentFileFormat = chooser.getSelectedFormat(); value = chooser.showSaveDialog(this); if (value != JalviewFileChooser.APPROVE_OPTION) @@@ -1151,15 -1150,15 +1150,15 @@@ if (shortName.indexOf(java.io.File.separatorChar) > -1) { - shortName = shortName.substring(shortName - .lastIndexOf(java.io.File.separatorChar) + 1); + shortName = shortName.substring( + shortName.lastIndexOf(java.io.File.separatorChar) + 1); } success = new Jalview2XML().saveAlignment(this, file, shortName); statusBar.setText(MessageManager.formatMessage( - "label.successfully_saved_to_file_in_format", new Object[] { - fileName, format })); + "label.successfully_saved_to_file_in_format", new Object[] + { fileName, format })); } else @@@ -1172,13 -1171,14 +1171,14 @@@ } FormatAdapter f = new FormatAdapter(alignPanel, exportData.getSettings()); - String output = f.formatSequences( - format, - exportData.getAlignment(), // class cast exceptions will + String output = f.formatSequences(format, exportData.getAlignment(), // class + // cast + // exceptions + // will // occur in the distant future exportData.getOmitHidden(), exportData.getStartEndPostions(), - f.getCacheSuffixDefault(format), viewport.getAlignment() - .getHiddenColumns()); + f.getCacheSuffixDefault(format), + viewport.getAlignment().getHiddenColumns()); if (output == null) { @@@ -1194,8 -1194,8 +1194,8 @@@ out.close(); this.setTitle(file); statusBar.setText(MessageManager.formatMessage( - "label.successfully_saved_to_file_in_format", - new Object[] { fileName, format.getName() })); + "label.successfully_saved_to_file_in_format", new Object[] + { fileName, format.getName() })); } catch (Exception ex) { success = false; @@@ -1207,9 -1207,9 +1207,9 @@@ if (!success) { JvOptionPane.showInternalMessageDialog(this, MessageManager - .formatMessage("label.couldnt_save_file", - new Object[] { fileName }), MessageManager - .getString("label.error_saving_file"), + .formatMessage("label.couldnt_save_file", new Object[] + { fileName }), + MessageManager.getString("label.error_saving_file"), JvOptionPane.WARNING_MESSAGE); } @@@ -1240,8 -1240,8 +1240,8 @@@ @Override protected void outputText_actionPerformed(ActionEvent e) { - FileFormatI fileFormat = FileFormats.getInstance().forName( - e.getActionCommand()); + FileFormatI fileFormat = FileFormats.getInstance() + .forName(e.getActionCommand()); AlignmentExportData exportData = getAlignmentForExport(fileFormat, viewport, null); if (exportData.getSettings().isCancelled()) @@@ -1256,15 -1256,15 +1256,15 @@@ cap.setText(new FormatAdapter(alignPanel, exportData.getSettings()) .formatSequences(format, exportData.getAlignment(), exportData.getOmitHidden(), - exportData - .getStartEndPostions(), viewport - .getAlignment().getHiddenColumns())); - Desktop.addInternalFrame(cap, MessageManager.formatMessage( - "label.alignment_output_command", - new Object[] { e.getActionCommand() }), 600, 500); + exportData.getStartEndPostions(), + viewport.getAlignment().getHiddenColumns())); + Desktop.addInternalFrame(cap, MessageManager + .formatMessage("label.alignment_output_command", new Object[] + { e.getActionCommand() }), 600, 500); } catch (OutOfMemoryError oom) { - new OOMWarning("Outputting alignment as " + e.getActionCommand(), oom); + new OOMWarning("Outputting alignment as " + e.getActionCommand(), + oom); cap.dispose(); } @@@ -1408,10 -1408,10 +1408,10 @@@ JalviewFileChooser chooser = new JalviewFileChooser( jalview.bin.Cache.getProperty("LAST_DIRECTORY")); chooser.setFileView(new JalviewFileView()); - chooser.setDialogTitle(MessageManager - .getString("label.load_jalview_annotations")); - chooser.setToolTipText(MessageManager - .getString("label.load_jalview_annotations")); + chooser.setDialogTitle( + MessageManager.getString("label.load_jalview_annotations")); + chooser.setToolTipText( + MessageManager.getString("label.load_jalview_annotations")); int value = chooser.showOpenDialog(null); @@@ -1510,9 -1510,9 +1510,9 @@@ { undoMenuItem.setEnabled(true); CommandI command = viewport.getHistoryList().peek(); - undoMenuItem.setText(MessageManager.formatMessage( - "label.undo_command", - new Object[] { command.getDescription() })); + undoMenuItem.setText(MessageManager + .formatMessage("label.undo_command", new Object[] + { command.getDescription() })); } else { @@@ -1525,9 -1525,9 +1525,9 @@@ redoMenuItem.setEnabled(true); CommandI command = viewport.getRedoList().peek(); - redoMenuItem.setText(MessageManager.formatMessage( - "label.redo_command", - new Object[] { command.getDescription() })); + redoMenuItem.setText(MessageManager + .formatMessage("label.redo_command", new Object[] + { command.getDescription() })); } else { @@@ -1599,8 -1599,8 +1599,8 @@@ { if (originalSource != viewport) { - Cache.log - .warn("Implementation worry: mismatch of viewport origin for undo"); + Cache.log.warn( + "Implementation worry: mismatch of viewport origin for undo"); } originalSource.updateHiddenColumns(); // originalSource.hasHiddenColumns = (viewport.getColumnSelection() != @@@ -1608,8 -1608,8 +1608,8 @@@ // && viewport.getColumnSelection().getHiddenColumns() != null && // viewport.getColumnSelection() // .getHiddenColumns().size() > 0); - originalSource.firePropertyChange("alignment", null, originalSource - .getAlignment().getSequences()); + originalSource.firePropertyChange("alignment", null, + originalSource.getAlignment().getSequences()); } } @@@ -1639,8 -1639,8 +1639,8 @@@ if (originalSource != viewport) { - Cache.log - .warn("Implementation worry: mismatch of viewport origin for redo"); + Cache.log.warn( + "Implementation worry: mismatch of viewport origin for redo"); } originalSource.updateHiddenColumns(); // originalSource.hasHiddenColumns = (viewport.getColumnSelection() != @@@ -1648,8 -1648,8 +1648,8 @@@ // && viewport.getColumnSelection().getHiddenColumns() != null && // viewport.getColumnSelection() // .getHiddenColumns().size() > 0); - originalSource.firePropertyChange("alignment", null, originalSource - .getAlignment().getSequences()); + originalSource.firePropertyChange("alignment", null, + originalSource.getAlignment().getSequences()); } } @@@ -1664,8 -1664,8 +1664,8 @@@ { EditCommand editCommand = (EditCommand) command; al = editCommand.getAlignment(); - List comps = PaintRefresher.components.get(viewport - .getSequenceSetId()); + List comps = PaintRefresher.components + .get(viewport.getSequenceSetId()); for (Component comp : comps) { @@@ -1719,15 -1719,15 +1719,15 @@@ List sg = new ArrayList<>(); if (viewport.cursorMode) { - sg.add(viewport.getAlignment().getSequenceAt( - alignPanel.getSeqPanel().seqCanvas.cursorY)); + sg.add(viewport.getAlignment() + .getSequenceAt(alignPanel.getSeqPanel().seqCanvas.cursorY)); } else if (viewport.getSelectionGroup() != null && viewport.getSelectionGroup().getSize() != viewport .getAlignment().getHeight()) { - sg = viewport.getSelectionGroup().getSequences( - viewport.getHiddenRepSequences()); + sg = viewport.getSelectionGroup() + .getSequences(viewport.getHiddenRepSequences()); } if (sg.size() < 1) @@@ -1756,13 -1756,13 +1756,13 @@@ SlideSequencesCommand ssc; if (right) { - ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1, - size, viewport.getGapCharacter()); + ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1, size, + viewport.getGapCharacter()); } else { - ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2, - size, viewport.getGapCharacter()); + ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2, size, + viewport.getGapCharacter()); } int groupAdjustment = 0; @@@ -1807,9 -1807,8 +1807,8 @@@ if (!inSplitFrame && historyList != null && historyList.size() > 0 && historyList.peek() instanceof SlideSequencesCommand) { - appendHistoryItem = ssc - .appendSlideCommand((SlideSequencesCommand) historyList - .peek()); + appendHistoryItem = ssc.appendSlideCommand( + (SlideSequencesCommand) historyList.peek()); } if (!appendHistoryItem) @@@ -1857,8 -1856,8 +1856,8 @@@ Toolkit.getDefaultToolkit().getSystemClipboard() .setContents(new StringSelection(""), null); - Toolkit.getDefaultToolkit().getSystemClipboard() - .setContents(ss, Desktop.instance); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, + Desktop.instance); } catch (OutOfMemoryError er) { new OOMWarning("copying region", er); @@@ -1877,8 -1876,9 +1876,9 @@@ { if (region[0] >= hiddenOffset && region[1] <= hiddenCutoff) { - hiddenColumns.add(new int[] { region[0] - hiddenOffset, - region[1] - hiddenOffset }); + hiddenColumns + .add(new int[] + { region[0] - hiddenOffset, region[1] - hiddenOffset }); } } } @@@ -1886,8 -1886,8 +1886,8 @@@ Desktop.jalviewClipboard = new Object[] { seqs, viewport.getAlignment().getDataset(), hiddenColumns }; statusBar.setText(MessageManager.formatMessage( - "label.copied_sequences_to_clipboard", new Object[] { Integer - .valueOf(seqs.length).toString() })); + "label.copied_sequences_to_clipboard", new Object[] + { Integer.valueOf(seqs.length).toString() })); } /** @@@ -2037,8 -2037,8 +2037,8 @@@ { // copy and derive new dataset sequence sequences[i] = sequences[i].deriveSequence(); - alignment.getDataset().addSequence( - sequences[i].getDatasetSequence()); + alignment.getDataset() + .addSequence(sequences[i].getDatasetSequence()); // TODO: avoid creation of duplicate dataset sequences with a // 'contains' method using SequenceI.equals()/SequenceI.contains() } @@@ -2068,18 -2068,20 +2068,20 @@@ annotationAdded = true; if (alann[i].sequenceRef == null && !alann[i].autoCalculated) { - AlignmentAnnotation newann = new AlignmentAnnotation(alann[i]); + AlignmentAnnotation newann = new AlignmentAnnotation( + alann[i]); if (newann.graphGroup > -1) { if (newGraphGroups.size() <= newann.graphGroup || newGraphGroups.get(newann.graphGroup) == null) { - for (int q = newGraphGroups.size(); q <= newann.graphGroup; q++) + for (int q = newGraphGroups + .size(); q <= newann.graphGroup; q++) { newGraphGroups.add(q, null); } - newGraphGroups.set(newann.graphGroup, new Integer( - ++fgroup)); + newGraphGroups.set(newann.graphGroup, + new Integer(++fgroup)); } newann.graphGroup = newGraphGroups.get(newann.graphGroup) .intValue(); @@@ -2098,7 -2100,8 +2100,8 @@@ // addHistoryItem(new EditCommand( MessageManager.getString("label.add_sequences"), - Action.PASTE, sequences, 0, alignment.getWidth(), alignment)); + Action.PASTE, sequences, 0, alignment.getWidth(), + alignment)); } // Add any annotations attached to sequences for (int i = 0; i < sequences.length; i++) @@@ -2119,12 -2122,13 +2122,13 @@@ if (newGraphGroups.size() <= newann.graphGroup || newGraphGroups.get(newann.graphGroup) == null) { - for (int q = newGraphGroups.size(); q <= newann.graphGroup; q++) + for (int q = newGraphGroups + .size(); q <= newann.graphGroup; q++) { newGraphGroups.add(q, null); } - newGraphGroups.set(newann.graphGroup, new Integer( - ++fgroup)); + newGraphGroups.set(newann.graphGroup, + new Integer(++fgroup)); } newann.graphGroup = newGraphGroups.get(newann.graphGroup) .intValue(); @@@ -2134,8 -2138,8 +2138,8 @@@ // was // duplicated // earlier - alignment - .setAnnotationIndex(sequences[i].getAnnotation()[a], a); + alignment.setAnnotationIndex(sequences[i].getAnnotation()[a], + a); } } } @@@ -2215,9 -2219,8 +2219,8 @@@ // >>>This is a fix for the moment, until a better solution is // found!!<<< af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer() - .transferSettings( - alignPanel.getSeqPanel().seqCanvas - .getFeatureRenderer()); + .transferSettings(alignPanel.getSeqPanel().seqCanvas + .getFeatureRenderer()); // TODO: maintain provenance of an alignment, rather than just make the // title a concatenation of operations. @@@ -2256,8 -2259,8 +2259,8 @@@ { try { - AlignmentI alignment = AlignmentUtils.expandContext(getViewport() - .getAlignment(), -1); + AlignmentI alignment = AlignmentUtils + .expandContext(getViewport().getAlignment(), -1); AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH, DEFAULT_HEIGHT); String newtitle = new String("Flanking alignment"); @@@ -2275,9 -2278,8 +2278,8 @@@ // >>>This is a fix for the moment, until a better solution is // found!!<<< af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer() - .transferSettings( - alignPanel.getSeqPanel().seqCanvas - .getFeatureRenderer()); + .transferSettings(alignPanel.getSeqPanel().seqCanvas + .getFeatureRenderer()); // TODO: maintain provenance of an alignment, rather than just make the // title a concatenation of operations. @@@ -2339,8 -2341,8 +2341,8 @@@ */ if (sg.getSize() == viewport.getAlignment().getHeight()) { - boolean isEntireAlignWidth = (((sg.getEndRes() - sg.getStartRes()) + 1) == viewport - .getAlignment().getWidth()) ? true : false; + boolean isEntireAlignWidth = (((sg.getEndRes() - sg.getStartRes()) + + 1) == viewport.getAlignment().getWidth()) ? true : false; if (isEntireAlignWidth) { int confirm = JvOptionPane.showConfirmDialog(this, @@@ -2369,8 -2371,8 +2371,8 @@@ viewport.sendSelection(); viewport.getAlignment().deleteGroup(sg); - viewport.firePropertyChange("alignment", null, viewport.getAlignment() - .getSequences()); + viewport.firePropertyChange("alignment", null, + viewport.getAlignment().getSequences()); if (viewport.getAlignment().getHeight() < 1) { try @@@ -2442,6 -2444,7 +2444,6 @@@ viewport.setSelectionGroup(null); viewport.getColumnSelection().clear(); viewport.setSelectionGroup(null); - alignPanel.getSeqPanel().seqCanvas.highlightSearchResults(null); alignPanel.getIdPanel().getIdCanvas().searchResults = null; // JAL-2034 - should delegate to // alignPanel to decide if overview needs @@@ -2533,8 -2536,8 +2535,8 @@@ SequenceI[] seqs; if (viewport.getSelectionGroup() != null) { - seqs = viewport.getSelectionGroup().getSequencesAsArray( - viewport.getHiddenRepSequences()); + seqs = viewport.getSelectionGroup() + .getSequencesAsArray(viewport.getHiddenRepSequences()); } else { @@@ -2554,10 -2557,9 +2556,9 @@@ column, viewport.getAlignment()); } - statusBar.setText(MessageManager.formatMessage( - "label.removed_columns", - new String[] { Integer.valueOf(trimRegion.getSize()) - .toString() })); + statusBar.setText(MessageManager + .formatMessage("label.removed_columns", new String[] + { Integer.valueOf(trimRegion.getSize()).toString() })); addHistoryItem(trimRegion); @@@ -2570,8 -2572,8 +2571,8 @@@ } } - viewport.firePropertyChange("alignment", null, viewport - .getAlignment().getSequences()); + viewport.firePropertyChange("alignment", null, + viewport.getAlignment().getSequences()); } } @@@ -2589,8 -2591,8 +2590,8 @@@ SequenceI[] seqs; if (viewport.getSelectionGroup() != null) { - seqs = viewport.getSelectionGroup().getSequencesAsArray( - viewport.getHiddenRepSequences()); + seqs = viewport.getSelectionGroup() + .getSequencesAsArray(viewport.getHiddenRepSequences()); start = viewport.getSelectionGroup().getStartRes(); end = viewport.getSelectionGroup().getEndRes(); } @@@ -2605,10 -2607,9 +2606,9 @@@ addHistoryItem(removeGapCols); - statusBar.setText(MessageManager.formatMessage( - "label.removed_empty_columns", - new Object[] { Integer.valueOf(removeGapCols.getSize()) - .toString() })); + statusBar.setText(MessageManager + .formatMessage("label.removed_empty_columns", new Object[] + { Integer.valueOf(removeGapCols.getSize()).toString() })); // This is to maintain viewport position on first residue // of first sequence @@@ -2620,8 -2621,8 +2620,8 @@@ // if (viewport.hasHiddenColumns) // viewport.getColumnSelection().compensateForEdits(shifts); vpRanges.setStartRes(seq.findIndex(startRes) - 1); - viewport.firePropertyChange("alignment", null, viewport.getAlignment() - .getSequences()); + viewport.firePropertyChange("alignment", null, + viewport.getAlignment().getSequences()); } @@@ -2639,8 -2640,8 +2639,8 @@@ SequenceI[] seqs; if (viewport.getSelectionGroup() != null) { - seqs = viewport.getSelectionGroup().getSequencesAsArray( - viewport.getHiddenRepSequences()); + seqs = viewport.getSelectionGroup() + .getSequencesAsArray(viewport.getHiddenRepSequences()); start = viewport.getSelectionGroup().getStartRes(); end = viewport.getSelectionGroup().getEndRes(); } @@@ -2659,8 -2660,8 +2659,8 @@@ vpRanges.setStartRes(seq.findIndex(startRes) - 1); - viewport.firePropertyChange("alignment", null, viewport.getAlignment() - .getSequences()); + viewport.firePropertyChange("alignment", null, + viewport.getAlignment().getSequences()); } @@@ -2674,8 -2675,8 +2674,8 @@@ public void padGapsMenuitem_actionPerformed(ActionEvent e) { viewport.setPadGaps(padGapsMenuitem.isSelected()); - viewport.firePropertyChange("alignment", null, viewport.getAlignment() - .getSequences()); + viewport.firePropertyChange("alignment", null, + viewport.getAlignment().getSequences()); } /** @@@ -2789,8 -2790,8 +2789,8 @@@ } String newViewName = viewTitle + ((addFirstIndex) ? " " + index : ""); - List comps = PaintRefresher.components.get(viewport - .getSequenceSetId()); + List comps = PaintRefresher.components + .get(viewport.getSequenceSetId()); List existingNames = getExistingViewNames(comps); @@@ -2970,9 -2971,8 +2970,8 @@@ // Hide everything by the current selection - this is a hack - we do the // invert and then hide // first check that there will be visible columns after the invert. - if (viewport.hasSelectedColumns() - || (sg != null && sg.getSize() > 0 && sg.getStartRes() <= sg - .getEndRes())) + if (viewport.hasSelectedColumns() || (sg != null && sg.getSize() > 0 + && sg.getStartRes() <= sg.getEndRes())) { // now invert the sequence set, if required - empty selection implies // that no hiding is required. @@@ -3228,14 -3228,15 +3227,15 @@@ editPane.setEditable(false); StringBuffer contents = new AlignmentProperties(viewport.getAlignment()) .formatAsHtml(); - editPane.setText(MessageManager.formatMessage("label.html_content", - new Object[] { contents.toString() })); + editPane.setText( + MessageManager.formatMessage("label.html_content", new Object[] + { contents.toString() })); JInternalFrame frame = new JInternalFrame(); frame.getContentPane().add(new JScrollPane(editPane)); - Desktop.addInternalFrame(frame, MessageManager.formatMessage( - "label.alignment_properties", new Object[] { getTitle() }), - 500, 400); + Desktop.addInternalFrame(frame, MessageManager + .formatMessage("label.alignment_properties", new Object[] + { getTitle() }), 500, 400); } /** @@@ -3255,21 -3256,23 +3255,23 @@@ JInternalFrame frame = new JInternalFrame(); final OverviewPanel overview = new OverviewPanel(alignPanel); frame.setContentPane(overview); - Desktop.addInternalFrame(frame, MessageManager.formatMessage( - "label.overview_params", new Object[] { this.getTitle() }), - true, frame.getWidth(), frame.getHeight(), true, true); + Desktop.addInternalFrame(frame, MessageManager + .formatMessage("label.overview_params", new Object[] + { this.getTitle() }), true, frame.getWidth(), frame.getHeight(), + true, true); frame.pack(); frame.setLayer(JLayeredPane.PALETTE_LAYER); - frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter() - { - @Override - public void internalFrameClosed( - javax.swing.event.InternalFrameEvent evt) - { - overview.dispose(); - alignPanel.setOverviewPanel(null); - }; - }); + frame.addInternalFrameListener( + new javax.swing.event.InternalFrameAdapter() + { + @Override + public void internalFrameClosed( + javax.swing.event.InternalFrameEvent evt) + { + overview.dispose(); + alignPanel.setOverviewPanel(null); + }; + }); alignPanel.setOverviewPanel(overview); } @@@ -3360,8 -3363,8 +3362,8 @@@ @Override protected void modifyPID_actionPerformed() { - SliderPanel.setPIDSliderSource(alignPanel, - viewport.getResidueShading(), alignPanel.getViewName()); + SliderPanel.setPIDSliderSource(alignPanel, viewport.getResidueShading(), + alignPanel.getViewName()); SliderPanel.showPIDSlider(); } @@@ -3432,8 -3435,8 +3434,8 @@@ public void sortPairwiseMenuItem_actionPerformed(ActionEvent e) { SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray(); - AlignmentSorter.sortByPID(viewport.getAlignment(), viewport - .getAlignment().getSequenceAt(0)); + AlignmentSorter.sortByPID(viewport.getAlignment(), + viewport.getAlignment().getSequenceAt(0)); addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder, viewport.getAlignment())); alignPanel.paintAlignment(true); @@@ -3450,8 -3453,8 +3452,8 @@@ { SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray(); AlignmentSorter.sortByID(viewport.getAlignment()); - addHistoryItem(new OrderCommand("ID Sort", oldOrder, - viewport.getAlignment())); + addHistoryItem( + new OrderCommand("ID Sort", oldOrder, viewport.getAlignment())); alignPanel.paintAlignment(true); } @@@ -3512,8 -3515,9 +3514,9 @@@ if ((viewport.getSelectionGroup() == null) || (viewport.getSelectionGroup().getSize() < 2)) { - JvOptionPane.showInternalMessageDialog(this, MessageManager - .getString("label.you_must_select_least_two_sequences"), + JvOptionPane.showInternalMessageDialog(this, + MessageManager.getString( + "label.you_must_select_least_two_sequences"), MessageManager.getString("label.invalid_selection"), JvOptionPane.WARNING_MESSAGE); } @@@ -3533,8 -3537,8 +3536,8 @@@ viewport.autoCalculateConsensus = autoCalculate.isSelected(); if (viewport.autoCalculateConsensus) { - viewport.firePropertyChange("alignment", null, viewport - .getAlignment().getSequences()); + viewport.firePropertyChange("alignment", null, + viewport.getAlignment().getSequences()); } } @@@ -3560,7 -3564,8 +3563,8 @@@ * @param options * parameters for the distance or similarity calculation */ - void newTreePanel(String type, String modelName, SimilarityParamsI options) + void newTreePanel(String type, String modelName, + SimilarityParamsI options) { String frameTitle = ""; TreePanel tp; @@@ -3576,14 -3581,12 +3580,12 @@@ { if (_s.getLength() < sg.getEndRes()) { - JvOptionPane - .showMessageDialog( - Desktop.desktop, - MessageManager - .getString("label.selected_region_to_tree_may_only_contain_residues_or_gaps"), - MessageManager - .getString("label.sequences_selection_not_aligned"), - JvOptionPane.WARNING_MESSAGE); + JvOptionPane.showMessageDialog(Desktop.desktop, + MessageManager.getString( + "label.selected_region_to_tree_may_only_contain_residues_or_gaps"), + MessageManager.getString( + "label.sequences_selection_not_aligned"), + JvOptionPane.WARNING_MESSAGE); return; } @@@ -3624,8 -3627,9 +3626,9 @@@ public void addSortByOrderMenuItem(String title, final AlignmentOrder order) { - final JMenuItem item = new JMenuItem(MessageManager.formatMessage( - "action.by_title_param", new Object[] { title })); + final JMenuItem item = new JMenuItem(MessageManager + .formatMessage("action.by_title_param", new Object[] + { title })); sort.add(item); item.addActionListener(new java.awt.event.ActionListener() { @@@ -3638,8 -3642,8 +3641,8 @@@ // pointers AlignmentSorter.sortBy(viewport.getAlignment(), order); - addHistoryItem(new OrderCommand(order.getName(), oldOrder, viewport - .getAlignment())); + addHistoryItem(new OrderCommand(order.getName(), oldOrder, + viewport.getAlignment())); alignPanel.paintAlignment(true); } @@@ -3695,7 -3699,8 +3698,8 @@@ return; } - if (viewport.getAlignment().getAlignmentAnnotation().hashCode() != _annotationScoreVectorHash) + if (viewport.getAlignment().getAlignmentAnnotation() + .hashCode() != _annotationScoreVectorHash) { sortByAnnotScore.removeAll(); // almost certainly a quicker way to do this - but we keep it simple @@@ -3738,8 -3743,8 +3742,8 @@@ { sortByTreeMenu.removeAll(); - List comps = PaintRefresher.components.get(viewport - .getSequenceSetId()); + List comps = PaintRefresher.components + .get(viewport.getSequenceSetId()); List treePanels = new ArrayList<>(); for (Component comp : comps) { @@@ -3878,9 -3883,10 +3882,10 @@@ JalviewFileChooser chooser = new JalviewFileChooser( jalview.bin.Cache.getProperty("LAST_DIRECTORY")); chooser.setFileView(new JalviewFileView()); - chooser.setDialogTitle(MessageManager - .getString("label.select_newick_like_tree_file")); - chooser.setToolTipText(MessageManager.getString("label.load_tree_file")); + chooser.setDialogTitle( + MessageManager.getString("label.select_newick_like_tree_file")); + chooser.setToolTipText( + MessageManager.getString("label.load_tree_file")); int value = chooser.showOpenDialog(null); @@@ -3895,20 -3901,17 +3900,17 @@@ viewport.setCurrentTree(showNewickTree(fin, filePath).getTree()); } catch (Exception ex) { - JvOptionPane - .showMessageDialog( - Desktop.desktop, - ex.getMessage(), - MessageManager - .getString("label.problem_reading_tree_file"), - JvOptionPane.WARNING_MESSAGE); + JvOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(), + MessageManager.getString("label.problem_reading_tree_file"), + JvOptionPane.WARNING_MESSAGE); ex.printStackTrace(); } if (fin != null && fin.hasWarningMessage()) { - JvOptionPane.showMessageDialog(Desktop.desktop, fin - .getWarningMessage(), MessageManager - .getString("label.possible_problem_with_tree_file"), + JvOptionPane.showMessageDialog(Desktop.desktop, + fin.getWarningMessage(), + MessageManager + .getString("label.possible_problem_with_tree_file"), JvOptionPane.WARNING_MESSAGE); } } @@@ -4138,9 -4141,9 +4140,9 @@@ } } catch (Exception e) { - Cache.log - .debug("Exception during web service menu building process.", - e); + Cache.log.debug( + "Exception during web service menu building process.", + e); } } }); @@@ -4225,7 -4228,8 +4227,8 @@@ @Override public void actionPerformed(ActionEvent e) { - showProductsFor(af.viewport.getSequenceSelection(), dna, source); + showProductsFor(af.viewport.getSequenceSelection(), dna, + source); } }); showProducts.add(xtype); @@@ -4234,9 -4238,9 +4237,9 @@@ showProducts.setEnabled(showp); } catch (Exception e) { - Cache.log - .warn("canShowProducts threw an exception - please report to help@jalview.org", - e); + Cache.log.warn( + "canShowProducts threw an exception - please report to help@jalview.org", + e); return false; } return showp; @@@ -4253,8 -4257,8 +4256,8 @@@ * @param source * the database to show cross-references for */ - protected void showProductsFor(final SequenceI[] sel, - final boolean _odna, final String source) + protected void showProductsFor(final SequenceI[] sel, final boolean _odna, + final String source) { new Thread(CrossRefAction.showProductsFor(sel, _odna, source, this)) .start(); @@@ -4277,8 -4281,8 +4280,8 @@@ { jalview.bin.Cache.log.error( "Exception during translation. Please report this !", ex); - final String msg = MessageManager - .getString("label.error_when_translating_sequences_submit_bug_report"); + final String msg = MessageManager.getString( + "label.error_when_translating_sequences_submit_bug_report"); final String errorTitle = MessageManager .getString("label.implementation_error") + MessageManager.getString("label.translation_failed"); @@@ -4288,8 -4292,8 +4291,8 @@@ } if (al == null || al.getHeight() == 0) { - final String msg = MessageManager - .getString("label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation"); + final String msg = MessageManager.getString( + "label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation"); final String errorTitle = MessageManager .getString("label.translation_failed"); JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle, @@@ -4299,9 -4303,9 +4302,9 @@@ { AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT); af.setFileFormat(this.currentFileFormat); - final String newTitle = MessageManager.formatMessage( - "label.translation_of_params", - new Object[] { this.getTitle() }); + final String newTitle = MessageManager + .formatMessage("label.translation_of_params", new Object[] + { this.getTitle() }); af.setTitle(newTitle); if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, true)) { @@@ -4399,8 -4403,8 +4402,8 @@@ { // check to see if any of these files have names matching sequences in // the alignment - SequenceIdMatcher idm = new SequenceIdMatcher(viewport - .getAlignment().getSequencesArray()); + SequenceIdMatcher idm = new SequenceIdMatcher( + viewport.getAlignment().getSequencesArray()); /** * Object[] { String,SequenceI} */ @@@ -4462,20 -4466,15 +4465,15 @@@ if (filesmatched.size() > 0) { if (Cache.getDefault("AUTOASSOCIATE_PDBANDSEQS", false) - || JvOptionPane - .showConfirmDialog( - this, - MessageManager - .formatMessage( - "label.automatically_associate_structure_files_with_sequences_same_name", - new Object[] { Integer - .valueOf( - filesmatched - .size()) - .toString() }), - MessageManager - .getString("label.automatically_associate_structure_files_by_name"), - JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION) + || JvOptionPane.showConfirmDialog(this, + MessageManager.formatMessage( + "label.automatically_associate_structure_files_with_sequences_same_name", + new Object[] + { Integer.valueOf(filesmatched.size()) + .toString() }), + MessageManager.getString( + "label.automatically_associate_structure_files_by_name"), + JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION) { for (Object[] fm : filesmatched) @@@ -4491,9 -4490,8 +4489,8 @@@ Desktop.instance); if (pe != null) { - System.err.println("Associated file : " - + ((String) fm[0]) + " with " - + toassoc.getDisplayId(true)); + System.err.println("Associated file : " + ((String) fm[0]) + + " with " + toassoc.getDisplayId(true)); assocfiles++; } } @@@ -4503,24 -4501,18 +4500,18 @@@ } if (filesnotmatched.size() > 0) { - if (assocfiles > 0 - && (Cache.getDefault( - "AUTOASSOCIATE_PDBANDSEQS_IGNOREOTHERS", false) || JvOptionPane - .showConfirmDialog( - this, - "" - + MessageManager - .formatMessage( - "label.ignore_unmatched_dropped_files_info", - new Object[] { Integer - .valueOf( - filesnotmatched - .size()) - .toString() }) - + "", - MessageManager - .getString("label.ignore_unmatched_dropped_files"), - JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION)) + if (assocfiles > 0 && (Cache.getDefault( + "AUTOASSOCIATE_PDBANDSEQS_IGNOREOTHERS", false) + || JvOptionPane.showConfirmDialog(this, + "" + MessageManager.formatMessage( + "label.ignore_unmatched_dropped_files_info", + new Object[] + { Integer.valueOf(filesnotmatched.size()) + .toString() }) + + "", + MessageManager.getString( + "label.ignore_unmatched_dropped_files"), + JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION)) { return; } @@@ -4561,9 -4553,11 +4552,11 @@@ // if the file isn't identified, or not positively identified as some // other filetype (PFAM is default unidentified alignment file type) then // try to parse as annotation. - boolean isAnnotation = (format == null || FileFormat.Pfam - .equals(format)) ? new AnnotationFile() - .annotateAlignmentView(viewport, file, sourceType) : false; + boolean isAnnotation = (format == null + || FileFormat.Pfam.equals(format)) + ? new AnnotationFile().annotateAlignmentView(viewport, + file, sourceType) + : false; if (!isAnnotation) { @@@ -4577,25 -4571,24 +4570,24 @@@ if (tcf.annotateAlignment(viewport.getAlignment(), true)) { buildColourMenu(); - changeColour(new TCoffeeColourScheme(viewport.getAlignment())); + changeColour( + new TCoffeeColourScheme(viewport.getAlignment())); isAnnotation = true; - statusBar - .setText(MessageManager - .getString("label.successfully_pasted_tcoffee_scores_to_alignment")); + statusBar.setText(MessageManager.getString( + "label.successfully_pasted_tcoffee_scores_to_alignment")); } else { // some problem - if no warning its probable that the ID matching // process didn't work - JvOptionPane - .showMessageDialog( - Desktop.desktop, - tcf.getWarningMessage() == null ? MessageManager - .getString("label.check_file_matches_sequence_ids_alignment") - : tcf.getWarningMessage(), - MessageManager - .getString("label.problem_reading_tcoffee_score_file"), - JvOptionPane.WARNING_MESSAGE); + JvOptionPane.showMessageDialog(Desktop.desktop, + tcf.getWarningMessage() == null + ? MessageManager.getString( + "label.check_file_matches_sequence_ids_alignment") + : tcf.getWarningMessage(), + MessageManager.getString( + "label.problem_reading_tcoffee_score_file"), + JvOptionPane.WARNING_MESSAGE); } } else @@@ -4604,9 -4597,9 +4596,9 @@@ } } catch (Exception x) { - Cache.log - .debug("Exception when processing data source as T-COFFEE score file", - x); + Cache.log.debug( + "Exception when processing data source as T-COFFEE score file", + x); tcf = null; } if (tcf == null) @@@ -4620,14 -4613,13 +4612,13 @@@ } if (FileFormat.ScoreMatrix == format) { - ScoreMatrixFile sm = new ScoreMatrixFile(new FileParse(file, - sourceType)); + ScoreMatrixFile sm = new ScoreMatrixFile( + new FileParse(file, sourceType)); sm.parse(); // todo: i18n this message - statusBar - .setText(MessageManager.formatMessage( - "label.successfully_loaded_matrix", - sm.getMatrixName())); + statusBar.setText(MessageManager.formatMessage( + "label.successfully_loaded_matrix", + sm.getMatrixName())); } else if (FileFormat.Jnet.equals(format)) { @@@ -4677,11 -4669,16 +4668,16 @@@ } new OOMWarning( "loading data " - + (sourceType != null ? (sourceType == DataSourceType.PASTE ? "from clipboard." - : "using " + sourceType + " from " + file) + + (sourceType != null + ? (sourceType == DataSourceType.PASTE + ? "from clipboard." + : "using " + sourceType + " from " + + file) : ".") - + (format != null ? "(parsing as '" + format - + "' file)" : ""), oom, Desktop.desktop); + + (format != null + ? "(parsing as '" + format + "' file)" + : ""), + oom, Desktop.desktop); } } @@@ -4732,7 -4729,8 +4728,8 @@@ final AlignViewportI peer = viewport.getCodingComplement(); if (peer != null) { - AlignFrame linkedAlignFrame = ((AlignViewport) peer).getAlignPanel().alignFrame; + AlignFrame linkedAlignFrame = ((AlignViewport) peer) + .getAlignPanel().alignFrame; if (linkedAlignFrame.tabbedPane.getTabCount() > index) { linkedAlignFrame.tabbedPane.setSelectedIndex(index); @@@ -4847,14 -4845,14 +4844,14 @@@ // here final JMenu rfetch = new JMenu( MessageManager.getString("action.fetch_db_references")); - rfetch.setToolTipText(MessageManager - .getString("label.retrieve_parse_sequence_database_records_alignment_or_selected_sequences")); + rfetch.setToolTipText(MessageManager.getString( + "label.retrieve_parse_sequence_database_records_alignment_or_selected_sequences")); webService.add(rfetch); final JCheckBoxMenuItem trimrs = new JCheckBoxMenuItem( MessageManager.getString("option.trim_retrieved_seqs")); - trimrs.setToolTipText(MessageManager - .getString("label.trim_retrieved_sequences")); + trimrs.setToolTipText( + MessageManager.getString("label.trim_retrieved_sequences")); trimrs.setSelected(Cache.getDefault("TRIM_FETCHED_DATASET_SEQS", true)); trimrs.addActionListener(new ActionListener() { @@@ -4869,8 -4867,8 +4866,8 @@@ rfetch.add(trimrs); JMenuItem fetchr = new JMenuItem( MessageManager.getString("label.standard_databases")); - fetchr.setToolTipText(MessageManager - .getString("label.fetch_embl_uniprot")); + fetchr.setToolTipText( + MessageManager.getString("label.fetch_embl_uniprot")); fetchr.addActionListener(new ActionListener() { @@@ -4884,8 -4882,9 +4881,9 @@@ { boolean isNucleotide = alignPanel.alignFrame.getViewport() .getAlignment().isNucleotide(); - DBRefFetcher dbRefFetcher = new DBRefFetcher(alignPanel.av - .getSequenceSelection(), alignPanel.alignFrame, null, + DBRefFetcher dbRefFetcher = new DBRefFetcher( + alignPanel.av.getSequenceSelection(), + alignPanel.alignFrame, null, alignPanel.alignFrame.featureSettings, isNucleotide); dbRefFetcher.addListener(new FetchFinishedListenerI() { @@@ -4988,8 -4987,8 +4986,8 @@@ }); fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true, MessageManager.formatMessage( - "label.fetch_retrieve_from", - new Object[] { src.getDbName() }))); + "label.fetch_retrieve_from", new Object[] + { src.getDbName() }))); dfetch.add(fetchr); comp++; } @@@ -4999,9 -4998,9 +4997,9 @@@ .toArray(new DbSourceProxy[0]); // fetch all entry DbSourceProxy src = otherdb.get(0); - fetchr = new JMenuItem(MessageManager.formatMessage( - "label.fetch_all_param", - new Object[] { src.getDbSource() })); + fetchr = new JMenuItem(MessageManager + .formatMessage("label.fetch_all_param", new Object[] + { src.getDbSource() })); fetchr.addActionListener(new ActionListener() { @Override @@@ -5039,30 -5038,33 +5037,33 @@@ fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true, MessageManager.formatMessage( "label.fetch_retrieve_from_all_sources", - new Object[] { - Integer.valueOf(otherdb.size()) - .toString(), src.getDbSource(), - src.getDbName() }))); + new Object[] + { Integer.valueOf(otherdb.size()) + .toString(), + src.getDbSource(), src.getDbName() }))); dfetch.add(fetchr); comp++; // and then build the rest of the individual menus ifetch = new JMenu(MessageManager.formatMessage( - "label.source_from_db_source", - new Object[] { src.getDbSource() })); + "label.source_from_db_source", new Object[] + { src.getDbSource() })); icomp = 0; String imname = null; int i = 0; for (DbSourceProxy sproxy : otherdb) { String dbname = sproxy.getDbName(); - String sname = dbname.length() > 5 ? dbname.substring(0, - 5) + "..." : dbname; - String msname = dbname.length() > 10 ? dbname.substring( - 0, 10) + "..." : dbname; + String sname = dbname.length() > 5 + ? dbname.substring(0, 5) + "..." + : dbname; + String msname = dbname.length() > 10 + ? dbname.substring(0, 10) + "..." + : dbname; if (imname == null) { - imname = MessageManager.formatMessage( - "label.from_msname", new Object[] { sname }); + imname = MessageManager + .formatMessage("label.from_msname", new Object[] + { sname }); } fetchr = new JMenuItem(msname); final DbSourceProxy[] dassrc = { sproxy }; @@@ -5101,8 -5103,8 +5102,8 @@@ } }); - fetchr.setToolTipText("" - + MessageManager.formatMessage( + fetchr.setToolTipText( + "" + MessageManager.formatMessage( "label.fetch_retrieve_from", new Object[] { dbname })); ifetch.add(fetchr); @@@ -5307,17 -5309,14 +5308,14 @@@ */ public void setDisplayedView(AlignmentPanel alignmentPanel) { - if (!viewport.getSequenceSetId().equals( - alignmentPanel.av.getSequenceSetId())) + if (!viewport.getSequenceSetId() + .equals(alignmentPanel.av.getSequenceSetId())) { - throw new Error( - MessageManager - .getString("error.implementation_error_cannot_show_view_alignment_frame")); + throw new Error(MessageManager.getString( + "error.implementation_error_cannot_show_view_alignment_frame")); } - if (tabbedPane != null - && tabbedPane.getTabCount() > 0 - && alignPanels.indexOf(alignmentPanel) != tabbedPane - .getSelectedIndex()) + if (tabbedPane != null && tabbedPane.getTabCount() > 0 && alignPanels + .indexOf(alignmentPanel) != tabbedPane.getSelectedIndex()) { tabbedPane.setSelectedIndex(alignPanels.indexOf(alignmentPanel)); } @@@ -5420,15 -5419,15 +5418,15 @@@ // show a warning dialog no mapped cDNA return; } - AlignmentI cdna = new Alignment(cdnaSeqs.toArray(new SequenceI[cdnaSeqs - .size()])); + AlignmentI cdna = new Alignment( + cdnaSeqs.toArray(new SequenceI[cdnaSeqs.size()])); GAlignFrame alignFrame = new AlignFrame(cdna, AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT); cdna.alignAs(alignment); String newtitle = "cDNA " + MessageManager.getString("label.for") + " " + this.title; - Desktop.addInternalFrame(alignFrame, newtitle, - AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT); + Desktop.addInternalFrame(alignFrame, newtitle, AlignFrame.DEFAULT_WIDTH, + AlignFrame.DEFAULT_HEIGHT); } /** @@@ -5461,8 -5460,8 +5459,8 @@@ al = dna.reverseCdna(complement); viewport.addAlignment(al, ""); addHistoryItem(new EditCommand( - MessageManager.getString("label.add_sequences"), - Action.PASTE, al.getSequencesArray(), 0, al.getWidth(), + MessageManager.getString("label.add_sequences"), Action.PASTE, + al.getSequencesArray(), 0, al.getWidth(), viewport.getAlignment())); } catch (Exception ex) { @@@ -5489,12 -5488,10 +5487,10 @@@ } catch (Exception ex) { System.err.println((ex.toString())); - JvOptionPane - .showInternalMessageDialog(Desktop.desktop, MessageManager - .getString("label.couldnt_run_groovy_script"), - MessageManager - .getString("label.groovy_support_failed"), - JvOptionPane.ERROR_MESSAGE); + JvOptionPane.showInternalMessageDialog(Desktop.desktop, + MessageManager.getString("label.couldnt_run_groovy_script"), + MessageManager.getString("label.groovy_support_failed"), + JvOptionPane.ERROR_MESSAGE); } } else @@@ -5534,9 -5531,9 +5530,9 @@@ { // include key modifier check in case user selects from menu avc.markHighlightedColumns( - (actionEvent.getModifiers() & ActionEvent.ALT_MASK) != 0, - true, - (actionEvent.getModifiers() & (ActionEvent.META_MASK | ActionEvent.CTRL_MASK)) != 0); + (actionEvent.getModifiers() & ActionEvent.ALT_MASK) != 0, true, + (actionEvent.getModifiers() & (ActionEvent.META_MASK + | ActionEvent.CTRL_MASK)) != 0); } /** @@@ -5551,8 -5548,8 +5547,8 @@@ colourMenu.add(textColour); colourMenu.addSeparator(); - ColourMenuHelper.addMenuItems(colourMenu, this, - viewport.getAlignment(), false); + ColourMenuHelper.addMenuItems(colourMenu, this, viewport.getAlignment(), + false); colourMenu.addSeparator(); colourMenu.add(conservationMenuItem); diff --combined src/jalview/gui/AlignmentPanel.java index fc687b4,922e481..25f44c5 --- a/src/jalview/gui/AlignmentPanel.java +++ b/src/jalview/gui/AlignmentPanel.java @@@ -30,12 -30,10 +30,12 @@@ import jalview.datamodel.SearchResultsI import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; +import jalview.io.HTMLOutput; import jalview.jbgui.GAlignmentPanel; import jalview.math.AlignmentDimension; import jalview.schemes.ResidueProperties; import jalview.structure.StructureSelectionManager; +import jalview.util.Comparison; import jalview.util.MessageManager; import jalview.util.Platform; import jalview.viewmodel.ViewportListenerI; @@@ -72,8 -70,7 +72,7 @@@ import javax.swing.SwingUtilities * @version $Revision: 1.161 $ */ public class AlignmentPanel extends GAlignmentPanel implements - AdjustmentListener, Printable, AlignmentViewPanel, - ViewportListenerI + AdjustmentListener, Printable, AlignmentViewPanel, ViewportListenerI { public AlignViewport av; @@@ -159,8 -156,8 +158,8 @@@ // is initialised if (av.getWrapAlignment()) { - int widthInRes = getSeqPanel().seqCanvas - .getWrappedCanvasWidth(getSeqPanel().seqCanvas.getWidth()); + int widthInRes = getSeqPanel().seqCanvas.getWrappedCanvasWidth( + getSeqPanel().seqCanvas.getWidth()); vpRanges.setViewportWidth(widthInRes); } else @@@ -169,7 -166,7 +168,7 @@@ / av.getCharWidth(); int heightInSeq = getSeqPanel().seqCanvas.getHeight() / av.getCharHeight(); - + vpRanges.setViewportWidth(widthInRes); vpRanges.setViewportHeight(heightInSeq); } @@@ -228,10 -225,10 +227,10 @@@ // to prevent drawing old image FontMetrics fm = getFontMetrics(av.getFont()); - scalePanelHolder.setPreferredSize(new Dimension(10, av.getCharHeight() - + fm.getDescent())); - idSpaceFillerPanel1.setPreferredSize(new Dimension(10, av - .getCharHeight() + fm.getDescent())); + scalePanelHolder.setPreferredSize( + new Dimension(10, av.getCharHeight() + fm.getDescent())); + idSpaceFillerPanel1.setPreferredSize( + new Dimension(10, av.getCharHeight() + fm.getDescent())); getIdPanel().getIdCanvas().gg = null; getSeqPanel().seqCanvas.img = null; @@@ -291,8 -288,8 +290,8 @@@ { Container c = new Container(); - FontMetrics fm = c.getFontMetrics(new Font(av.font.getName(), - Font.ITALIC, av.font.getSize())); + FontMetrics fm = c.getFontMetrics( + new Font(av.font.getName(), Font.ITALIC, av.font.getSize())); AlignmentI al = av.getAlignment(); int i = 0; @@@ -333,8 -330,8 +332,8 @@@ } } - return new Dimension(maxwidth < 0 ? idWidth : Math.min(maxwidth, - idWidth), 12); + return new Dimension( + maxwidth < 0 ? idWidth : Math.min(maxwidth, idWidth), 12); } /** @@@ -343,11 -340,19 +342,11 @@@ */ public void highlightSearchResults(SearchResultsI results) { - scrollToPosition(results); - getSeqPanel().seqCanvas.highlightSearchResults(results); - } + boolean scrolled = scrollToPosition(results, 0, true, false); - /** - * Scroll the view to show the position of the highlighted region in results - * (if any) and redraw the overview - * - * @param results - */ - public boolean scrollToPosition(SearchResultsI results) - { - return scrollToPosition(results, 0, true, false); + boolean noFastPaint = scrolled && av.getWrapAlignment(); + + getSeqPanel().seqCanvas.highlightSearchResults(results, noFastPaint); } /** @@@ -365,10 -370,8 +364,10 @@@ } /** - * Scroll the view to show the position of the highlighted region in results - * (if any) + * Scrolls the view (if necessary) to show the position of the first + * highlighted region in results (if any). Answers true if the view was + * scrolled, or false if no matched region was found, or it is already + * visible. * * @param results * @param verticalOffset @@@ -378,117 -381,116 +377,117 @@@ * - when set, the overview will be recalculated (takes longer) * @param centre * if true, try to centre the search results horizontally in the view - * @return false if results were not found + * @return */ - public boolean scrollToPosition(SearchResultsI results, + protected boolean scrollToPosition(SearchResultsI results, int verticalOffset, boolean redrawOverview, boolean centre) { int startv, endv, starts, ends; - // TODO: properly locate search results in view when large numbers of hidden - // columns exist before highlighted region - // do we need to scroll the panel? - // TODO: tons of nullpointerexceptions raised here. - if (results != null && results.getSize() > 0 && av != null - && av.getAlignment() != null) - { - int seqIndex = av.getAlignment().findIndex(results); - if (seqIndex == -1) - { - return false; - } - SequenceI seq = av.getAlignment().getSequenceAt(seqIndex); - int[] r = results.getResults(seq, 0, av.getAlignment().getWidth()); - if (r == null) - { - return false; - } - int start = r[0]; - int end = r[1]; + if (results == null || results.isEmpty() || av == null + || av.getAlignment() == null) + { + return false; + } + int seqIndex = av.getAlignment().findIndex(results); + if (seqIndex == -1) + { + return false; + } + SequenceI seq = av.getAlignment().getSequenceAt(seqIndex); - /* - * To centre results, scroll to positions half the visible width - * left/right of the start/end positions - */ - if (centre) - { - int offset = (vpRanges.getEndRes() - vpRanges.getStartRes() + 1) / 2 - - 1; - start = Math.max(start - offset, 0); - end = end + offset - 1; - } - if (start < 0) - { - return false; - } - if (end == seq.getEnd()) - { - return false; - } - if (av.hasHiddenColumns()) + int[] r = results.getResults(seq, 0, av.getAlignment().getWidth()); + if (r == null) + { + return false; + } + int start = r[0]; + int end = r[1]; + + /* + * To centre results, scroll to positions half the visible width + * left/right of the start/end positions + */ + if (centre) + { + int offset = (vpRanges.getEndRes() - vpRanges.getStartRes() + 1) / 2 - 1; + start = Math.max(start - offset, 0); + end = end + offset - 1; + } + if (start < 0) + { + return false; + } + if (end == seq.getEnd()) + { + return false; + } + + if (av.hasHiddenColumns()) + { + HiddenColumns hidden = av.getAlignment().getHiddenColumns(); + start = hidden.findColumnPosition(start); + end = hidden.findColumnPosition(end); + if (start == end) { - HiddenColumns hidden = av.getAlignment().getHiddenColumns(); - start = hidden.findColumnPosition(start); - end = hidden.findColumnPosition(end); - if (start == end) + if (!hidden.isVisible(r[0])) { - if (!hidden.isVisible(r[0])) - { - // don't scroll - position isn't visible - return false; - } + // don't scroll - position isn't visible + return false; } } + } - /* - * allow for offset of target sequence (actually scroll to one above it) - */ - seqIndex = Math.max(0, seqIndex - verticalOffset); + /* + * allow for offset of target sequence (actually scroll to one above it) + */ + seqIndex = Math.max(0, seqIndex - verticalOffset); + boolean scrollNeeded = true; - if (!av.getWrapAlignment()) + if (!av.getWrapAlignment()) + { + if ((startv = vpRanges.getStartRes()) >= start) { - if ((startv = vpRanges.getStartRes()) >= start) - { - /* - * Scroll left to make start of search results visible - */ - setScrollValues(start, seqIndex); - } - else if ((endv = vpRanges.getEndRes()) <= end) - { - /* - * Scroll right to make end of search results visible - */ - setScrollValues(startv + end - endv, seqIndex); - } - else if ((starts = vpRanges.getStartSeq()) > seqIndex) - { - /* - * Scroll up to make start of search results visible - */ - setScrollValues(vpRanges.getStartRes(), seqIndex); - } - else if ((ends = vpRanges.getEndSeq()) <= seqIndex) - { - /* - * Scroll down to make end of search results visible - */ - setScrollValues(vpRanges.getStartRes(), - starts + seqIndex - ends + 1); - } /* - * Else results are already visible - no need to scroll + * Scroll left to make start of search results visible */ + setScrollValues(start, seqIndex); } - else + else if ((endv = vpRanges.getEndRes()) <= end) + { + /* + * Scroll right to make end of search results visible + */ + setScrollValues(startv + end - endv, seqIndex); + } + else if ((starts = vpRanges.getStartSeq()) > seqIndex) + { + /* + * Scroll up to make start of search results visible + */ + setScrollValues(vpRanges.getStartRes(), seqIndex); + } + else if ((ends = vpRanges.getEndSeq()) <= seqIndex) { - vpRanges.scrollToWrappedVisible(start); + /* + * Scroll down to make end of search results visible + */ + setScrollValues(vpRanges.getStartRes(), starts + seqIndex - ends + + 1); } + /* + * Else results are already visible - no need to scroll + */ + scrollNeeded = false; + } + else + { + scrollNeeded = vpRanges.scrollToWrappedVisible(start); } paintAlignment(redrawOverview); - return true; + + return scrollNeeded; } /** @@@ -576,8 -578,8 +575,8 @@@ */ if (annotationHeight + alignmentHeight > availableHeight) { - annotationHeight = Math.min(annotationHeight, availableHeight - 2 - * rowHeight); + annotationHeight = Math.min(annotationHeight, + availableHeight - 2 * rowHeight); } } else @@@ -587,8 -589,8 +586,8 @@@ } hscroll.addNotify(); - annotationScroller.setPreferredSize(new Dimension(annotationScroller - .getWidth(), annotationHeight)); + annotationScroller.setPreferredSize( + new Dimension(annotationScroller.getWidth(), annotationHeight)); Dimension e = idPanel.getSize(); alabels.setSize(new Dimension(e.width, annotationHeight)); @@@ -638,8 -640,8 +637,8 @@@ else { int widthInRes = (canvasWidth / av.getCharWidth()) - 1; - int heightInSeq = (getSeqPanel().seqCanvas.getHeight() / av - .getCharHeight()) - 1; + int heightInSeq = (getSeqPanel().seqCanvas.getHeight() + / av.getCharHeight()) - 1; vpRanges.setViewportWidth(widthInRes); vpRanges.setViewportHeight(heightInSeq); @@@ -651,7 -653,6 +650,6 @@@ repaint(); } - /** * Adjust row/column scrollers to show a visible position in the alignment. * @@@ -683,7 -684,8 +681,8 @@@ if (av.hasHiddenColumns()) { // reset the width to exclude hidden columns - width = av.getAlignment().getHiddenColumns().findColumnPosition(width); + width = av.getAlignment().getHiddenColumns() + .findColumnPosition(width); } hextent = getSeqPanel().seqCanvas.getWidth() / av.getCharWidth(); @@@ -825,13 -827,13 +824,13 @@@ { @Override public void run() - { + { // When updating scrolling to use ViewportChange events, this code // could not be validated and it is not clear if it is now being // called. Log warning here in case it is called and unforeseen // problems occur - Cache.log - .warn("Unexpected path through code: Wrapped jar file opened with wrap alignment set in preferences"); + Cache.log.warn( + "Unexpected path through code: Wrapped jar file opened with wrap alignment set in preferences"); // scroll to start of panel vpRanges.setStartRes(0); @@@ -986,7 -988,8 +985,8 @@@ * Get the horizontal offset to where we draw the sequences. * This is idWidth if using a single Graphics context, else zero. */ - final int alignmentGraphicsOffset = idGraphics != alignmentGraphics ? 0 : idWidth; + final int alignmentGraphicsOffset = idGraphics != alignmentGraphics ? 0 + : idWidth; FontMetrics fm = getFontMetrics(av.getFont()); int charHeight = av.getCharHeight(); @@@ -1023,8 -1026,7 +1023,7 @@@ endSeq = alignmentHeight; } - int pagesHigh = ((alignmentHeight / totalSeq) + 1) - * pageHeight; + int pagesHigh = ((alignmentHeight / totalSeq) + 1) * pageHeight; if (av.isShowAnnotation()) { @@@ -1037,8 -1039,7 +1036,7 @@@ { return Printable.NO_SUCH_PAGE; } - final int alignmentDrawnHeight = (endSeq - startSeq) * charHeight - + 3; + final int alignmentDrawnHeight = (endSeq - startSeq) * charHeight + 3; /* * draw the Scale at horizontal offset, then reset to top left (0, 0) @@@ -1087,9 -1088,7 +1085,7 @@@ if (av.isRightAlignIds()) { fm = idGraphics.getFontMetrics(); - xPos = idWidth - - fm.stringWidth(displayId) - - 4; + xPos = idWidth - fm.stringWidth(displayId) - 4; } idGraphics.drawString(displayId, xPos, @@@ -1125,7 -1124,8 +1121,8 @@@ * draw the annotations starting at * (idOffset, alignmentHeight) from (0, scaleHeight) */ - alignmentGraphics.translate(alignmentGraphicsOffset, alignmentDrawnHeight); + alignmentGraphics.translate(alignmentGraphicsOffset, + alignmentDrawnHeight); getAnnotationPanel().renderer.drawComponent(getAnnotationPanel(), av, alignmentGraphics, -1, startRes, endRes + 1); } @@@ -1179,8 -1179,8 +1176,8 @@@ .findColumnPosition(maxwidth) - 1; } - int resWidth = getSeqPanel().seqCanvas.getWrappedCanvasWidth(pwidth - - idWidth); + int resWidth = getSeqPanel().seqCanvas + .getWrappedCanvasWidth(pwidth - idWidth); int totalHeight = cHeight * (maxwidth / resWidth + 1); @@@ -1217,16 -1217,13 +1214,13 @@@ } if (labels != null) { - pg.translate(-3, - ypos + (av.getAlignment().getHeight() * av.getCharHeight())); + pg.translate(-3, ypos + + (av.getAlignment().getHeight() * av.getCharHeight())); pg.setFont(av.getFont()); labels.drawComponent(pg, idWidth); - pg.translate( - +3, - -ypos - - (av.getAlignment().getHeight() * av - .getCharHeight())); + pg.translate(+3, -ypos + - (av.getAlignment().getHeight() * av.getCharHeight())); } ypos += cHeight; @@@ -1276,8 -1273,8 +1270,8 @@@ return calculateIdWidth(-1).width + 4; } Integer idwidth = null; - if (onscreen - || (idwidth = Cache.getIntegerProperty("FIGURE_FIXEDIDWIDTH")) == null) + if (onscreen || (idwidth = Cache + .getIntegerProperty("FIGURE_FIXEDIDWIDTH")) == null) { int w = getIdPanel().getWidth(); return (w > 0 ? w : calculateIdWidth().width + 4); @@@ -1289,15 -1286,15 +1283,15 @@@ { int boarderBottomOffset = 5; long pSessionId = System.currentTimeMillis(); - headless = (System.getProperty("java.awt.headless") != null && System - .getProperty("java.awt.headless").equals("true")); + headless = (System.getProperty("java.awt.headless") != null + && System.getProperty("java.awt.headless").equals("true")); if (alignFrame != null && !headless) { if (file != null) { - alignFrame.setProgressBar(MessageManager.formatMessage( - "status.saving_file", new Object[] { type.getLabel() }), - pSessionId); + alignFrame.setProgressBar(MessageManager + .formatMessage("status.saving_file", new Object[] + { type.getLabel() }), pSessionId); } } try @@@ -1324,9 -1321,9 +1318,9 @@@ } im = new jalview.util.ImageMaker(this, type, imageAction, - aDimension.getWidth(), aDimension.getHeight() - + boarderBottomOffset, file, imageTitle, - alignFrame, pSessionId, headless); + aDimension.getWidth(), + aDimension.getHeight() + boarderBottomOffset, file, + imageTitle, alignFrame, pSessionId, headless); Graphics graphics = im.getGraphics(); if (av.getWrapAlignment()) { @@@ -1342,8 -1339,8 +1336,8 @@@ { if (graphics != null) { - printUnwrapped(aDimension.getWidth(), aDimension.getHeight(), - 0, graphics, graphics); + printUnwrapped(aDimension.getWidth(), aDimension.getHeight(), 0, + graphics, graphics); im.writeImage(); } } @@@ -1388,9 -1385,8 +1382,8 @@@ // this duplicates the calculation in getWrappedHeight but adjusts for // offscreen idWith width = alignFrame.getWidth() - vscroll.getPreferredSize().width - - alignFrame.getInsets().left - - alignFrame.getInsets().right - getVisibleIdWidth() - + getVisibleIdWidth(false); + - alignFrame.getInsets().left - alignFrame.getInsets().right + - getVisibleIdWidth() + getVisibleIdWidth(false); } else { @@@ -1441,33 -1437,35 +1434,33 @@@ { try { - int s, sSize = av.getAlignment().getHeight(), res, - alwidth = av.getAlignment().getWidth(), g, gSize, f, fSize, - sy; + int sSize = av.getAlignment().getHeight(); + int alwidth = av.getAlignment().getWidth(); PrintWriter out = new PrintWriter(new FileWriter(imgMapFile)); - out.println(jalview.io.HTMLOutput.getImageMapHTML()); + out.println(HTMLOutput.getImageMapHTML()); out.println("" + ""); - for (s = 0; s < sSize; s++) + for (int s = 0; s < sSize; s++) { - sy = s * av.getCharHeight() + scaleHeight; + int sy = s * av.getCharHeight() + scaleHeight; SequenceI seq = av.getAlignment().getSequenceAt(s); - SequenceFeature[] features = seq.getSequenceFeatures(); SequenceGroup[] groups = av.getAlignment().findAllGroups(seq); - for (res = 0; res < alwidth; res++) + for (int column = 0; column < alwidth; column++) { - StringBuilder text = new StringBuilder(); + StringBuilder text = new StringBuilder(512); String triplet = null; if (av.getAlignment().isNucleotide()) { - triplet = ResidueProperties.nucleotideName - .get(seq.getCharAt(res) + ""); + triplet = ResidueProperties.nucleotideName.get(seq + .getCharAt(column) + ""); } else { - triplet = ResidueProperties.aa2Triplet - .get(seq.getCharAt(res) + ""); + triplet = ResidueProperties.aa2Triplet.get(seq.getCharAt(column) + + ""); } if (triplet == null) @@@ -1475,73 -1473,84 +1468,73 @@@ continue; } - int alIndex = seq.findPosition(res); - gSize = groups.length; - for (g = 0; g < gSize; g++) + int seqPos = seq.findPosition(column); + int gSize = groups.length; + for (int g = 0; g < gSize; g++) { if (text.length() < 1) { text.append(" res) + if (groups[g].getStartRes() < column + && groups[g].getEndRes() > column) { text.append("
").append(groups[g].getName()) .append(""); } } - if (features != null) + if (text.length() < 1) { - if (text.length() < 1) - { - text.append(" features = seq.findFeatures(column, column); + for (SequenceFeature sf : features) { - - if ((features[f].getBegin() <= seq.findPosition(res)) - && (features[f].getEnd() >= seq.findPosition(res))) + if (sf.isContactFeature()) { - if (features[f].isContactFeature()) - { - if (features[f].getBegin() == seq.findPosition(res) - || features[f].getEnd() == seq - .findPosition(res)) - { - text.append("
").append(features[f].getType()) - .append(" ").append(features[f].getBegin()) - .append(":").append(features[f].getEnd()); - } - } - else + text.append("
").append(sf.getType()).append(" ") + .append(sf.getBegin()).append(":") + .append(sf.getEnd()); + } + else + { + text.append("
"); + text.append(sf.getType()); + String description = sf.getDescription(); + if (description != null + && !sf.getType().equals(description)) { - text.append("
"); - text.append(features[f].getType()); - if (features[f].getDescription() != null && !features[f] - .getType().equals(features[f].getDescription())) - { - text.append(" ").append(features[f].getDescription()); - } - - if (features[f].getValue("status") != null) - { - text.append(" (") - .append(features[f].getValue("status")) - .append(")"); - } + description = description.replace("\"", """); + text.append(" ").append(description); } } - + String status = sf.getStatus(); + if (status != null && !"".equals(status)) + { + text.append(" (").append(status).append(")"); + } + } + if (text.length() > 1) + { + text.append("')\"; onMouseOut=\"toolTip()\"; href=\"#\">"); + out.println(text.toString()); } - } - if (text.length() > 1) - { - text.append("')\"; onMouseOut=\"toolTip()\"; href=\"#\">"); - out.println(text.toString()); } } } @@@ -1810,7 -1819,7 +1803,7 @@@ * @param verticalOffset * the number of visible sequences to show above the mapped region */ - public void scrollToCentre(SearchResultsI sr, int verticalOffset) + protected void scrollToCentre(SearchResultsI sr, int verticalOffset) { /* * To avoid jumpy vertical scrolling (if some sequences are gapped or not @@@ -1888,7 -1897,7 +1881,7 @@@ @Override /** - * Property change event fired when a change is made to the viewport ranges + * Property change event fired when a change is made to the viewport ranges * object associated with this alignment panel's viewport */ public void propertyChange(PropertyChangeEvent evt) diff --combined src/jalview/gui/AnnotationExporter.java index 42913de,beb77ca..a619997 --- a/src/jalview/gui/AnnotationExporter.java +++ b/src/jalview/gui/AnnotationExporter.java @@@ -34,7 -34,6 +34,7 @@@ import java.awt.Color import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.List; import java.util.Map; import javax.swing.BorderFactory; @@@ -95,8 -94,8 +95,8 @@@ public class AnnotationExporter extend public void exportAnnotations(AlignmentPanel ap) { this.ap = ap; - annotations = ap.av.isShowAnnotation() ? null : ap.av.getAlignment() - .getAlignmentAnnotation(); + annotations = ap.av.isShowAnnotation() ? null + : ap.av.getAlignment().getAlignmentAnnotation(); wholeView = true; startExportAnnotation(); } @@@ -124,9 -123,9 +124,9 @@@ jalview.bin.Cache.getProperty("LAST_DIRECTORY")); chooser.setFileView(new JalviewFileView()); - chooser.setDialogTitle(features ? MessageManager - .getString("label.save_features_to_file") : MessageManager - .getString("label.save_annotation_to_file")); + chooser.setDialogTitle(features + ? MessageManager.getString("label.save_features_to_file") + : MessageManager.getString("label.save_annotation_to_file")); chooser.setToolTipText(MessageManager.getString("action.save")); int value = chooser.showSaveDialog(this); @@@ -157,22 -156,28 +157,22 @@@ .getString("label.no_features_on_alignment"); if (features) { - Map displayedFeatureColours = ap - .getFeatureRenderer().getDisplayedFeatureCols(); FeaturesFile formatter = new FeaturesFile(); SequenceI[] sequences = ap.av.getAlignment().getSequencesArray(); Map featureColours = ap.getFeatureRenderer() .getDisplayedFeatureCols(); + List featureGroups = ap.getFeatureRenderer() + .getDisplayedFeatureGroups(); boolean includeNonPositional = ap.av.isShowNPFeats(); if (GFFFormat.isSelected()) { - text = new FeaturesFile().printGffFormat( - ap.av.getAlignment().getDataset().getSequencesArray(), - displayedFeatureColours, true, ap.av.isShowNPFeats()); - text = formatter.printGffFormat(sequences, featureColours, true, - includeNonPositional); + text = formatter.printGffFormat(sequences, featureColours, + featureGroups, includeNonPositional); } else { - text = new FeaturesFile().printJalviewFormat( - ap.av.getAlignment().getDataset().getSequencesArray(), - displayedFeatureColours, true, ap.av.isShowNPFeats()); // ap.av.featuresDisplayed); - text = formatter.printJalviewFormat(sequences, featureColours, true, - includeNonPositional); + text = formatter.printJalviewFormat(sequences, featureColours, + featureGroups, includeNonPositional); } } else @@@ -205,23 -210,23 +205,23 @@@ { String text = getFileContents(); cap.setText(text); - Desktop.addInternalFrame( - cap, - (features ? MessageManager.formatMessage( - "label.features_for_params", - new String[] { ap.alignFrame.getTitle() }) - : MessageManager.formatMessage( - "label.annotations_for_params", - new String[] { ap.alignFrame.getTitle() })), + Desktop.addInternalFrame(cap, (features ? MessageManager + .formatMessage("label.features_for_params", new String[] + { ap.alignFrame.getTitle() }) + : MessageManager.formatMessage("label.annotations_for_params", + new String[] + { ap.alignFrame.getTitle() })), 600, 500); } catch (OutOfMemoryError oom) { new OOMWarning((features ? MessageManager.formatMessage( - "label.generating_features_for_params", - new String[] { ap.alignFrame.getTitle() }) + "label.generating_features_for_params", new String[] + { ap.alignFrame.getTitle() }) : MessageManager.formatMessage( "label.generating_annotations_for_params", - new String[] { ap.alignFrame.getTitle() })), oom); + new String[] + { ap.alignFrame.getTitle() })), + oom); cap.dispose(); } diff --combined src/jalview/gui/AppVarna.java index 079645f,1bbe8d8..ea16f23 --- a/src/jalview/gui/AppVarna.java +++ b/src/jalview/gui/AppVarna.java @@@ -61,9 -61,9 +61,9 @@@ import fr.orsay.lri.varna.models.annota import fr.orsay.lri.varna.models.rna.ModeleBase; import fr.orsay.lri.varna.models.rna.RNA; - public class AppVarna extends JInternalFrame implements SelectionListener, - SecondaryStructureListener, InterfaceVARNASelectionListener, - VamsasSource + public class AppVarna extends JInternalFrame + implements SelectionListener, SecondaryStructureListener, + InterfaceVARNASelectionListener, VamsasSource { private static final byte[] PAIRS = new byte[] { '(', ')', '[', ']', '{', '}', '<', '>' }; @@@ -177,12 -177,15 +177,15 @@@ { this(ap); - String sname = aa.sequenceRef == null ? "secondary structure (alignment)" + String sname = aa.sequenceRef == null + ? "secondary structure (alignment)" : seq.getName() + " structure"; String theTitle = sname - + (aa.sequenceRef == null ? " trimmed to " + seq.getName() : ""); + + (aa.sequenceRef == null ? " trimmed to " + seq.getName() + : ""); theTitle = MessageManager.formatMessage("label.varna_params", - new String[] { theTitle }); + new String[] + { theTitle }); setTitle(theTitle); String gappedTitle = sname + " (with gaps)"; @@@ -190,7 -193,8 +193,8 @@@ addModel(gappedModel, gappedTitle); String trimmedTitle = "trimmed " + sname; - RnaModel trimmedModel = new RnaModel(trimmedTitle, aa, seq, null, false); + RnaModel trimmedModel = new RnaModel(trimmedTitle, aa, seq, null, + false); addModel(trimmedModel, trimmedTitle); vab.setSelectedIndex(0); } @@@ -424,8 -428,8 +428,8 @@@ end = shift.shift(end); } selectionHighlighter.highlightRegion(rna, start, end); - selectionHighlighter.getLastHighlight().setOutlineColor( - seqsel.getOutlineColour()); + selectionHighlighter.getLastHighlight() + .setOutlineColor(seqsel.getOutlineColour()); // TODO - translate column markings to positions on structure if present. vab.updateSelectedRNA(rna); } @@@ -460,7 -464,8 +464,8 @@@ } @Override - public void onSelectionChanged(BaseList arg0, BaseList arg1, BaseList arg2) + public void onSelectionChanged(BaseList arg0, BaseList arg1, + BaseList arg2) { // TODO translate selected regions in VARNA to a selection on the // alignpanel. @@@ -577,7 -582,8 +582,8 @@@ { if (!model.ann.isValidStruc()) { - throw new IllegalArgumentException("Invalid RNA structure annotation"); + throw new IllegalArgumentException( + "Invalid RNA structure annotation"); } /* @@@ -622,10 -628,11 +628,10 @@@ ShiftList offset = new ShiftList(); int ofstart = -1; int sleng = seq.getLength(); for (int i = 0; i < sleng; i++) { - if (Comparison.isGap(seqChars[i])) + if (Comparison.isGap(seq.getCharAt(i))) { if (ofstart == -1) { @@@ -686,7 -693,8 +692,8 @@@ { if (!model.ann.isValidStruc()) { - throw new IllegalArgumentException("Invalid RNA structure annotation"); + throw new IllegalArgumentException( + "Invalid RNA structure annotation"); } try diff --combined src/jalview/gui/CutAndPasteTransfer.java index 3eced2f,7b8ade6..2a96daf --- a/src/jalview/gui/CutAndPasteTransfer.java +++ b/src/jalview/gui/CutAndPasteTransfer.java @@@ -140,8 -140,8 +140,8 @@@ public class CutAndPasteTransfer extend chooser.setAcceptAllFileFilterUsed(false); chooser.setFileView(new JalviewFileView()); - chooser.setDialogTitle(MessageManager - .getString("label.save_text_to_file")); + chooser.setDialogTitle( + MessageManager.getString("label.save_text_to_file")); chooser.setToolTipText(MessageManager.getString("action.save")); int value = chooser.showSaveDialog(this); @@@ -150,8 -150,8 +150,8 @@@ { try { - PrintWriter out = new PrintWriter(new FileWriter( - chooser.getSelectedFile())); + PrintWriter out = new PrintWriter( + new FileWriter(chooser.getSelectedFile())); out.print(getText()); out.close(); @@@ -196,8 -196,8 +196,8 @@@ try { - textarea.append((String) contents - .getTransferData(DataFlavor.stringFlavor)); + textarea.append( + (String) contents.getTransferData(DataFlavor.stringFlavor)); } catch (Exception ex) { } @@@ -228,8 -228,8 +228,8 @@@ } if (format == null) { - System.err.println(MessageManager - .getString("label.couldnt_read_data")); + System.err + .println(MessageManager.getString("label.couldnt_read_data")); if (!Jalview.isHeadlessMode()) { JvOptionPane.showInternalMessageDialog(Desktop.desktop, @@@ -253,16 -253,16 +253,16 @@@ { JvOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager .formatMessage("label.couldnt_read_pasted_text", new String[] - { ex.toString() }), MessageManager - .getString("label.error_parsing_text"), + { ex.toString() }), + MessageManager.getString("label.error_parsing_text"), JvOptionPane.WARNING_MESSAGE); } if (al != null && al.hasValidSequence()) { - String title = MessageManager.formatMessage( - "label.input_cut_paste_params", - new String[] { format.getName() }); + String title = MessageManager + .formatMessage("label.input_cut_paste_params", new String[] + { format.getName() }); FeatureSettingsModelI proxyColourScheme = source .getFeatureColourScheme(); @@@ -298,9 -298,8 +298,9 @@@ AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT); af.getViewport().setShowSequenceFeatures(showSeqFeatures); af.getViewport().setFeaturesDisplayed(fd); - ColourSchemeI cs = ColourSchemeMapper - .getJalviewColourScheme(colourSchemeName, al); + af.setMenusForViewport(); + ColourSchemeI cs = ColourSchemeMapper.getJalviewColourScheme( + colourSchemeName, al); if (cs != null) { af.changeColour(cs); @@@ -327,8 -326,8 +327,8 @@@ try { - af.setMaximum(jalview.bin.Cache.getDefault("SHOW_FULLSCREEN", - false)); + af.setMaximum( + jalview.bin.Cache.getDefault("SHOW_FULLSCREEN", false)); } catch (Exception ex) { } @@@ -336,8 -335,8 +336,8 @@@ } else { - System.err.println(MessageManager - .getString("label.couldnt_read_data")); + System.err + .println(MessageManager.getString("label.couldnt_read_data")); if (!Jalview.isHeadlessMode()) { JvOptionPane.showInternalMessageDialog(Desktop.desktop, diff --combined src/jalview/gui/FeatureColourChooser.java index 192fd23,396df04..b27328d --- a/src/jalview/gui/FeatureColourChooser.java +++ b/src/jalview/gui/FeatureColourChooser.java @@@ -31,8 -31,6 +31,8 @@@ import java.awt.Dimension import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; @@@ -119,8 -117,9 +119,9 @@@ public class FeatureColourChooser exten this.fr = frender; this.type = theType; ap = fr.ap; - String title = MessageManager.formatMessage( - "label.graduated_color_for_params", new String[] { theType }); + String title = MessageManager + .formatMessage("label.graduated_color_for_params", new String[] + { theType }); initDialogFrame(this, true, blocking, title, 480, 185); slider.addChangeListener(new ChangeListener() @@@ -207,7 -206,8 +208,8 @@@ slider.setEnabled(true); slider.setValue((int) (cs.getThreshold() * scaleFactor)); thresholdValue.setEnabled(true); - threshline = new GraphLine((max - min) / 2f, "Threshold", Color.black); + threshline = new GraphLine((max - min) / 2f, "Threshold", + Color.black); threshline.value = cs.getThreshold(); } @@@ -288,28 -288,20 +290,28 @@@ thresholdValue_actionPerformed(); } }); + thresholdValue.addFocusListener(new FocusAdapter() + { + @Override + public void focusLost(FocusEvent e) + { + thresholdValue_actionPerformed(); + } + }); slider.setPaintLabels(false); slider.setPaintTicks(true); slider.setBackground(Color.white); slider.setEnabled(false); slider.setOpaque(false); slider.setPreferredSize(new Dimension(100, 32)); - slider.setToolTipText(MessageManager - .getString("label.adjust_threshold")); + slider.setToolTipText( + MessageManager.getString("label.adjust_threshold")); thresholdValue.setEnabled(false); thresholdValue.setColumns(7); jPanel3.setBackground(Color.white); thresholdIsMin.setBackground(Color.white); - thresholdIsMin.setText(MessageManager - .getString("label.threshold_minmax")); + thresholdIsMin + .setText(MessageManager.getString("label.threshold_minmax")); thresholdIsMin.setToolTipText(MessageManager .getString("label.toggle_absolute_relative_display_threshold")); thresholdIsMin.addActionListener(new ActionListener() @@@ -323,9 -315,8 +325,8 @@@ colourByLabel.setBackground(Color.white); colourByLabel .setText(MessageManager.getString("label.colour_by_label")); - colourByLabel - .setToolTipText(MessageManager - .getString("label.display_features_same_type_different_label_using_different_colour")); + colourByLabel.setToolTipText(MessageManager.getString( + "label.display_features_same_type_different_label_using_different_colour")); colourByLabel.addActionListener(new ActionListener() { @Override @@@ -443,7 -434,8 +444,8 @@@ /* * todo not yet implemented: visual indication of feature threshold */ - threshline = new GraphLine((max - min) / 2f, "Threshold", Color.black); + threshline = new GraphLine((max - min) / 2f, "Threshold", + Color.black); } if (hasThreshold) @@@ -606,8 -598,8 +608,8 @@@ { if (colourEditor != null) { - System.err - .println("IMPLEMENTATION ISSUE: overwriting action listener for FeatureColourChooser"); + System.err.println( + "IMPLEMENTATION ISSUE: overwriting action listener for FeatureColourChooser"); } colourEditor = graduatedColorEditor; } diff --combined src/jalview/gui/FeatureRenderer.java index d580eaf,358798d..17f5a71 --- a/src/jalview/gui/FeatureRenderer.java +++ b/src/jalview/gui/FeatureRenderer.java @@@ -41,7 -41,6 +41,7 @@@ import java.awt.event.ItemEvent import java.awt.event.ItemListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.List; @@@ -64,8 -63,8 +64,8 @@@ import javax.swing.event.DocumentListen * @author $author$ * @version $Revision$ */ - public class FeatureRenderer extends - jalview.renderer.seqfeatures.FeatureRenderer + public class FeatureRenderer + extends jalview.renderer.seqfeatures.FeatureRenderer { /* * defaults for creating a new feature are the last created @@@ -235,27 -234,19 +235,26 @@@ if (!create && features.size() > 1) { /* - * more than one feature at selected position - add a drop-down - * to choose the feature to amend + * more than one feature at selected position - + * add a drop-down to choose the feature to amend + * space pad text if necessary to make entries distinct */ gridPanel = new JPanel(new GridLayout(4, 1)); JPanel choosePanel = new JPanel(); - choosePanel.add(new JLabel(MessageManager - .getString("label.select_feature") - + ":")); + choosePanel.add(new JLabel( + MessageManager.getString("label.select_feature") + ":")); final JComboBox overlaps = new JComboBox(); + List added = new ArrayList<>(); for (SequenceFeature sf : features) { - String text = sf.getType() + "/" + sf.getBegin() + "-" + sf.getEnd() - + " (" + sf.getFeatureGroup() + ")"; + String text = String.format("%s/%d-%d (%s)", sf.getType(), + sf.getBegin(), sf.getEnd(), sf.getFeatureGroup()); + while (added.contains(text)) + { + text += " "; + } overlaps.addItem(text); + added.add(text); } choosePanel.add(overlaps); @@@ -279,15 -270,15 +278,14 @@@ highlight.addResult(sequences.get(0), sf.getBegin(), sf.getEnd()); - alignPanel.getSeqPanel().seqCanvas - .highlightSearchResults(highlight); - + alignPanel.getSeqPanel().seqCanvas.highlightSearchResults( + highlight, false); - } FeatureColourI col = getFeatureStyle(name.getText()); if (col == null) { - col = new FeatureColour(ColorUtils - .createColourFromName(name.getText())); + col = new FeatureColour( + ColorUtils.createColourFromName(name.getText())); } oldcol = fcol = col; updateColourButton(mainPanel, colour, col); @@@ -324,9 -315,8 +322,8 @@@ mainPanel.add(gridPanel, BorderLayout.NORTH); JPanel descriptionPanel = new JPanel(); - descriptionPanel.add(new JLabel(MessageManager - .getString("label.description:"), - JLabel.RIGHT)); + descriptionPanel.add(new JLabel( + MessageManager.getString("label.description:"), JLabel.RIGHT)); description.setFont(JvSwingUtils.getTextAreaFont()); description.setLineWrap(true); descriptionPanel.add(new JScrollPane(description)); @@@ -380,10 -370,11 +377,11 @@@ MessageManager.getString("action.cancel") }; } - String title = create ? MessageManager - .getString("label.create_new_sequence_features") + String title = create + ? MessageManager.getString("label.create_new_sequence_features") : MessageManager.formatMessage("label.amend_delete_features", - new String[] { sequences.get(0).getName() }); + new String[] + { sequences.get(0).getName() }); /* * show the dialog @@@ -395,10 -386,7 +393,10 @@@ FeaturesFile ffile = new FeaturesFile(); - String enteredType = name.getText().trim(); + final String enteredType = name.getText().trim(); + final String enteredGroup = group.getText().trim(); + final String enteredDescription = description.getText().replaceAll("\n", " "); + if (reply == JvOptionPane.OK_OPTION && enteredType.length() > 0) { /* @@@ -407,7 -395,7 +405,7 @@@ if (useLastDefaults) { lastFeatureAdded = enteredType; - lastFeatureGroupAdded = group.getText().trim(); + lastFeatureGroupAdded = enteredGroup; // TODO: determine if the null feature group is valid if (lastFeatureGroupAdded.length() < 1) { @@@ -433,37 -421,26 +431,37 @@@ { /* * YES_OPTION corresponds to the Amend button - * need to refresh Feature Settings if type, group or colour changed + * need to refresh Feature Settings if type, group or colour changed; + * note we don't force the feature to be visible - the user has been + * warned if a hidden feature type or group was entered */ - sf.type = enteredType; - sf.featureGroup = group.getText().trim(); - sf.description = description.getText().replaceAll("\n", " "); - boolean refreshSettings = (!featureType.equals(sf.type) - || !featureGroup.equals(sf.featureGroup)); + boolean refreshSettings = (!featureType.equals(enteredType) || !featureGroup + .equals(enteredGroup)); refreshSettings |= (fcol != oldcol); - - setColour(sf.type, fcol); - + setColour(enteredType, fcol); + int newBegin = sf.begin; + int newEnd = sf.end; try { - sf.begin = ((Integer) start.getValue()).intValue(); - sf.end = ((Integer) end.getValue()).intValue(); + newBegin = ((Integer) start.getValue()).intValue(); + newEnd = ((Integer) end.getValue()).intValue(); } catch (NumberFormatException ex) { + // JSpinner doesn't accept invalid format data :-) } - ffile.parseDescriptionHTML(sf, false); + /* + * replace the feature by deleting it and adding a new one + * (to ensure integrity of SequenceFeatures data store) + */ + sequences.get(0).deleteFeature(sf); + SequenceFeature newSf = new SequenceFeature(sf, enteredType, + newBegin, newEnd, enteredGroup, sf.getScore()); + newSf.setDescription(enteredDescription); + ffile.parseDescriptionHTML(newSf, false); + // amend features dialog only updates one sequence at a time + sequences.get(0).addSequenceFeature(newSf); + if (refreshSettings) { featuresAdded(); @@@ -478,11 -455,12 +476,11 @@@ for (int i = 0; i < sequences.size(); i++) { SequenceFeature sf = features.get(i); - sf.type = enteredType; - // fix for JAL-1538 - always set feature group here - sf.featureGroup = group.getText().trim(); - sf.description = description.getText().replaceAll("\n", " "); - sequences.get(i).addSequenceFeature(sf); - ffile.parseDescriptionHTML(sf, false); + SequenceFeature sf2 = new SequenceFeature(enteredType, + enteredDescription, sf.getBegin(), sf.getEnd(), + enteredGroup); + ffile.parseDescriptionHTML(sf2, false); + sequences.get(i).addSequenceFeature(sf2); } setColour(enteredType, fcol); @@@ -536,7 -514,8 +534,8 @@@ { String msg = MessageManager.formatMessage("label.warning_hidden", MessageManager.getString("label.group"), group); - JvOptionPane.showMessageDialog(panel, msg, "", JvOptionPane.OK_OPTION); + JvOptionPane.showMessageDialog(panel, msg, "", + JvOptionPane.OK_OPTION); } } diff --combined src/jalview/gui/FeatureSettings.java index 45b6b0d,109d0b6..bd74db5 --- a/src/jalview/gui/FeatureSettings.java +++ b/src/jalview/gui/FeatureSettings.java @@@ -23,7 -23,7 +23,7 @@@ package jalview.gui import jalview.api.FeatureColourI; import jalview.api.FeatureSettingsControllerI; import jalview.bin.Cache; -import jalview.datamodel.SequenceFeature; +import jalview.datamodel.AlignmentI; import jalview.datamodel.SequenceI; import jalview.gui.Help.HelpId; import jalview.io.JalviewFileChooser; @@@ -97,8 -97,8 +97,8 @@@ import javax.swing.table.AbstractTableM import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellRenderer; - public class FeatureSettings extends JPanel implements - FeatureSettingsControllerI + public class FeatureSettings extends JPanel + implements FeatureSettingsControllerI { DasSourceBrowser dassourceBrowser; @@@ -142,8 -142,8 +142,8 @@@ this.af = af; fr = af.getFeatureRenderer(); // allow transparency to be recovered - transparency.setMaximum(100 - (int) ((originalTransparency = fr - .getTransparency()) * 100)); + transparency.setMaximum(100 + - (int) ((originalTransparency = fr.getTransparency()) * 100)); try { @@@ -291,16 -291,17 +291,17 @@@ } frame.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT)); - frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter() - { - @Override - public void internalFrameClosed( - javax.swing.event.InternalFrameEvent evt) - { - fr.removePropertyChangeListener(change); - dassourceBrowser.fs = null; - }; - }); + frame.addInternalFrameListener( + new javax.swing.event.InternalFrameAdapter() + { + @Override + public void internalFrameClosed( + javax.swing.event.InternalFrameEvent evt) + { + fr.removePropertyChangeListener(change); + dassourceBrowser.fs = null; + }; + }); frame.setLayer(JLayeredPane.PALETTE_LAYER); } @@@ -310,8 -311,9 +311,9 @@@ { final FeatureColourI featureColour = (FeatureColourI) typeCol; - JPopupMenu men = new JPopupMenu(MessageManager.formatMessage( - "label.settings_for_param", new String[] { type })); + JPopupMenu men = new JPopupMenu(MessageManager + .formatMessage("label.settings_for_param", new String[] + { type })); JMenuItem scr = new JMenuItem( MessageManager.getString("label.sort_by_score")); men.add(scr); @@@ -322,8 -324,9 +324,9 @@@ @Override public void actionPerformed(ActionEvent e) { - me.af.avc.sortAlignmentByFeatureScore(Arrays - .asList(new String[] { type })); + me.af.avc + .sortAlignmentByFeatureScore(Arrays.asList(new String[] + { type })); } }); @@@ -335,8 -338,9 +338,9 @@@ @Override public void actionPerformed(ActionEvent e) { - me.af.avc.sortAlignmentByFeatureDensity(Arrays - .asList(new String[] { type })); + me.af.avc + .sortAlignmentByFeatureDensity(Arrays.asList(new String[] + { type })); } }); @@@ -406,8 -410,7 +410,7 @@@ else { // probably the color chooser! - table.setValueAt( - new FeatureColour(colorChooser.getColor()), + table.setValueAt(new FeatureColour(colorChooser.getColor()), selectedRow, 1); table.validate(); me.updateFeatureRenderer( @@@ -431,8 -434,8 +434,8 @@@ false, type); } }); - JMenuItem clearCols = new JMenuItem( - MessageManager.getString("label.select_columns_not_containing")); + JMenuItem clearCols = new JMenuItem(MessageManager + .getString("label.select_columns_not_containing")); clearCols.addActionListener(new ActionListener() { @Override @@@ -475,26 -478,50 +478,26 @@@ private boolean handlingUpdate = false; /** - * contains a float[3] for each feature type string. created by setTableData + * holds {featureCount, totalExtent} for each feature type */ Map typeWidth = null; @Override synchronized public void discoverAllFeatureData() { - Vector allFeatures = new Vector(); - Vector allGroups = new Vector(); - SequenceFeature[] tmpfeatures; - String group; - for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++) - { - tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i) - .getSequenceFeatures(); - if (tmpfeatures == null) - { - continue; - } + Set allGroups = new HashSet(); + AlignmentI alignment = af.getViewport().getAlignment(); - int index = 0; - while (index < tmpfeatures.length) + for (int i = 0; i < alignment.getHeight(); i++) + { + SequenceI seq = alignment.getSequenceAt(i); + for (String group : seq.getFeatures().getFeatureGroups(true)) { - if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0) + if (group != null && !allGroups.contains(group)) { - index++; - continue; + allGroups.add(group); + checkGroupState(group); } - - if (tmpfeatures[index].getFeatureGroup() != null) - { - group = tmpfeatures[index].featureGroup; - if (!allGroups.contains(group)) - { - allGroups.addElement(group); - checkGroupState(group); - } - } - - if (!allFeatures.contains(tmpfeatures[index].getType())) - { - allFeatures.addElement(tmpfeatures[index].getType()); - } - index++; } } @@@ -548,7 -575,7 +551,7 @@@ synchronized void resetTable(String[] groupChanged) { - if (resettingTable == true) + if (resettingTable) { return; } @@@ -556,59 -583,71 +559,59 @@@ typeWidth = new Hashtable(); // TODO: change avWidth calculation to 'per-sequence' average and use long // rather than float - float[] avWidth = null; - SequenceFeature[] tmpfeatures; - String group = null, type; - Vector visibleChecks = new Vector(); + + Set displayableTypes = new HashSet(); Set foundGroups = new HashSet(); - // Find out which features should be visible depending on which groups - // are selected / deselected - // and recompute average width ordering + /* + * determine which feature types may be visible depending on + * which groups are selected, and recompute average width data + */ for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++) { - tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i) - .getSequenceFeatures(); - if (tmpfeatures == null) - { - continue; - } + SequenceI seq = af.getViewport().getAlignment().getSequenceAt(i); - int index = 0; - while (index < tmpfeatures.length) + /* + * get the sequence's groups for positional features + * and keep track of which groups are visible + */ + Set groups = seq.getFeatures().getFeatureGroups(true); + Set visibleGroups = new HashSet(); + for (String group : groups) { - group = tmpfeatures[index].featureGroup; - foundGroups.add(group); - - if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0) - { - index++; - continue; - } - if (group == null || checkGroupState(group)) { - type = tmpfeatures[index].getType(); - if (!visibleChecks.contains(type)) - { - visibleChecks.addElement(type); - } - } - if (!typeWidth.containsKey(tmpfeatures[index].getType())) - { - typeWidth.put(tmpfeatures[index].getType(), - avWidth = new float[3]); + visibleGroups.add(group); } - else - { - avWidth = typeWidth.get(tmpfeatures[index].getType()); - } - avWidth[0]++; - if (tmpfeatures[index].getBegin() > tmpfeatures[index].getEnd()) - { - avWidth[1] += 1 + tmpfeatures[index].getBegin() - - tmpfeatures[index].getEnd(); - } - else + } + foundGroups.addAll(groups); + + /* + * get distinct feature types for visible groups + * record distinct visible types, and their count and total length + */ + Set types = seq.getFeatures().getFeatureTypesForGroups(true, + visibleGroups.toArray(new String[visibleGroups.size()])); + for (String type : types) + { + displayableTypes.add(type); + float[] avWidth = typeWidth.get(type); + if (avWidth == null) { - avWidth[1] += 1 + tmpfeatures[index].getEnd() - - tmpfeatures[index].getBegin(); + avWidth = new float[2]; + typeWidth.put(type, avWidth); } - index++; + // todo this could include features with a non-visible group + // - do we greatly care? + // todo should we include non-displayable features here, and only + // update when features are added? + avWidth[0] += seq.getFeatures().getFeatureCount(true, type); + avWidth[1] += seq.getFeatures().getTotalFeatureLength(type); } } - int fSize = visibleChecks.size(); - Object[][] data = new Object[fSize][3]; + Object[][] data = new Object[displayableTypes.size()][3]; int dataIndex = 0; if (fr.hasRenderOrder()) @@@ -624,29 -663,28 +627,29 @@@ List frl = fr.getRenderOrder(); for (int ro = frl.size() - 1; ro > -1; ro--) { - type = frl.get(ro); + String type = frl.get(ro); - if (!visibleChecks.contains(type)) + if (!displayableTypes.contains(type)) { continue; } data[dataIndex][0] = type; data[dataIndex][1] = fr.getFeatureStyle(type); - data[dataIndex][2] = new Boolean(af.getViewport() - .getFeaturesDisplayed().isVisible(type)); + data[dataIndex][2] = new Boolean( + af.getViewport().getFeaturesDisplayed().isVisible(type)); dataIndex++; - visibleChecks.removeElement(type); + displayableTypes.remove(type); } } - fSize = visibleChecks.size(); - for (int i = 0; i < fSize; i++) + /* + * process any extra features belonging only to + * a group which was just selected + */ + while (!displayableTypes.isEmpty()) { - // These must be extra features belonging to the group - // which was just selected - type = visibleChecks.elementAt(i).toString(); + String type = displayableTypes.iterator().next(); data[dataIndex][0] = type; data[dataIndex][1] = fr.getFeatureStyle(type); @@@ -659,7 -697,6 +662,7 @@@ data[dataIndex][2] = new Boolean(true); dataIndex++; + displayableTypes.remove(type); } if (originalData == null) @@@ -678,8 -715,8 +681,8 @@@ table.setModel(new FeatureTableModel(data)); table.getColumnModel().getColumn(0).setPreferredWidth(200); - groupPanel.setLayout(new GridLayout(fr.getFeatureGroupsSize() / 4 + 1, - 4)); + groupPanel.setLayout( + new GridLayout(fr.getFeatureGroupsSize() / 4 + 1, 4)); pruneGroups(foundGroups); groupPanel.validate(); @@@ -800,8 -837,8 +803,8 @@@ JalviewFileChooser chooser = new JalviewFileChooser("fc", "Sequence Feature Colours"); chooser.setFileView(new JalviewFileView()); - chooser.setDialogTitle(MessageManager - .getString("label.load_feature_colours")); + chooser.setDialogTitle( + MessageManager.getString("label.load_feature_colours")); chooser.setToolTipText(MessageManager.getString("action.load")); int value = chooser.showOpenDialog(this); @@@ -812,8 -849,8 +815,8 @@@ try { - InputStreamReader in = new InputStreamReader(new FileInputStream( - file), "UTF-8"); + InputStreamReader in = new InputStreamReader( + new FileInputStream(file), "UTF-8"); JalviewUserColours jucs = JalviewUserColours.unmarshal(in); @@@ -892,8 -929,8 +895,8 @@@ JalviewFileChooser chooser = new JalviewFileChooser("fc", "Sequence Feature Colours"); chooser.setFileView(new JalviewFileView()); - chooser.setDialogTitle(MessageManager - .getString("label.save_feature_colours")); + chooser.setDialogTitle( + MessageManager.getString("label.save_feature_colours")); chooser.setToolTipText(MessageManager.getString("action.save")); int value = chooser.showSaveDialog(this); @@@ -935,13 -972,13 +938,13 @@@ col.setRGB(Format.getHexString(fcol.getMaxColour())); col.setMin(fcol.getMin()); col.setMax(fcol.getMax()); - col.setMinRGB(jalview.util.Format.getHexString(fcol - .getMinColour())); + col.setMinRGB( + jalview.util.Format.getHexString(fcol.getMinColour())); col.setAutoScale(fcol.isAutoScaled()); col.setThreshold(fcol.getThreshold()); col.setColourByLabel(fcol.isColourByLabel()); - col.setThreshType(fcol.isAboveThreshold() ? "ABOVE" : (fcol - .isBelowThreshold() ? "BELOW" : "NONE")); + col.setThreshType(fcol.isAboveThreshold() ? "ABOVE" + : (fcol.isBelowThreshold() ? "BELOW" : "NONE")); } ucs.addColour(col); } @@@ -1144,8 -1181,8 +1147,8 @@@ } }); sortByDens.setFont(JvSwingUtils.getLabelFont()); - sortByDens.setText(MessageManager - .getString("label.sequence_sort_by_density")); + sortByDens.setText( + MessageManager.getString("label.sequence_sort_by_density")); sortByDens.addActionListener(new ActionListener() { @Override @@@ -1239,8 -1276,8 +1242,8 @@@ }); transparency.setMaximum(70); - transparency.setToolTipText(MessageManager - .getString("label.transparency_tip")); + transparency.setToolTipText( + MessageManager.getString("label.transparency_tip")); fetchDAS.setText(MessageManager.getString("label.fetch_das_features")); fetchDAS.addActionListener(new ActionListener() { @@@ -1450,15 -1487,10 +1453,10 @@@ public void noDasSourceActive() { complete(); - JvOptionPane - .showInternalConfirmDialog( - Desktop.desktop, - MessageManager - .getString("label.no_das_sources_selected_warn"), - MessageManager - .getString("label.no_das_sources_selected_title"), - JvOptionPane.DEFAULT_OPTION, - JvOptionPane.INFORMATION_MESSAGE); + JvOptionPane.showInternalConfirmDialog(Desktop.desktop, + MessageManager.getString("label.no_das_sources_selected_warn"), + MessageManager.getString("label.no_das_sources_selected_title"), + JvOptionPane.DEFAULT_OPTION, JvOptionPane.INFORMATION_MESSAGE); } // /////////////////////////////////////////////////////////////////////// @@@ -1555,9 -1587,8 +1553,8 @@@ } @Override - public Component getTableCellRendererComponent(JTable tbl, - Object color, boolean isSelected, boolean hasFocus, int row, - int column) + public Component getTableCellRendererComponent(JTable tbl, Object color, + boolean isSelected, boolean hasFocus, int row, int column) { FeatureColourI cellColour = (FeatureColourI) color; // JLabel comp = new JLabel(); @@@ -1765,8 -1796,8 +1762,8 @@@ class FeatureIcon implements Ico } } - class ColorEditor extends AbstractCellEditor implements TableCellEditor, - ActionListener + class ColorEditor extends AbstractCellEditor + implements TableCellEditor, ActionListener { FeatureSettings me; diff --combined src/jalview/gui/Finder.java index 5c917ae,f526592..84540f4 --- a/src/jalview/gui/Finder.java +++ b/src/jalview/gui/Finder.java @@@ -101,14 -101,15 +101,15 @@@ public class Finder extends GFinde frame = new JInternalFrame(); frame.setContentPane(this); frame.setLayer(JLayeredPane.PALETTE_LAYER); - frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter() - { - @Override - public void internalFrameClosing(InternalFrameEvent e) - { - closeAction(); - } - }); + frame.addInternalFrameListener( + new javax.swing.event.InternalFrameAdapter() + { + @Override + public void internalFrameClosing(InternalFrameEvent e) + { + closeAction(); + } + }); addEscapeHandler(); Desktop.addInternalFrame(frame, MessageManager.getString("label.find"), MY_WIDTH, MY_HEIGHT); @@@ -121,8 -122,8 +122,8 @@@ */ private void addEscapeHandler() { - getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( - KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "Cancel"); + getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW) + .put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "Cancel"); getRootPane().getActionMap().put("Cancel", new AbstractAction() { @Override @@@ -133,7 -134,6 +134,6 @@@ }); } - /** * Performs the 'Find Next' action. * @@@ -223,9 -223,8 +223,9 @@@ for (SearchResultMatchI match : searchResults.getResults()) { seqs.add(match.getSequence().getDatasetSequence()); - features.add(new SequenceFeature(searchString, desc, null, - match.getStart(), match.getEnd(), desc)); + features.add(new SequenceFeature(searchString, desc, + match + .getStart(), match.getEnd(), desc)); } if (ap.getSeqPanel().seqCanvas.getFeatureRenderer().amendFeatures(seqs, @@@ -316,8 -315,8 +316,8 @@@ if (doFindAll) { // then we report the matches that were found - String message = (idMatch.size() > 0) ? "" + idMatch.size() - + " IDs" : ""; + String message = (idMatch.size() > 0) ? "" + idMatch.size() + " IDs" + : ""; if (searchResults != null) { if (idMatch.size() > 0 && searchResults.getSize() > 0) diff --combined src/jalview/gui/IdPanel.java index 1271fa3,4ccfb2f..3cc0ed3 --- a/src/jalview/gui/IdPanel.java +++ b/src/jalview/gui/IdPanel.java @@@ -48,8 -48,8 +48,8 @@@ import javax.swing.ToolTipManager * @author $author$ * @version $Revision$ */ - public class IdPanel extends JPanel implements MouseListener, - MouseMotionListener, MouseWheelListener + public class IdPanel extends JPanel + implements MouseListener, MouseMotionListener, MouseWheelListener { private IdCanvas idCanvas; @@@ -293,8 -293,8 +293,8 @@@ } if ((av.getSelectionGroup() == null) - || (!jalview.util.Platform.isControlDown(e) && !e.isShiftDown() && av - .getSelectionGroup() != null)) + || (!jalview.util.Platform.isControlDown(e) && !e.isShiftDown() + && av.getSelectionGroup() != null)) { av.setSelectionGroup(new SequenceGroup()); av.getSelectionGroup().setStartRes(0); @@@ -325,19 -325,23 +325,19 @@@ { int seq2 = alignPanel.getSeqPanel().findSeq(e); Sequence sq = (Sequence) av.getAlignment().getSequenceAt(seq2); - // build a new links menu based on the current links + any non-positional - // features + + /* + * build a new links menu based on the current links + * and any non-positional features + */ List nlinks = Preferences.sequenceUrlLinks.getLinksForMenu(); - SequenceFeature sfs[] = sq == null ? null : sq.getSequenceFeatures(); - if (sfs != null) + for (SequenceFeature sf : sq.getFeatures().getNonPositionalFeatures()) { - for (SequenceFeature sf : sfs) + if (sf.links != null) { - if (sf.begin == sf.end && sf.begin == 0) + for (String link : sf.links) { - if (sf.links != null && sf.links.size() > 0) - { - for (int l = 0, lSize = sf.links.size(); l < lSize; l++) - { - nlinks.add(sf.links.elementAt(l)); - } - } + nlinks.add(link); } } } @@@ -391,8 -395,8 +391,8 @@@ for (int i = start; i <= end; i++) { - av.getSelectionGroup().addSequence( - av.getAlignment().getSequenceAt(i), i == end); + av.getSelectionGroup().addSequence(av.getAlignment().getSequenceAt(i), + i == end); } } diff --combined src/jalview/gui/Jalview2XML.java index d625918,4c2b8b6..1658f0f88 --- a/src/jalview/gui/Jalview2XML.java +++ b/src/jalview/gui/Jalview2XML.java @@@ -32,7 -32,6 +32,7 @@@ import jalview.datamodel.AlignmentI import jalview.datamodel.GraphLine; import jalview.datamodel.PDBEntry; import jalview.datamodel.RnaViewerModel; +import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; import jalview.datamodel.StructureViewerModel; @@@ -361,7 -360,8 +361,8 @@@ public class Jalview2XM } public SeqFref newAlcodMapRef(final String sref, - final AlignedCodonFrame _cf, final jalview.datamodel.Mapping _jmap) + final AlignedCodonFrame _cf, + final jalview.datamodel.Mapping _jmap) { SeqFref fref = new SeqFref(sref, "Codon Frame") @@@ -413,8 -413,8 +414,8 @@@ } } catch (Exception x) { - System.err - .println("IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence " + System.err.println( + "IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence " + ref.getSref()); x.printStackTrace(); failedtoresolve++; @@@ -437,9 -437,9 +438,9 @@@ } if (incompleteSeqs != null && incompleteSeqs.size() > 0) { - System.err.println("Jalview Project Import: There are " - + incompleteSeqs.size() - + " sequences which may have incomplete metadata."); + System.err.println( + "Jalview Project Import: There are " + incompleteSeqs.size() + + " sequences which may have incomplete metadata."); if (incompleteSeqs.size() < 10) { for (SequenceI s : incompleteSeqs.values()) @@@ -449,8 -449,8 +450,8 @@@ } else { - System.err - .println("Too many to report. Skipping output of incomplete sequences."); + System.err.println( + "Too many to report. Skipping output of incomplete sequences."); } } } @@@ -560,9 -560,8 +561,8 @@@ { AlignFrame af = frames.get(i); // skip ? - if (skipList != null - && skipList - .containsKey(af.getViewport().getSequenceSetId())) + if (skipList != null && skipList + .containsKey(af.getViewport().getSequenceSetId())) { continue; } @@@ -582,8 -581,8 +582,8 @@@ saveState(apanel, fileName, jout, viewIds); - String dssid = getDatasetIdRef(af.getViewport().getAlignment() - .getDataset()); + String dssid = getDatasetIdRef( + af.getViewport().getAlignment().getDataset()); if (!dsses.containsKey(dssid)) { dsses.put(dssid, af); @@@ -629,8 -628,8 +629,8 @@@ if (shortName.indexOf(File.separatorChar) > -1) { - shortName = shortName.substring(shortName - .lastIndexOf(File.separatorChar) + 1); + shortName = shortName + .substring(shortName.lastIndexOf(File.separatorChar) + 1); } int count = 1; @@@ -763,8 -762,8 +763,8 @@@ object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel()); object.setCreationDate(new java.util.Date(System.currentTimeMillis())); - object.setVersion(jalview.bin.Cache.getDefault("VERSION", - "Development Build")); + object.setVersion( + jalview.bin.Cache.getDefault("VERSION", "Development Build")); /** * rjal is full height alignment, jal is actual alignment with full metadata @@@ -857,8 -856,8 +857,8 @@@ if (av.hasHiddenRows()) { // use rjal, contains the full height alignment - jseq.setHidden(av.getAlignment().getHiddenSequences() - .isHidden(jds)); + jseq.setHidden( + av.getAlignment().getHiddenSequences().isHidden(jds)); if (av.isHiddenRepSequence(jds)) { @@@ -883,43 -882,48 +883,43 @@@ // TODO: omit sequence features from each alignment view's XML dump if we // are storing dataset - if (jds.getSequenceFeatures() != null) + List sfs = jds + .getSequenceFeatures(); + for (SequenceFeature sf : sfs) { - jalview.datamodel.SequenceFeature[] sf = jds.getSequenceFeatures(); - int index = 0; - while (index < sf.length) - { - Features features = new Features(); + Features features = new Features(); - features.setBegin(sf[index].getBegin()); - features.setEnd(sf[index].getEnd()); - features.setDescription(sf[index].getDescription()); - features.setType(sf[index].getType()); - features.setFeatureGroup(sf[index].getFeatureGroup()); - features.setScore(sf[index].getScore()); - if (sf[index].links != null) + features.setBegin(sf.getBegin()); + features.setEnd(sf.getEnd()); + features.setDescription(sf.getDescription()); + features.setType(sf.getType()); + features.setFeatureGroup(sf.getFeatureGroup()); + features.setScore(sf.getScore()); + if (sf.links != null) + { + for (int l = 0; l < sf.links.size(); l++) { - for (int l = 0; l < sf[index].links.size(); l++) - { - OtherData keyValue = new OtherData(); - keyValue.setKey("LINK_" + l); - keyValue.setValue(sf[index].links.elementAt(l).toString()); - features.addOtherData(keyValue); - } + OtherData keyValue = new OtherData(); + keyValue.setKey("LINK_" + l); + keyValue.setValue(sf.links.elementAt(l).toString()); + features.addOtherData(keyValue); } - if (sf[index].otherDetails != null) + } + if (sf.otherDetails != null) + { + String key; + Iterator keys = sf.otherDetails.keySet().iterator(); + while (keys.hasNext()) { - String key; - Iterator keys = sf[index].otherDetails.keySet() - .iterator(); - while (keys.hasNext()) - { - key = keys.next(); - OtherData keyValue = new OtherData(); - keyValue.setKey(key); - keyValue.setValue(sf[index].otherDetails.get(key).toString()); - features.addOtherData(keyValue); - } + key = keys.next(); + OtherData keyValue = new OtherData(); + keyValue.setKey(key); + keyValue.setValue(sf.otherDetails.get(key).toString()); + features.addOtherData(keyValue); } - - jseq.addFeatures(features); - index++; } + + jseq.addFeatures(features); } if (jdatasq.getAllPDBEntries() != null) @@@ -948,8 -952,8 +948,8 @@@ if (frames[f] instanceof StructureViewerBase) { StructureViewerBase viewFrame = (StructureViewerBase) frames[f]; - matchedFile = saveStructureState(ap, jds, pdb, entry, - viewIds, matchedFile, viewFrame); + matchedFile = saveStructureState(ap, jds, pdb, entry, viewIds, + matchedFile, viewFrame); /* * Only store each structure viewer's state once in the project * jar. First time through only (storeDS==false) @@@ -965,8 -969,8 +965,8 @@@ viewerState.getBytes()); } catch (IOException e) { - System.err.println("Error saving viewer state: " - + e.getMessage()); + System.err.println( + "Error saving viewer state: " + e.getMessage()); } } } @@@ -1038,8 -1042,8 +1038,8 @@@ { AlcodMap alcmap = new AlcodMap(); alcmap.setDnasq(seqHash(dnas[m])); - alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null, - false)); + alcmap.setMapping( + createVamsasMapping(pmaps[m], dnas[m], null, false)); alc.addAlcodMap(alcmap); hasMap = true; } @@@ -1176,16 -1180,15 +1176,15 @@@ ColourSchemeI colourScheme = sg.getColourScheme(); if (colourScheme != null) { - ResidueShaderI groupColourScheme = sg - .getGroupColourScheme(); + ResidueShaderI groupColourScheme = sg.getGroupColourScheme(); if (groupColourScheme.conservationApplied()) { jGroup.setConsThreshold(groupColourScheme.getConservationInc()); if (colourScheme instanceof jalview.schemes.UserColourScheme) { - jGroup.setColour(setUserColourScheme(colourScheme, - userColours, jms)); + jGroup.setColour( + setUserColourScheme(colourScheme, userColours, jms)); } else { @@@ -1201,8 -1204,8 +1200,8 @@@ } else if (colourScheme instanceof jalview.schemes.UserColourScheme) { - jGroup.setColour(setUserColourScheme(colourScheme, - userColours, jms)); + jGroup.setColour( + setUserColourScheme(colourScheme, userColours, jms)); } else { @@@ -1237,8 -1240,8 +1236,8 @@@ // /////////SAVE VIEWPORT Viewport view = new Viewport(); view.setTitle(ap.alignFrame.getTitle()); - view.setSequenceSetId(makeHashCode(av.getSequenceSetId(), - av.getSequenceSetId())); + view.setSequenceSetId( + makeHashCode(av.getSequenceSetId(), av.getSequenceSetId())); view.setId(av.getViewId()); if (av.getCodingComplement() != null) { @@@ -1276,7 -1279,8 +1275,8 @@@ view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(), userColours, jms)); } - else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient) + else if (av + .getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient) { AnnotationColours ac = constructAnnotationColours( (jalview.schemes.AnnotationColourGradient) av @@@ -1288,8 -1292,8 +1288,8 @@@ } else { - view.setBgColour(ColourSchemeProperty.getColourName(av - .getGlobalColourScheme())); + view.setBgColour(ColourSchemeProperty + .getColourName(av.getGlobalColourScheme())); } ResidueShaderI vcs = av.getResidueShading(); @@@ -1364,16 -1368,16 +1364,16 @@@ setting.setAutoScale(fcol.isAutoScaled()); setting.setThreshold(fcol.getThreshold()); // -1 = No threshold, 0 = Below, 1 = Above - setting.setThreshstate(fcol.isAboveThreshold() ? 1 : (fcol - .isBelowThreshold() ? 0 : -1)); + setting.setThreshstate(fcol.isAboveThreshold() ? 1 + : (fcol.isBelowThreshold() ? 0 : -1)); } else { setting.setColour(fcol.getColour().getRGB()); } - setting.setDisplay(av.getFeaturesDisplayed().isVisible( - featureType)); + setting.setDisplay( + av.getFeaturesDisplayed().isVisible(featureType)); float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer() .getOrder(featureType); if (rorder > -1) @@@ -1400,7 -1404,7 +1400,7 @@@ g.setName(grp); g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas .getFeatureRenderer().checkGroupVisibility(grp, false)) - .booleanValue()); + .booleanValue()); fs.addGroup(g); groupsAdded.addElement(grp); } @@@ -1417,8 -1421,7 +1417,7 @@@ } else { - ArrayList hiddenRegions = hidden - .getHiddenColumnsCopy(); + ArrayList hiddenRegions = hidden.getHiddenColumnsCopy(); for (int[] region : hiddenRegions) { HiddenColumns hc = new HiddenColumns(); @@@ -1459,8 -1462,8 +1458,8 @@@ System.out.println("Writing jar entry " + fileName); JarEntry entry = new JarEntry(fileName); jout.putNextEntry(entry); - PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout, - UTF_8)); + PrintWriter pout = new PrintWriter( + new OutputStreamWriter(jout, UTF_8)); Marshaller marshaller = new Marshaller(pout); marshaller.marshal(object); pout.flush(); @@@ -1661,8 -1664,8 +1660,8 @@@ final PDBEntry pdbentry = bindingModel.getPdbEntry(peid); final String pdbId = pdbentry.getId(); if (!pdbId.equals(entry.getId()) - && !(entry.getId().length() > 4 && entry.getId() - .toLowerCase().startsWith(pdbId.toLowerCase()))) + && !(entry.getId().length() > 4 && entry.getId().toLowerCase() + .startsWith(pdbId.toLowerCase()))) { /* * not interested in a binding to a different PDB entry here @@@ -1675,8 -1678,8 +1674,8 @@@ } else if (!matchedFile.equals(pdbentry.getFile())) { - Cache.log - .warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): " + Cache.log.warn( + "Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): " + pdbentry.getFile()); } // record the @@@ -1685,7 -1688,8 +1684,8 @@@ // match is ambiguous (e.g. // 1QIP==1qipA) - for (int smap = 0; smap < viewFrame.getBinding().getSequence()[peid].length; smap++) + for (int smap = 0; smap < viewFrame.getBinding() + .getSequence()[peid].length; smap++) { // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1) if (jds == viewFrame.getBinding().getSequence()[peid][smap]) @@@ -1729,12 -1733,13 +1729,13 @@@ ac.setAnnotation(acg.getAnnotation().annotationId); if (acg.getBaseColour() instanceof UserColourScheme) { - ac.setColourScheme(setUserColourScheme(acg.getBaseColour(), - userColours, jms)); + ac.setColourScheme( + setUserColourScheme(acg.getBaseColour(), userColours, jms)); } else { - ac.setColourScheme(ColourSchemeProperty.getColourName(acg.getBaseColour())); + ac.setColourScheme( + ColourSchemeProperty.getColourName(acg.getBaseColour())); } ac.setMaxColour(acg.getMaxColour().getRGB()); @@@ -1777,11 -1782,10 +1778,10 @@@ if (groupIdr == null) { // make a locally unique String - groupRefs.put( - annotation.groupRef, + groupRefs.put(annotation.groupRef, groupIdr = ("" + System.currentTimeMillis() - + annotation.groupRef.getName() + groupRefs - .size())); + + annotation.groupRef.getName() + + groupRefs.size())); } an.setGroupRef(groupIdr.toString()); } @@@ -1861,7 -1865,8 +1861,8 @@@ } if (annotation.annotations[a].displayCharacter != null) { - ae.setDisplayCharacter(annotation.annotations[a].displayCharacter); + ae.setDisplayCharacter( + annotation.annotations[a].displayCharacter); } if (!Float.isNaN(annotation.annotations[a].value)) @@@ -1872,8 -1877,8 +1873,8 @@@ ae.setPosition(a); if (annotation.annotations[a].secondaryStructure > ' ') { - ae.setSecondaryStructure(annotation.annotations[a].secondaryStructure - + ""); + ae.setSecondaryStructure( + annotation.annotations[a].secondaryStructure + ""); } if (annotation.annotations[a].colour != null @@@ -1935,8 -1940,8 +1936,8 @@@ // need to be able to recover 1) settings 2) user-defined presets or // recreate settings from preset 3) predefined settings provided by // service - or settings that can be transferred (or discarded) - vCalcIdParam.setParameters(settings.getWsParamFile().replace("\n", - "|\\n|")); + vCalcIdParam.setParameters( + settings.getWsParamFile().replace("\n", "|\\n|")); vCalcIdParam.setAutoUpdate(settings.isAutoUpdate()); // todo - decide if updateImmediately is needed for any projects. @@@ -1996,8 -2001,8 +1997,8 @@@ } } throw new Error(MessageManager.formatMessage( - "error.unsupported_version_calcIdparam", - new Object[] { calcIdParam.toString() })); + "error.unsupported_version_calcIdparam", new Object[] + { calcIdParam.toString() })); } /** @@@ -2239,8 -2244,8 +2240,8 @@@ for (int i = 0; i < 24; i++) { - newColours[i] = new java.awt.Color(Integer.parseInt(colours - .getUserColourScheme().getColour(i).getRGB(), 16)); + newColours[i] = new java.awt.Color(Integer.parseInt( + colours.getUserColourScheme().getColour(i).getRGB(), 16)); } jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme( @@@ -2251,8 -2256,9 +2252,9 @@@ newColours = new java.awt.Color[23]; for (int i = 0; i < 23; i++) { - newColours[i] = new java.awt.Color(Integer.parseInt(colours - .getUserColourScheme().getColour(i + 24).getRGB(), 16)); + newColours[i] = new java.awt.Color(Integer.parseInt( + colours.getUserColourScheme().getColour(i + 24).getRGB(), + 16)); } ucs.setLowerCaseColours(newColours); } @@@ -2406,8 -2412,8 +2408,8 @@@ if (true) // !skipViewport(object)) { _af = loadFromObject(object, file, true, jprovider); - if (_af != null - && object.getJalviewModelSequence().getViewportCount() > 0) + if (_af != null && object.getJalviewModelSequence() + .getViewportCount() > 0) { if (af == null) { @@@ -2439,8 -2445,8 +2441,8 @@@ { ex.printStackTrace(); errorMessage = "Couldn't locate Jalview XML file : " + file; - System.err.println("Exception whilst loading jalview XML file : " - + ex + "\n"); + System.err.println( + "Exception whilst loading jalview XML file : " + ex + "\n"); } catch (Exception ex) { System.err.println("Parsing as Jalview Version 2 file failed."); @@@ -2469,8 -2475,8 +2471,8 @@@ } ex.printStackTrace(); - System.err.println("Exception whilst loading jalview XML file : " - + ex + "\n"); + System.err.println( + "Exception whilst loading jalview XML file : " + ex + "\n"); } catch (OutOfMemoryError e) { // Don't use the OOM Window here @@@ -2496,8 -2502,9 +2498,9 @@@ { if (ds.getCodonFrames() != null) { - StructureSelectionManager.getStructureSelectionManager( - Desktop.instance).registerMappings(ds.getCodonFrames()); + StructureSelectionManager + .getStructureSelectionManager(Desktop.instance) + .registerMappings(ds.getCodonFrames()); } } if (errorMessage != null) @@@ -2647,12 -2654,11 +2650,11 @@@ @Override public void run() { - JvOptionPane - .showInternalMessageDialog(Desktop.desktop, - finalErrorMessage, "Error " - + (saving ? "saving" : "loading") - + " Jalview file", - JvOptionPane.WARNING_MESSAGE); + JvOptionPane.showInternalMessageDialog(Desktop.desktop, + finalErrorMessage, + "Error " + (saving ? "saving" : "loading") + + " Jalview file", + JvOptionPane.WARNING_MESSAGE); } }); } @@@ -2854,8 -2860,8 +2856,8 @@@ if (tmpSeq.getStart() != jseqs[i].getStart() || tmpSeq.getEnd() != jseqs[i].getEnd()) { - System.err - .println("Warning JAL-2154 regression: updating start/end for sequence " + System.err.println( + "Warning JAL-2154 regression: updating start/end for sequence " + tmpSeq.toString() + " to " + jseqs[i]); } } @@@ -2928,7 -2934,8 +2930,8 @@@ } else { - boolean isdsal = object.getJalviewModelSequence().getViewportCount() == 0; + boolean isdsal = object.getJalviewModelSequence() + .getViewportCount() == 0; if (isdsal) { // we are importing a dataset record, so @@@ -2981,11 -2988,12 +2984,11 @@@ Features[] features = jseqs[i].getFeatures(); for (int f = 0; f < features.length; f++) { - jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature( - features[f].getType(), features[f].getDescription(), - features[f].getStatus(), features[f].getBegin(), - features[f].getEnd(), features[f].getFeatureGroup()); - - sf.setScore(features[f].getScore()); + SequenceFeature sf = new SequenceFeature(features[f].getType(), + features[f].getDescription(), features[f].getBegin(), + features[f].getEnd(), features[f].getScore(), + features[f].getFeatureGroup()); + sf.setStatus(features[f].getStatus()); for (int od = 0; od < features[f].getOtherDataCount(); od++) { OtherData keyValue = features[f].getOtherData(od); @@@ -3007,7 -3015,8 +3010,8 @@@ { // adds dbrefs to datasequence's set (since Jalview 2.10) addDBRefs( - al.getSequenceAt(i).getDatasetSequence() == null ? al.getSequenceAt(i) + al.getSequenceAt(i).getDatasetSequence() == null + ? al.getSequenceAt(i) : al.getSequenceAt(i).getDatasetSequence(), vamsasSeq[i]); } @@@ -3052,8 -3061,9 +3056,9 @@@ } } } - StructureSelectionManager.getStructureSelectionManager( - Desktop.instance).registerPDBEntry(entry); + StructureSelectionManager + .getStructureSelectionManager(Desktop.instance) + .registerPDBEntry(entry); // adds PDBEntry to datasequence's set (since Jalview 2.10) if (al.getSequenceAt(i).getDatasetSequence() != null) { @@@ -3098,8 -3108,8 +3103,8 @@@ else { // defer to later - frefedSequence.add(newAlcodMapRef(maps[m].getDnasq(), cf, - mapping)); + frefedSequence.add( + newAlcodMapRef(maps[m].getDnasq(), cf, mapping)); } } } @@@ -3140,9 -3150,8 +3145,8 @@@ annotation.setAutoCalculated(true); } } - if (autoForView - || (annotation.hasAutoCalculated() && annotation - .isAutoCalculated())) + if (autoForView || (annotation.hasAutoCalculated() + && annotation.isAutoCalculated())) { // remove ID - we don't recover annotation from other views for // view-specific annotation @@@ -3184,10 -3193,12 +3188,12 @@@ anot[anpos] = new jalview.datamodel.Annotation( - ae[aa].getDisplayCharacter(), ae[aa].getDescription(), - (ae[aa].getSecondaryStructure() == null || ae[aa] - .getSecondaryStructure().length() == 0) ? ' ' - : ae[aa].getSecondaryStructure().charAt(0), + ae[aa].getDisplayCharacter(), ae[aa].getDescription(), + (ae[aa].getSecondaryStructure() == null + || ae[aa].getSecondaryStructure().length() == 0) + ? ' ' + : ae[aa].getSecondaryStructure() + .charAt(0), ae[aa].getValue() ); @@@ -3221,10 -3232,11 +3227,11 @@@ jaa._linecolour = firstColour; if (annotation.getThresholdLine() != null) { - jaa.setThreshold(new jalview.datamodel.GraphLine(annotation - .getThresholdLine().getValue(), annotation - .getThresholdLine().getLabel(), new java.awt.Color( - annotation.getThresholdLine().getColour()))); + jaa.setThreshold(new jalview.datamodel.GraphLine( + annotation.getThresholdLine().getValue(), + annotation.getThresholdLine().getLabel(), + new java.awt.Color( + annotation.getThresholdLine().getColour()))); } if (autoForView || annotation.isAutoCalculated()) @@@ -3355,7 -3367,8 +3362,8 @@@ } else { - cs = ColourSchemeProperty.getColourScheme(al, jGroup.getColour()); + cs = ColourSchemeProperty.getColourScheme(al, + jGroup.getColour()); } } int pidThreshold = jGroup.getPidThreshold(); @@@ -3382,13 -3395,15 +3390,15 @@@ jGroup.getDisplayBoxes(), jGroup.getDisplayText(), jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd()); sg.getGroupColourScheme().setThreshold(pidThreshold, true); - sg.getGroupColourScheme().setConservationInc(jGroup.getConsThreshold()); + sg.getGroupColourScheme() + .setConservationInc(jGroup.getConsThreshold()); sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour())); sg.textColour = new java.awt.Color(jGroup.getTextCol1()); sg.textColour2 = new java.awt.Color(jGroup.getTextCol2()); - sg.setShowNonconserved(jGroup.hasShowUnconserved() ? jGroup - .isShowUnconserved() : false); + sg.setShowNonconserved( + jGroup.hasShowUnconserved() ? jGroup.isShowUnconserved() + : false); sg.thresholdTextColour = jGroup.getTextColThreshold(); if (jGroup.hasShowConsensusHistogram()) { @@@ -3409,8 -3424,8 +3419,8 @@@ } if (jGroup.getConsThreshold() != 0) { - Conservation c = new Conservation("All", sg.getSequences(null), - 0, sg.getWidth() - 1); + Conservation c = new Conservation("All", sg.getSequences(null), 0, + sg.getWidth() - 1); c.calculate(); c.verdict(false, 25); sg.cs.setConservation(c); @@@ -3419,8 -3434,8 +3429,8 @@@ if (jGroup.getId() != null && groupAnnotRefs.size() > 0) { // re-instate unique group/annotation row reference - List jaal = groupAnnotRefs.get(jGroup - .getId()); + List jaal = groupAnnotRefs + .get(jGroup.getId()); if (jaal != null) { for (AlignmentAnnotation jaa : jaal) @@@ -3466,8 -3481,8 +3476,8 @@@ // to the same sequenceSet. We must modify this id on load // so that each load of the file gives a unique id String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix; - String viewId = (view.getId() == null ? null : view.getId() - + uniqueSetSuffix); + String viewId = (view.getId() == null ? null + : view.getId() + uniqueSetSuffix); AlignFrame af = null; AlignViewport av = null; // now check to see if we really need to create a new viewport. @@@ -3480,8 -3495,8 +3490,8 @@@ // XML. // and then recover its containing af to allow the settings to be applied. // TODO: fix for vamsas demo - System.err - .println("About to recover a viewport for existing alignment: Sequence set ID is " + System.err.println( + "About to recover a viewport for existing alignment: Sequence set ID is " + uniqueSeqSetId); Object seqsetobj = retrieveExistingObj(uniqueSeqSetId); if (seqsetobj != null) @@@ -3489,14 -3504,14 +3499,14 @@@ if (seqsetobj instanceof String) { uniqueSeqSetId = (String) seqsetobj; - System.err - .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is " + System.err.println( + "Recovered extant sequence set ID mapping for ID : New Sequence set ID is " + uniqueSeqSetId); } else { - System.err - .println("Warning : Collision between sequence set ID string and existing jalview object mapping."); + System.err.println( + "Warning : Collision between sequence set ID string and existing jalview object mapping."); } } @@@ -3505,8 -3520,8 +3515,8 @@@ * indicate that annotation colours are applied across all groups (pre * Jalview 2.8.1 behaviour) */ - boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan( - "2.8.1", object.getVersion()); + boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan("2.8.1", + object.getVersion()); AlignmentPanel ap = null; boolean isnewview = true; @@@ -3581,15 -3596,15 +3591,15 @@@ for (int i = 0; i < jseq.getRnaViewerCount(); i++) { RnaViewer viewer = jseq.getRnaViewer(i); - AppVarna appVarna = findOrCreateVarnaViewer(viewer, - uniqueSetSuffix, ap); + AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix, + ap); for (int j = 0; j < viewer.getSecondaryStructureCount(); j++) { SecondaryStructure ss = viewer.getSecondaryStructure(j); SequenceI seq = seqRefIds.get(jseq.getId()); - AlignmentAnnotation ann = this.annotationIds.get(ss - .getAnnotationId()); + AlignmentAnnotation ann = this.annotationIds + .get(ss.getAnnotationId()); /* * add the structure to the Varna display (with session state copied @@@ -3643,10 -3658,9 +3653,9 @@@ /* * viewer not found - make it */ - RnaViewerModel model = new RnaViewerModel(postLoadId, - viewer.getTitle(), viewer.getXpos(), viewer.getYpos(), - viewer.getWidth(), viewer.getHeight(), - viewer.getDividerLocation()); + RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(), + viewer.getXpos(), viewer.getYpos(), viewer.getWidth(), + viewer.getHeight(), viewer.getDividerLocation()); AppVarna varna = new AppVarna(model, ap); return varna; @@@ -3690,8 -3704,8 +3699,8 @@@ // TODO: should check if tp has been manipulated by user - if so its // settings shouldn't be modified tp.setTitle(tree.getTitle()); - tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree - .getWidth(), tree.getHeight())); + tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), + tree.getWidth(), tree.getHeight())); tp.av = av; // af.viewport; // TODO: verify 'associate with all // views' // works still @@@ -3711,13 -3725,13 +3720,13 @@@ if (tree.getFontName() != null) { - tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree - .getFontStyle(), tree.getFontSize())); + tp.setTreeFont(new java.awt.Font(tree.getFontName(), + tree.getFontStyle(), tree.getFontSize())); } else { - tp.setTreeFont(new java.awt.Font(view.getFontName(), view - .getFontStyle(), tree.getFontSize())); + tp.setTreeFont(new java.awt.Font(view.getFontName(), + view.getFontStyle(), tree.getFontSize())); } tp.showPlaceholders(tree.getMarkUnlinked()); @@@ -3788,12 -3802,12 +3797,12 @@@ // TODO: NOW: check that this recovers the PDB file correctly. String pdbFile = loadPDBFile(jprovider, ids[p].getId(), ids[p].getFile()); - jalview.datamodel.SequenceI seq = seqRefIds.get(jseqs[i] - .getId() + ""); + jalview.datamodel.SequenceI seq = seqRefIds + .get(jseqs[i].getId() + ""); if (sviewid == null) { - sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width - + "," + height; + sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + "," + + height; } if (!structureViewers.containsKey(sviewid)) { @@@ -3812,8 -3826,9 +3821,9 @@@ // linkAlignPanel,superposeWithAlignpanel}} from hash StructureViewerModel jmoldat = structureViewers.get(sviewid); jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel() - | (structureState.hasAlignwithAlignPanel() ? structureState - .getAlignwithAlignPanel() : false)); + | (structureState.hasAlignwithAlignPanel() + ? structureState.getAlignwithAlignPanel() + : false)); /* * Default colour by linked panel to false if not specified (e.g. @@@ -3821,8 -3836,9 +3831,9 @@@ */ boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel(); colourWithAlignPanel |= (structureState - .hasColourwithAlignPanel() ? structureState - .getColourwithAlignPanel() : false); + .hasColourwithAlignPanel() + ? structureState.getColourwithAlignPanel() + : false); jmoldat.setColourWithAlignPanel(colourWithAlignPanel); /* @@@ -3830,8 -3846,9 +3841,9 @@@ * pre-2.7 projects) */ boolean colourByViewer = jmoldat.isColourByViewer(); - colourByViewer &= structureState.hasColourByJmol() ? structureState - .getColourByJmol() : true; + colourByViewer &= structureState.hasColourByJmol() + ? structureState.getColourByJmol() + : true; jmoldat.setColourByViewer(colourByViewer); if (jmoldat.getStateData().length() < structureState @@@ -3847,8 -3864,7 +3859,7 @@@ StructureData seqstrmaps = jmoldat.getFileData().get(mapkey); if (seqstrmaps == null) { - jmoldat.getFileData().put( - mapkey, + jmoldat.getFileData().put(mapkey, seqstrmaps = jmoldat.new StructureData(pdbFile, ids[p].getId())); } @@@ -3876,8 -3892,8 +3887,8 @@@ createOrLinkStructureViewer(entry, af, ap, jprovider); } catch (Exception e) { - System.err.println("Error loading structure viewer: " - + e.getMessage()); + System.err.println( + "Error loading structure viewer: " + e.getMessage()); // failed - try the next one } } @@@ -3969,8 -3985,8 +3980,8 @@@ // TODO use StructureViewer as a factory here, see JAL-1761 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]); - final SequenceI[][] seqsArray = allseqs.toArray(new SequenceI[allseqs - .size()][]); + final SequenceI[][] seqsArray = allseqs + .toArray(new SequenceI[allseqs.size()][]); String newViewId = viewerData.getKey(); ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile, @@@ -4081,8 -4097,8 +4092,8 @@@ */ histbug += 10; int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug); - String val = (diff == -1) ? null : newFileLoc - .substring(histbug, diff); + String val = (diff == -1) ? null + : newFileLoc.substring(histbug, diff); if (val != null && val.length() >= 4) { if (val.contains("e")) // eh? what can it be? @@@ -4100,8 -4116,8 +4111,8 @@@ } } - final String[] pdbf = pdbfilenames.toArray(new String[pdbfilenames - .size()]); + final String[] pdbf = pdbfilenames + .toArray(new String[pdbfilenames.size()]); final String[] id = pdbids.toArray(new String[pdbids.size()]); final SequenceI[][] sq = seqmaps .toArray(new SequenceI[seqmaps.size()][]); @@@ -4120,10 -4136,11 +4131,11 @@@ JalviewStructureDisplayI sview = null; try { - sview = new StructureViewer(alf.alignPanel - .getStructureSelectionManager()).createView( - StructureViewer.ViewerType.JMOL, pdbf, id, sq, - alf.alignPanel, svattrib, fileloc, rect, sviewid); + sview = new StructureViewer( + alf.alignPanel.getStructureSelectionManager()) + .createView(StructureViewer.ViewerType.JMOL, + pdbf, id, sq, alf.alignPanel, svattrib, + fileloc, rect, sviewid); addNewStructureViewer(sview); } catch (OutOfMemoryError ex) { @@@ -4183,9 -4200,8 +4195,8 @@@ /* * Post jalview 2.4 schema includes structure view id */ - if (sviewid != null - && ((StructureViewerBase) frame).getViewId() - .equals(sviewid)) + if (sviewid != null && ((StructureViewerBase) frame).getViewId() + .equals(sviewid)) { comp = (StructureViewerBase) frame; break; // break added in 2.9 @@@ -4357,8 -4373,9 +4368,9 @@@ for (int i = 0; i < JSEQ.length; i++) { - af.viewport.setSequenceColour(af.viewport.getAlignment() - .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour())); + af.viewport.setSequenceColour( + af.viewport.getAlignment().getSequenceAt(i), + new java.awt.Color(JSEQ[i].getColour())); } if (al.hasSeqrep()) @@@ -4398,8 -4415,8 +4410,8 @@@ for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++) { isRepresentative = true; - SequenceI sequenceToHide = al.getSequenceAt(JSEQ[s] - .getHiddenSequences(r)); + SequenceI sequenceToHide = al + .getSequenceAt(JSEQ[s].getHiddenSequences(r)); hidden.addSequence(sequenceToHide, false); // remove from hiddenSeqs list so we don't try to hide it twice hiddenSeqs.remove(sequenceToHide); @@@ -4412,8 -4429,8 +4424,8 @@@ } } - SequenceI[] hseqs = hiddenSeqs.toArray(new SequenceI[hiddenSeqs - .size()]); + SequenceI[] hseqs = hiddenSeqs + .toArray(new SequenceI[hiddenSeqs.size()]); af.viewport.hideSequence(hseqs); } @@@ -4429,9 -4446,8 +4441,8 @@@ af.viewport.setIncrement(view.getConsThreshold()); af.viewport.setShowJVSuffix(view.getShowFullId()); af.viewport.setRightAlignIds(view.getRightAlignIds()); - af.viewport.setFont( - new java.awt.Font(view.getFontName(), view.getFontStyle(), view - .getFontSize()), true); + af.viewport.setFont(new java.awt.Font(view.getFontName(), + view.getFontStyle(), view.getFontSize()), true); ViewStyleI vs = af.viewport.getViewStyle(); vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna()); af.viewport.setViewStyle(vs); @@@ -4448,8 -4464,8 +4459,8 @@@ af.viewport.setTextColour(new java.awt.Color(view.getTextCol1())); af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2())); af.viewport.setThresholdTextColour(view.getTextColThreshold()); - af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view - .isShowUnconserved() : false); + af.viewport.setShowUnconserved( + view.hasShowUnconserved() ? view.isShowUnconserved() : false); af.viewport.getRanges().setStartRes(view.getStartRes()); if (view.getViewName() != null) @@@ -4486,14 -4502,14 +4497,14 @@@ af.viewport.setGlobalColourScheme(cs); af.viewport.getResidueShading().setThreshold(view.getPidThreshold(), view.getIgnoreGapsinConsensus()); - af.viewport.getResidueShading().setConsensus( - af.viewport.getSequenceConsensusHash()); + af.viewport.getResidueShading() + .setConsensus(af.viewport.getSequenceConsensusHash()); af.viewport.setColourAppliesToAllGroups(false); if (view.getConservationSelected() && cs != null) { - af.viewport.getResidueShading().setConservationInc( - view.getConsThreshold()); + af.viewport.getResidueShading() + .setConservationInc(view.getConsThreshold()); } af.changeColour(cs); @@@ -4521,8 -4537,8 +4532,8 @@@ } if (view.hasShowConsensusHistogram()) { - af.viewport.setShowConsensusHistogram(view - .getShowConsensusHistogram()); + af.viewport + .setShowConsensusHistogram(view.getShowConsensusHistogram()); } else { @@@ -4575,17 -4591,18 +4586,18 @@@ Map featureColours = new Hashtable<>(); Map featureOrder = new Hashtable<>(); - for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++) + for (int fs = 0; fs < jms.getFeatureSettings() + .getSettingCount(); fs++) { Setting setting = jms.getFeatureSettings().getSetting(fs); if (setting.hasMincolour()) { - FeatureColourI gc = setting.hasMin() ? new FeatureColour( - new Color(setting.getMincolour()), new Color( - setting.getColour()), setting.getMin(), - setting.getMax()) : new FeatureColour(new Color( - setting.getMincolour()), new Color(setting.getColour()), - 0, 1); + FeatureColourI gc = setting.hasMin() + ? new FeatureColour(new Color(setting.getMincolour()), + new Color(setting.getColour()), setting.getMin(), + setting.getMax()) + : new FeatureColour(new Color(setting.getMincolour()), + new Color(setting.getColour()), 0, 1); if (setting.hasThreshold()) { gc.setThreshold(setting.getThreshold()); @@@ -4614,8 -4631,8 +4626,8 @@@ } else { - featureColours.put(setting.getType(), new FeatureColour( - new Color(setting.getColour()))); + featureColours.put(setting.getType(), + new FeatureColour(new Color(setting.getColour()))); } renderOrder[fs] = setting.getType(); if (setting.hasOrder()) @@@ -4624,8 -4641,8 +4636,8 @@@ } else { - featureOrder.put(setting.getType(), new Float(fs - / jms.getFeatureSettings().getSettingCount())); + featureOrder.put(setting.getType(), new Float( + fs / jms.getFeatureSettings().getSettingCount())); } if (setting.getDisplay()) { @@@ -4641,8 -4658,8 +4653,8 @@@ // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder, // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ? // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder); - FeatureRendererSettings frs = new FeatureRendererSettings( - renderOrder, fgtable, featureColours, 1.0f, featureOrder); + FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder, + fgtable, featureColours, 1.0f, featureOrder); af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer() .transferSettings(frs); @@@ -4652,9 -4669,9 +4664,9 @@@ { for (int c = 0; c < view.getHiddenColumnsCount(); c++) { - af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view - .getHiddenColumns(c).getEnd() // +1 - ); + af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), + view.getHiddenColumns(c).getEnd() // +1 + ); } } if (view.getCalcIdParam() != null) @@@ -4739,7 -4756,8 +4751,8 @@@ /* * pre 2.10.2: saved annotationId is AlignmentAnnotation.label */ - if (matchedAnnotation == null && annAlignment.getAlignmentAnnotation() != null) + if (matchedAnnotation == null + && annAlignment.getAlignmentAnnotation() != null) { for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++) { @@@ -4759,22 -4777,22 +4772,22 @@@ } if (matchedAnnotation.getThreshold() == null) { - matchedAnnotation.setThreshold(new GraphLine(viewAnnColour.getThreshold(), - "Threshold", Color.black)); + matchedAnnotation.setThreshold(new GraphLine( + viewAnnColour.getThreshold(), "Threshold", Color.black)); } AnnotationColourGradient cs = null; if (viewAnnColour.getColourScheme().equals("None")) { - cs = new AnnotationColourGradient(matchedAnnotation, new Color( - viewAnnColour.getMinColour()), new Color( - viewAnnColour.getMaxColour()), + cs = new AnnotationColourGradient(matchedAnnotation, + new Color(viewAnnColour.getMinColour()), + new Color(viewAnnColour.getMaxColour()), viewAnnColour.getAboveThreshold()); } else if (viewAnnColour.getColourScheme().startsWith("ucs")) { - cs = new AnnotationColourGradient(matchedAnnotation, getUserColourScheme( - jms, viewAnnColour.getColourScheme()), + cs = new AnnotationColourGradient(matchedAnnotation, + getUserColourScheme(jms, viewAnnColour.getColourScheme()), viewAnnColour.getAboveThreshold()); } else @@@ -4833,8 -4851,9 +4846,9 @@@ for (JvAnnotRow auan : autoAlan) { visan.put(auan.template.label - + (auan.template.getCalcId() == null ? "" : "\t" - + auan.template.getCalcId()), auan); + + (auan.template.getCalcId() == null ? "" + : "\t" + auan.template.getCalcId()), + auan); } int hSize = al.getAlignmentAnnotation().length; List reorder = new ArrayList<>(); @@@ -4937,8 -4956,9 +4951,9 @@@ return false; } String id; - if (skipList.containsKey(id = object.getJalviewModelSequence() - .getViewport()[0].getSequenceSetId())) + if (skipList.containsKey( + id = object.getJalviewModelSequence().getViewport()[0] + .getSequenceSetId())) { if (Cache.log != null && Cache.log.isDebugEnabled()) { @@@ -4970,8 -4990,8 +4985,8 @@@ private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al, boolean ignoreUnrefed) { - jalview.datamodel.AlignmentI ds = getDatasetFor(vamsasSet - .getDatasetId()); + jalview.datamodel.AlignmentI ds = getDatasetFor( + vamsasSet.getDatasetId()); Vector dseqs = null; if (ds == null) { @@@ -5120,8 -5140,8 +5135,8 @@@ } // TODO: merges will never happen if we 'know' we have the real dataset // sequence - this should be detected when id==dssid - System.err - .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // (" + System.err.println( + "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // (" // + (pre ? "prepended" : "") + " " // + (post ? "appended" : "")); } @@@ -5227,8 -5247,9 +5242,9 @@@ { DBRef dr = sequence.getDBRef(d); jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry( - sequence.getDBRef(d).getSource(), sequence.getDBRef(d) - .getVersion(), sequence.getDBRef(d).getAccessionId()); + sequence.getDBRef(d).getSource(), + sequence.getDBRef(d).getVersion(), + sequence.getDBRef(d).getAccessionId()); if (dr.getMapping() != null) { entry.setMap(addMapping(dr.getMapping())); @@@ -5257,8 -5278,8 +5273,8 @@@ fto[_i] = mf.getStart(); fto[_i + 1] = mf.getEnd(); } - jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, - fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit()); + jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr, + fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit()); if (m.getMappingChoice() != null) { MappingChoice mc = m.getMappingChoice(); @@@ -5294,8 -5315,8 +5310,8 @@@ } else { - System.err - .println("Warning - making up dataset sequence id for DbRef sequence map reference"); + System.err.println( + "Warning - making up dataset sequence id for DbRef sequence map reference"); sqid = ((Object) ms).toString(); // make up a new hascode for // undefined dataset sequence hash // (unlikely to happen) diff --combined src/jalview/gui/Jalview2XML_V1.java index 614efd2,e94ee0e..331e738 --- a/src/jalview/gui/Jalview2XML_V1.java +++ b/src/jalview/gui/Jalview2XML_V1.java @@@ -36,7 -36,6 +36,7 @@@ import jalview.binding.Tree import jalview.binding.UserColours; import jalview.binding.Viewport; import jalview.datamodel.PDBEntry; +import jalview.datamodel.SequenceFeature; import jalview.io.FileFormat; import jalview.schemes.ColourSchemeI; import jalview.schemes.ColourSchemeProperty; @@@ -94,8 -93,8 +94,8 @@@ public class Jalview2XML_V for (int i = 0; i < csize; i++) { - newColours[i] = new java.awt.Color(Integer.parseInt(colours - .getUserColourScheme().getColour(i).getRGB(), 16)); + newColours[i] = new java.awt.Color(Integer.parseInt( + colours.getUserColourScheme().getColour(i).getRGB(), 16)); } return new jalview.schemes.UserColourScheme(newColours); @@@ -153,12 -152,13 +153,13 @@@ public void run() { - System.err.println("Couldn't locate Jalview XML file : " + ex - + "\n"); + System.err.println( + "Couldn't locate Jalview XML file : " + ex + "\n"); JvOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager.formatMessage("label.couldnt_locate", - new String[] { file }), MessageManager - .getString("label.url_not_found"), + new String[] + { file }), + MessageManager.getString("label.url_not_found"), JvOptionPane.WARNING_MESSAGE); } }); @@@ -179,7 -179,8 +180,8 @@@ JvOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager.formatMessage( "label.error_loading_file_params", new String[] - { file }), MessageManager + { file }), + MessageManager .getString("label.error_loading_jalview_file"), JvOptionPane.WARNING_MESSAGE); } @@@ -225,10 -226,11 +227,10 @@@ Features[] features = JSEQ[i].getFeatures(); for (int f = 0; f < features.length; f++) { - jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature( - features[f].getType(), features[f].getDescription(), - features[f].getStatus(), features[f].getBegin(), + SequenceFeature sf = new SequenceFeature(features[f].getType(), + features[f].getDescription(), features[f].getBegin(), features[f].getEnd(), null); - + sf.setStatus(features[f].getStatus()); al.getSequenceAt(i).getDatasetSequence().addSequenceFeature(sf); } } @@@ -251,8 -253,9 +253,9 @@@ } } al.getSequenceAt(i).getDatasetSequence().addPDBId(entry); - StructureSelectionManager.getStructureSelectionManager( - Desktop.instance).registerPDBEntry(entry); + StructureSelectionManager + .getStructureSelectionManager(Desktop.instance) + .registerPDBEntry(entry); } } @@@ -308,8 -311,9 +311,9 @@@ for (int i = 0; i < JSEQ.length; i++) { - af.viewport.setSequenceColour(af.viewport.getAlignment() - .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour())); + af.viewport.setSequenceColour( + af.viewport.getAlignment().getSequenceAt(i), + new java.awt.Color(JSEQ[i].getColour())); } // af.changeColour() ); @@@ -331,7 -335,8 +335,8 @@@ } else { - cs = ColourSchemeProperty.getColourScheme(al, groups[i].getColour()); + cs = ColourSchemeProperty.getColourScheme(al, + groups[i].getColour()); } } int pidThreshold = groups[i].getPidThreshold(); @@@ -350,12 -355,13 +355,13 @@@ groups[i].getStart(), groups[i].getEnd()); sg.getGroupColourScheme().setThreshold(pidThreshold, true); - sg.setOutlineColour(new java.awt.Color(groups[i].getOutlineColour())); + sg.setOutlineColour( + new java.awt.Color(groups[i].getOutlineColour())); if (groups[i].getConsThreshold() != 0) { - Conservation c = new Conservation("All", sg.getSequences(null), - 0, sg.getWidth() - 1); + Conservation c = new Conservation("All", sg.getSequences(null), 0, + sg.getWidth() - 1); c.calculate(); c.verdict(false, 25); sg.cs.setConservation(c); @@@ -374,9 -380,8 +380,8 @@@ af.viewport.setColourText(view.getShowColourText()); af.viewport.setConservationSelected(view.getConservationSelected()); af.viewport.setShowJVSuffix(view.getShowFullId()); - af.viewport.setFont( - new java.awt.Font(view.getFontName(), view.getFontStyle(), view - .getFontSize()), true); + af.viewport.setFont(new java.awt.Font(view.getFontName(), + view.getFontStyle(), view.getFontSize()), true); af.viewport.setRenderGaps(view.getRenderGaps()); af.viewport.setWrapAlignment(view.getWrapAlignment()); @@@ -405,17 -410,17 +410,17 @@@ // } } - af.viewport.getResidueShading().setThreshold( - view.getPidThreshold(), true); - af.viewport.getResidueShading().setConsensus( - af.viewport.getSequenceConsensusHash()); + af.viewport.getResidueShading().setThreshold(view.getPidThreshold(), + true); + af.viewport.getResidueShading() + .setConsensus(af.viewport.getSequenceConsensusHash()); af.viewport.setColourAppliesToAllGroups(false); af.alignPanel.updateLayout(); af.changeColour(cs); if (view.getConservationSelected() && cs != null) { - af.viewport.getResidueShading().setConservationInc( - view.getConsThreshold()); + af.viewport.getResidueShading() + .setConservationInc(view.getConsThreshold()); } af.viewport.setColourAppliesToAllGroups(true); @@@ -427,7 -432,8 +432,8 @@@ Hashtable featureColours = new Hashtable(); String[] renderOrder = new String[jms.getFeatureSettings() .getSettingCount()]; - for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++) + for (int fs = 0; fs < jms.getFeatureSettings() + .getSettingCount(); fs++) { Setting setting = jms.getFeatureSettings().getSetting(fs); @@@ -442,8 -448,8 +448,8 @@@ new Integer(setting.getColour())); } } - FeatureRendererSettings frs = new FeatureRendererSettings( - renderOrder, new Hashtable(), featureColours, 1.0f, null); + FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder, + new Hashtable(), featureColours, 1.0f, null); af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer() .transferSettings(frs); } @@@ -474,13 -480,13 +480,13 @@@ if (tree.getFontName() != null) { - tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree - .getFontStyle(), tree.getFontSize())); + tp.setTreeFont(new java.awt.Font(tree.getFontName(), + tree.getFontStyle(), tree.getFontSize())); } else { - tp.setTreeFont(new java.awt.Font(view.getFontName(), view - .getFontStyle(), tree.getFontSize())); + tp.setTreeFont(new java.awt.Font(view.getFontName(), + view.getFontStyle(), tree.getFontSize())); } tp.showPlaceholders(tree.getMarkUnlinked()); diff --combined src/jalview/gui/PopupMenu.java index c78021c,3e2eba9..2473ba9 --- a/src/jalview/gui/PopupMenu.java +++ b/src/jalview/gui/PopupMenu.java @@@ -180,7 -180,8 +180,8 @@@ public class PopupMenu extends JPopupMe * @param seq * DOCUMENT ME! */ - public PopupMenu(final AlignmentPanel ap, Sequence seq, List links) + public PopupMenu(final AlignmentPanel ap, Sequence seq, + List links) { this(ap, seq, links, null); } @@@ -225,8 -226,9 +226,9 @@@ * 'reference annotations' that may be added to the alignment. First for the * currently selected sequence (if there is one): */ - final List selectedSequence = (seq == null ? Collections - . emptyList() : Arrays.asList(seq)); + final List selectedSequence = (seq == null + ? Collections. emptyList() + : Arrays.asList(seq)); buildAnnotationTypesMenus(seqShowAnnotationsMenu, seqHideAnnotationsMenu, selectedSequence); configureReferenceAnnotationsMenu(seqAddReferenceAnnotations, @@@ -235,9 -237,9 +237,9 @@@ /* * And repeat for the current selection group (if there is one): */ - final List selectedGroup = (ap.av.getSelectionGroup() == null ? Collections - . emptyList() : ap.av.getSelectionGroup() - .getSequences()); + final List selectedGroup = (ap.av.getSelectionGroup() == null + ? Collections. emptyList() + : ap.av.getSelectionGroup().getSequences()); buildAnnotationTypesMenus(groupShowAnnotationsMenu, groupHideAnnotationsMenu, selectedGroup); configureReferenceAnnotationsMenu(groupAddReferenceAnnotations, @@@ -257,13 -259,13 +259,13 @@@ sequenceMenu.setText(sequence.getName()); if (seq == ap.av.getAlignment().getSeqrep()) { - makeReferenceSeq.setText(MessageManager - .getString("action.unmark_as_reference")); + makeReferenceSeq.setText( + MessageManager.getString("action.unmark_as_reference")); } else { - makeReferenceSeq.setText(MessageManager - .getString("action.set_as_reference")); + makeReferenceSeq.setText( + MessageManager.getString("action.set_as_reference")); } if (!ap.av.getAlignment().isNucleotide()) @@@ -290,8 -292,8 +292,8 @@@ */ menuItem = new JMenuItem(); menuItem.setText(MessageManager.formatMessage( - "label.2d_rna_structure_line", - new Object[] { aa.label })); + "label.2d_rna_structure_line", new Object[] + { aa.label })); menuItem.addActionListener(new ActionListener() { @Override @@@ -318,8 -320,8 +320,8 @@@ // TODO: make rnastrucF a bit more nice menuItem = new JMenuItem(); menuItem.setText(MessageManager.formatMessage( - "label.2d_rna_sequence_name", - new Object[] { seq.getName() })); + "label.2d_rna_sequence_name", new Object[] + { seq.getName() })); menuItem.addActionListener(new ActionListener() { @Override @@@ -354,9 -356,9 +356,9 @@@ if (ap.av.getSelectionGroup() != null && ap.av.getSelectionGroup().getSize() > 1) { - menuItem = new JMenuItem(MessageManager.formatMessage( - "label.represent_group_with", - new Object[] { seq.getName() })); + menuItem = new JMenuItem(MessageManager + .formatMessage("label.represent_group_with", new Object[] + { seq.getName() })); menuItem.addActionListener(new ActionListener() { @Override @@@ -417,8 -419,9 +419,9 @@@ } SequenceGroup sg = ap.av.getSelectionGroup(); - boolean isDefinedGroup = (sg != null) ? ap.av.getAlignment() - .getGroups().contains(sg) : false; + boolean isDefinedGroup = (sg != null) + ? ap.av.getAlignment().getGroups().contains(sg) + : false; if (sg != null && sg.getSize() > 0) { @@@ -452,7 -455,8 +455,8 @@@ buildGroupURLMenu(sg, groupLinks); } // Add a 'show all structures' for the current selection - Hashtable pdbe = new Hashtable(), reppdb = new Hashtable(); + Hashtable pdbe = new Hashtable(), + reppdb = new Hashtable(); SequenceI sqass = null; for (SequenceI sq : ap.av.getSequenceSelection()) { @@@ -472,9 -476,9 +476,9 @@@ } if (pdbe.size() > 0) { - final PDBEntry[] pe = pdbe.values().toArray( - new PDBEntry[pdbe.size()]), pr = reppdb.values().toArray( - new PDBEntry[reppdb.size()]); + final PDBEntry[] pe = pdbe.values() + .toArray(new PDBEntry[pdbe.size()]), + pr = reppdb.values().toArray(new PDBEntry[reppdb.size()]); final JMenuItem gpdbview, rpdbview; } } @@@ -586,9 -590,11 +590,11 @@@ showMenu.removeAll(); hideMenu.removeAll(); - final List all = Arrays.asList(new String[] { MessageManager - .getString("label.all") }); - addAnnotationTypeToShowHide(showMenu, forSequences, "", all, true, true); + final List all = Arrays + .asList(new String[] + { MessageManager.getString("label.all") }); + addAnnotationTypeToShowHide(showMenu, forSequences, "", all, true, + true); addAnnotationTypeToShowHide(hideMenu, forSequences, "", all, true, false); showMenu.addSeparator(); @@@ -714,8 -720,8 +720,8 @@@ for (int sq = 0; sq < seqs.length; sq++) { - int start = seqs[sq].findPosition(sg.getStartRes()), end = seqs[sq] - .findPosition(sg.getEndRes()); + int start = seqs[sq].findPosition(sg.getStartRes()), + end = seqs[sq].findPosition(sg.getEndRes()); // just collect ids from dataset sequence // TODO: check if IDs collected from selecton group intersects with the // current selection, too @@@ -742,8 -748,8 +748,8 @@@ if (((String[]) sarray[1])[sq] == null) { - if (!dbr[d].hasMap() - || (dbr[d].getMap().locateMappedRange(start, end) != null)) + if (!dbr[d].hasMap() || (dbr[d].getMap() + .locateMappedRange(start, end) != null)) { ((String[]) sarray[1])[sq] = dbr[d].getAccessionId(); ((int[]) sarray[0])[0]++; @@@ -815,9 -821,10 +821,10 @@@ int type = urlLink.getGroupURLType() & 3; // first two bits ofurlLink type bitfield are sequenceids and sequences // TODO: FUTURE: ensure the groupURL menu structure can be generalised - addshowLink(linkMenus[type], label - + (((type & 1) == 1) ? ("(" - + (usingNames ? "Names" : ltarget) + ")") : ""), + addshowLink(linkMenus[type], + label + (((type & 1) == 1) + ? ("(" + (usingNames ? "Names" : ltarget) + ")") + : ""), urlLink, urlset); addMenu = true; } @@@ -839,7 -846,8 +846,8 @@@ } } - private void addshowLinks(JMenu linkMenu, Collection> linkset) + private void addshowLinks(JMenu linkMenu, + Collection> linkset) { for (List linkstrset : linkset) { @@@ -860,8 -868,9 +868,9 @@@ private void addshowLink(JMenu linkMenu, String label, final String url) { JMenuItem item = new JMenuItem(label); - item.setToolTipText(MessageManager.formatMessage( - "label.open_url_param", new Object[] { url })); + item.setToolTipText(MessageManager.formatMessage("label.open_url_param", + new Object[] + { url })); item.addActionListener(new ActionListener() { @Override @@@ -898,9 -907,9 +907,9 @@@ final GroupUrlLink urlgenerator, final Object[] urlstub) { JMenuItem item = new JMenuItem(label); - item.setToolTipText(MessageManager.formatMessage( - "label.open_url_seqs_param", - new Object[] { urlgenerator.getUrl_prefix(), + item.setToolTipText(MessageManager + .formatMessage("label.open_url_seqs_param", new Object[] + { urlgenerator.getUrl_prefix(), urlgenerator.getNumberInvolved(urlstub) })); // TODO: put in info about what is being sent. item.addActionListener(new ActionListener() @@@ -948,8 -957,8 +957,8 @@@ } }); sequenceMenu.setText(MessageManager.getString("label.sequence")); - sequenceName.setText(MessageManager - .getString("label.edit_name_description")); + sequenceName.setText( + MessageManager.getString("label.edit_name_description")); sequenceName.addActionListener(new ActionListener() { @Override @@@ -958,8 -967,8 +967,8 @@@ sequenceName_actionPerformed(); } }); - chooseAnnotations.setText(MessageManager - .getString("action.choose_annotations")); + chooseAnnotations + .setText(MessageManager.getString("action.choose_annotations")); chooseAnnotations.addActionListener(new ActionListener() { @Override @@@ -968,8 -977,8 +977,8 @@@ chooseAnnotations_actionPerformed(e); } }); - sequenceDetails.setText(MessageManager - .getString("label.sequence_details")); + sequenceDetails + .setText(MessageManager.getString("label.sequence_details")); sequenceDetails.addActionListener(new ActionListener() { @Override @@@ -978,8 -987,8 +987,8 @@@ sequenceDetails_actionPerformed(); } }); - sequenceSelDetails.setText(MessageManager - .getString("label.sequence_details")); + sequenceSelDetails + .setText(MessageManager.getString("label.sequence_details")); sequenceSelDetails.addActionListener(new ActionListener() { @Override @@@ -999,8 -1008,8 +1008,8 @@@ unGroupMenuItem_actionPerformed(); } }); - createGroupMenuItem.setText(MessageManager - .getString("action.create_group")); + createGroupMenuItem + .setText(MessageManager.getString("action.create_group")); createGroupMenuItem.addActionListener(new ActionListener() { @Override @@@ -1048,8 -1057,8 +1057,8 @@@ showColourText_actionPerformed(); } }); - displayNonconserved.setText(MessageManager - .getString("label.show_non_conserved")); + displayNonconserved + .setText(MessageManager.getString("label.show_non_conserved")); displayNonconserved.setState(true); displayNonconserved.addActionListener(new ActionListener() { @@@ -1105,18 -1114,18 +1114,18 @@@ changeCase(e); } }); - outputMenu.setText(MessageManager.getString("label.out_to_textbox") - + "..."); - seqShowAnnotationsMenu.setText(MessageManager - .getString("label.show_annotations")); - seqHideAnnotationsMenu.setText(MessageManager - .getString("label.hide_annotations")); - groupShowAnnotationsMenu.setText(MessageManager - .getString("label.show_annotations")); - groupHideAnnotationsMenu.setText(MessageManager - .getString("label.hide_annotations")); - sequenceFeature.setText(MessageManager - .getString("label.create_sequence_feature")); + outputMenu.setText( + MessageManager.getString("label.out_to_textbox") + "..."); + seqShowAnnotationsMenu + .setText(MessageManager.getString("label.show_annotations")); + seqHideAnnotationsMenu + .setText(MessageManager.getString("label.hide_annotations")); + groupShowAnnotationsMenu + .setText(MessageManager.getString("label.show_annotations")); + groupHideAnnotationsMenu + .setText(MessageManager.getString("label.hide_annotations")); + sequenceFeature.setText( + MessageManager.getString("label.create_sequence_feature")); sequenceFeature.addActionListener(new ActionListener() { @Override @@@ -1126,8 -1135,8 +1135,8 @@@ } }); jMenu1.setText(MessageManager.getString("label.group")); - pdbStructureDialog.setText(MessageManager - .getString("label.show_pdbstruct_dialog")); + pdbStructureDialog.setText( + MessageManager.getString("label.show_pdbstruct_dialog")); pdbStructureDialog.addActionListener(new ActionListener() { @Override @@@ -1142,12 -1151,12 +1151,12 @@@ } }); - rnaStructureMenu.setText(MessageManager - .getString("label.view_rna_structure")); + rnaStructureMenu + .setText(MessageManager.getString("label.view_rna_structure")); // colStructureMenu.setText("Colour By Structure"); - editSequence.setText(MessageManager.getString("label.edit_sequence") - + "..."); + editSequence.setText( + MessageManager.getString("label.edit_sequence") + "..."); editSequence.addActionListener(new ActionListener() { @Override @@@ -1156,8 -1165,8 +1165,8 @@@ editSequence_actionPerformed(actionEvent); } }); - makeReferenceSeq.setText(MessageManager - .getString("label.mark_as_representative")); + makeReferenceSeq.setText( + MessageManager.getString("label.mark_as_representative")); makeReferenceSeq.addActionListener(new ActionListener() { @@@ -1168,8 -1177,8 +1177,8 @@@ } }); - hideInsertions.setText(MessageManager - .getString("label.hide_insertions")); + hideInsertions + .setText(MessageManager.getString("label.hide_insertions")); hideInsertions.addActionListener(new ActionListener() { @@@ -1233,7 -1242,7 +1242,7 @@@ jMenu1.add(outline); jMenu1.add(displayNonconserved); } - + /** * Constructs the entries for the colour menu */ @@@ -1250,8 -1259,8 +1259,8 @@@ } }); - abovePIDColour.setText(MessageManager - .getString("label.above_identity_threshold")); + abovePIDColour.setText( + MessageManager.getString("label.above_identity_threshold")); abovePIDColour.addActionListener(new ActionListener() { @Override @@@ -1261,8 -1270,8 +1270,8 @@@ } }); - modifyPID.setText(MessageManager - .getString("label.modify_identity_threshold")); + modifyPID.setText( + MessageManager.getString("label.modify_identity_threshold")); modifyPID.addActionListener(new ActionListener() { @Override @@@ -1272,15 -1281,15 +1281,15 @@@ } }); - conservationMenuItem.setText(MessageManager - .getString("action.by_conservation")); + conservationMenuItem + .setText(MessageManager.getString("action.by_conservation")); conservationMenuItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - conservationMenuItem_actionPerformed(conservationMenuItem - .isSelected()); + conservationMenuItem_actionPerformed( + conservationMenuItem.isSelected()); } }); @@@ -1341,8 -1350,7 +1350,7 @@@ // int threshold = SliderPanel.setPIDSliderSource(ap, sg.cs, getGroup() // .getName()); // sg.cs.setThreshold(threshold, ap.av.isIgnoreGapsConsensus()); - SliderPanel.setPIDSliderSource(ap, sg.cs, getGroup() - .getName()); + SliderPanel.setPIDSliderSource(ap, sg.cs, getGroup().getName()); SliderPanel.showPIDSlider(); } } @@@ -1372,8 -1380,8 +1380,8 @@@ SortedMap tipEntries = new TreeMap(); final Map> candidates = new LinkedHashMap>(); AlignmentI al = this.ap.av.getAlignment(); - AlignmentUtils.findAddableReferenceAnnotations(forSequences, - tipEntries, candidates, al); + AlignmentUtils.findAddableReferenceAnnotations(forSequences, tipEntries, + candidates, al); if (!candidates.isEmpty()) { StringBuilder tooltip = new StringBuilder(64); @@@ -1460,8 -1468,8 +1468,8 @@@ if (ap.av.getSelectionGroup() != null) { // mark just the columns in the selection group to be hidden - inserts.set(ap.av.getSelectionGroup().getStartRes(), ap.av - .getSelectionGroup().getEndRes() + 1); + inserts.set(ap.av.getSelectionGroup().getStartRes(), + ap.av.getSelectionGroup().getEndRes() + 1); // and clear that part of the mask mask.andNot(inserts); @@@ -1517,30 -1525,27 +1525,27 @@@ StringBuilder contents = new StringBuilder(128); for (SequenceI seq : sequences) { - contents.append("

" - + MessageManager - .formatMessage( - "label.create_sequence_details_report_annotation_for", - new Object[] { seq.getDisplayId(true) }) - + "

"); - new SequenceAnnotationReport(null) - .createSequenceAnnotationReport( - contents, - seq, - true, - true, - (ap.getSeqPanel().seqCanvas.fr != null) ? ap - .getSeqPanel().seqCanvas.fr.getMinMax() - : null); + contents.append("

" + MessageManager.formatMessage( + "label.create_sequence_details_report_annotation_for", + new Object[] + { seq.getDisplayId(true) }) + "

"); + new SequenceAnnotationReport(null).createSequenceAnnotationReport( + contents, seq, true, true, + (ap.getSeqPanel().seqCanvas.fr != null) + ? ap.getSeqPanel().seqCanvas.fr.getMinMax() + : null); contents.append("

"); } cap.setText("" + contents.toString() + ""); - Desktop.addInternalFrame(cap, MessageManager.formatMessage( - "label.sequence_details_for", - (sequences.length == 1 ? new Object[] { sequences[0] - .getDisplayId(true) } : new Object[] { MessageManager - .getString("label.selection") })), 500, 400); + Desktop.addInternalFrame(cap, + MessageManager.formatMessage("label.sequence_details_for", + (sequences.length == 1 ? new Object[] + { sequences[0].getDisplayId(true) } + : new Object[] + { MessageManager + .getString("label.selection") })), + 500, 400); } @@@ -1588,8 -1593,7 +1593,7 @@@ sg.getStartRes(), sg.getEndRes() + 1)); int threshold = SliderPanel.setPIDSliderSource(ap, - sg.getGroupColourScheme(), getGroup() - .getName()); + sg.getGroupColourScheme(), getGroup().getName()); sg.cs.setThreshold(threshold, ap.av.isIgnoreGapsConsensus()); @@@ -1635,9 -1639,9 +1639,9 @@@ if (selected) { // JBPNote: Conservation name shouldn't be i18n translated - Conservation c = new Conservation("Group", sg.getSequences(ap.av - .getHiddenRepSequences()), sg.getStartRes(), - sg.getEndRes() + 1); + Conservation c = new Conservation("Group", + sg.getSequences(ap.av.getHiddenRepSequences()), + sg.getStartRes(), sg.getEndRes() + 1); c.calculate(); c.verdict(false, ap.av.getConsPercGaps()); @@@ -1669,8 -1673,8 +1673,8 @@@ SequenceGroup sg = getGroup(); EditNameDialog dialog = new EditNameDialog(sg.getName(), - sg.getDescription(), " " - + MessageManager.getString("label.group_name") + " ", + sg.getDescription(), + " " + MessageManager.getString("label.group_name") + " ", MessageManager.getString("label.group_description") + " ", MessageManager.getString("label.edit_group_name_description"), ap.alignFrame); @@@ -1715,8 -1719,8 +1719,8 @@@ " " + MessageManager.getString("label.sequence_name") + " ", MessageManager.getString("label.sequence_description") + " ", - MessageManager - .getString("label.edit_sequence_name_description"), + MessageManager.getString( + "label.edit_sequence_name_description"), ap.alignFrame); if (!dialog.accept) @@@ -1728,14 -1732,12 +1732,12 @@@ { if (dialog.getName().indexOf(" ") > -1) { - JvOptionPane - .showMessageDialog( - ap, - MessageManager - .getString("label.spaces_converted_to_backslashes"), - MessageManager - .getString("label.no_spaces_allowed_sequence_name"), - JvOptionPane.WARNING_MESSAGE); + JvOptionPane.showMessageDialog(ap, + MessageManager + .getString("label.spaces_converted_to_backslashes"), + MessageManager + .getString("label.no_spaces_allowed_sequence_name"), + JvOptionPane.WARNING_MESSAGE); } sequence.setName(dialog.getName().replace(' ', '_')); @@@ -1744,8 -1746,8 +1746,8 @@@ sequence.setDescription(dialog.getDescription()); - ap.av.firePropertyChange("alignment", null, ap.av.getAlignment() - .getSequences()); + ap.av.firePropertyChange("alignment", null, + ap.av.getAlignment().getSequences()); } @@@ -1893,8 -1895,8 +1895,8 @@@ ap.alignFrame.addHistoryItem(caseCommand); - ap.av.firePropertyChange("alignment", null, ap.av.getAlignment() - .getSequences()); + ap.av.firePropertyChange("alignment", null, + ap.av.getAlignment().getSequences()); } } @@@ -1903,9 -1905,9 +1905,9 @@@ { CutAndPasteTransfer cap = new CutAndPasteTransfer(); cap.setForInput(null); - Desktop.addInternalFrame(cap, MessageManager.formatMessage( - "label.alignment_output_command", - new Object[] { e.getActionCommand() }), 600, 500); + Desktop.addInternalFrame(cap, MessageManager + .formatMessage("label.alignment_output_command", new Object[] + { e.getActionCommand() }), 600, 500); String[] omitHidden = null; @@@ -1913,8 -1915,10 +1915,10 @@@ // or we simply trust the user wants // wysiwig behaviour - FileFormatI fileFormat = FileFormats.getInstance().forName(e.getActionCommand()); - cap.setText(new FormatAdapter(ap).formatSequences(fileFormat, ap, true)); + FileFormatI fileFormat = FileFormats.getInstance() + .forName(e.getActionCommand()); + cap.setText( + new FormatAdapter(ap).formatSequences(fileFormat, ap, true)); } public void sequenceFeature_actionPerformed() @@@ -1940,7 -1944,8 +1944,7 @@@ if (start <= end) { seqs.add(sg.getSequenceAt(i).getDatasetSequence()); - features.add( - new SequenceFeature(null, null, null, start, end, null)); + features.add(new SequenceFeature(null, null, start, end, null)); } } @@@ -1949,12 -1954,11 +1953,12 @@@ */ if (!seqs.isEmpty()) { - if (ap.getSeqPanel().seqCanvas.getFeatureRenderer().amendFeatures( - seqs, features, true, ap)) + if (ap.getSeqPanel().seqCanvas.getFeatureRenderer() + .amendFeatures(seqs, features, true, ap)) { ap.alignFrame.setShowSeqFeatures(true); - ap.highlightSearchResults(null); + ap.av.setSearchResults(null); // clear highlighting + ap.repaint(); // draw new/amended features } } } @@@ -2000,8 -2004,8 +2004,8 @@@ EditNameDialog dialog = new EditNameDialog( sequence.getSequenceAsString(sg.getStartRes(), - sg.getEndRes() + 1), null, - MessageManager.getString("label.edit_sequence"), null, + sg.getEndRes() + 1), + null, MessageManager.getString("label.edit_sequence"), null, MessageManager.getString("label.edit_sequence"), ap.alignFrame); @@@ -2009,15 -2013,15 +2013,15 @@@ { EditCommand editCommand = new EditCommand( MessageManager.getString("label.edit_sequences"), - Action.REPLACE, dialog.getName().replace(' ', - ap.av.getGapCharacter()), + Action.REPLACE, + dialog.getName().replace(' ', ap.av.getGapCharacter()), sg.getSequencesAsArray(ap.av.getHiddenRepSequences()), sg.getStartRes(), sg.getEndRes() + 1, ap.av.getAlignment()); ap.alignFrame.addHistoryItem(editCommand); - ap.av.firePropertyChange("alignment", null, ap.av.getAlignment() - .getSequences()); + ap.av.firePropertyChange("alignment", null, + ap.av.getAlignment().getSequences()); } } } diff --combined src/jalview/gui/SeqCanvas.java index 0e31246,a052ae3..d4b3e73 --- a/src/jalview/gui/SeqCanvas.java +++ b/src/jalview/gui/SeqCanvas.java @@@ -52,8 -52,6 +52,8 @@@ import javax.swing.JComponent */ public class SeqCanvas extends JComponent implements ViewportListenerI { + private static String ZEROS = "0000000000"; + final FeatureRenderer fr; final SequenceRenderer sr; @@@ -70,9 -68,9 +70,9 @@@ boolean fastPaint = false; - int LABEL_WEST; + int labelWidthWest; - int LABEL_EAST; + int labelWidthEast; int cursorX = 0; @@@ -146,9 -144,9 +146,9 @@@ { g.drawString(mstring, mpos * charWidth, ypos - (charHeight / 2)); } - g.drawLine((mpos * charWidth) + (charWidth / 2), (ypos + 2) - - (charHeight / 2), (mpos * charWidth) + (charWidth / 2), - ypos - 2); + g.drawLine((mpos * charWidth) + (charWidth / 2), + (ypos + 2) - (charHeight / 2), + (mpos * charWidth) + (charWidth / 2), ypos - 2); } } } @@@ -208,10 -206,10 +208,10 @@@ if (value != -1) { - int x = LABEL_WEST - fm.stringWidth(String.valueOf(value)) + int x = labelWidthWest - fm.stringWidth(String.valueOf(value)) - charWidth / 2; - g.drawString(value + "", x, (ypos + (i * charHeight)) - - (charHeight / 5)); + g.drawString(value + "", x, + (ypos + (i * charHeight)) - (charHeight / 5)); } } } @@@ -262,8 -260,8 +262,8 @@@ if (value != -1) { - g.drawString(String.valueOf(value), 0, (ypos + (i * charHeight)) - - (charHeight / 5)); + g.drawString(String.valueOf(value), 0, + (ypos + (i * charHeight)) - (charHeight / 5)); } } } @@@ -290,10 -288,10 +290,10 @@@ updateViewport(); ViewportRanges ranges = av.getRanges(); - int sr = ranges.getStartRes(); - int er = ranges.getEndRes(); - int ss = ranges.getStartSeq(); - int es = ranges.getEndSeq(); + int startRes = ranges.getStartRes(); + int endRes = ranges.getEndRes(); + int startSeq = ranges.getStartSeq(); + int endSeq = ranges.getEndSeq(); int transX = 0; int transY = 0; @@@ -302,20 -300,20 +302,20 @@@ if (horizontal > 0) // scrollbar pulled right, image to the left { - transX = (er - sr - horizontal) * charWidth; - sr = er - horizontal; + transX = (endRes - startRes - horizontal) * charWidth; + startRes = endRes - horizontal; } else if (horizontal < 0) { - er = sr - horizontal; + endRes = startRes - horizontal; } else if (vertical > 0) // scroll down { - ss = es - vertical; + startSeq = endSeq - vertical; - if (ss < ranges.getStartSeq()) + if (startSeq < ranges.getStartSeq()) { // ie scrolling too fast, more than a page at a time - ss = ranges.getStartSeq(); + startSeq = ranges.getStartSeq(); } else { @@@ -324,22 -322,32 +324,22 @@@ } else if (vertical < 0) { - es = ss - vertical; + endSeq = startSeq - vertical; - if (es > ranges.getEndSeq()) + if (endSeq > ranges.getEndSeq()) { - es = ranges.getEndSeq(); + endSeq = ranges.getEndSeq(); } } gg.translate(transX, transY); - drawPanel(gg, sr, er, ss, es, 0); + drawPanel(gg, startRes, endRes, startSeq, endSeq, 0); gg.translate(-transX, -transY); repaint(); fastpainting = false; } - /** - * Definitions of startx and endx (hopefully): SMJS This is what I'm working - * towards! startx is the first residue (starting at 0) to display. endx is - * the last residue to display (starting at 0). starty is the first sequence - * to display (starting at 0). endy is the last sequence to display (starting - * at 0). NOTE 1: The av limits are set in setFont in this class and in the - * adjustment listener in SeqPanel when the scrollbars move. - */ - - // Set this to false to force a full panel paint @Override public void paintComponent(Graphics g) { @@@ -348,10 -356,9 +348,9 @@@ // img and call later. super.paintComponent(g); - if (lcimg != null - && (fastPaint - || (getVisibleRect().width != g.getClipBounds().width) || (getVisibleRect().height != g - .getClipBounds().height))) + if (lcimg != null && (fastPaint + || (getVisibleRect().width != g.getClipBounds().width) + || (getVisibleRect().height != g.getClipBounds().height))) { g.drawImage(lcimg, 0, 0, this); fastPaint = false; @@@ -414,63 -421,57 +413,63 @@@ } /** - * DOCUMENT ME! + * Returns the visible width of the canvas in residues, after allowing for + * East or West scales (if shown) * - * @param cwidth - * DOCUMENT ME! + * @param canvasWidth + * the width in pixels (possibly including scales) * - * @return DOCUMENT ME! + * @return */ - public int getWrappedCanvasWidth(int cwidth) + public int getWrappedCanvasWidth(int canvasWidth) { FontMetrics fm = getFontMetrics(av.getFont()); - LABEL_EAST = 0; - LABEL_WEST = 0; + labelWidthEast = 0; + labelWidthWest = 0; if (av.getScaleRightWrapped()) { - LABEL_EAST = fm.stringWidth(getMask()); + labelWidthEast = getLabelWidth(fm); } if (av.getScaleLeftWrapped()) { - LABEL_WEST = fm.stringWidth(getMask()); + labelWidthWest = labelWidthEast > 0 ? labelWidthEast + : getLabelWidth(fm); } - return (cwidth - LABEL_EAST - LABEL_WEST) / charWidth; + return (canvasWidth - labelWidthEast - labelWidthWest) / charWidth; } /** - * Generates a string of zeroes. + * Returns a pixel width suitable for showing the largest sequence coordinate + * (end position) in the alignment. Returns 2 plus the number of decimal + * digits to be shown (3 for 1-10, 4 for 11-99 etc). * - * @return String + * @param fm + * @return */ - String getMask() + protected int getLabelWidth(FontMetrics fm) { - String mask = "00"; + /* + * find the biggest sequence end position we need to show + * (note this is not necessarily the sequence length) + */ int maxWidth = 0; - int tmp; - for (int i = 0; i < av.getAlignment().getHeight(); i++) + AlignmentI alignment = av.getAlignment(); + for (int i = 0; i < alignment.getHeight(); i++) { - tmp = av.getAlignment().getSequenceAt(i).getEnd(); - if (tmp > maxWidth) - { - maxWidth = tmp; - } + maxWidth = Math.max(maxWidth, alignment.getSequenceAt(i).getEnd()); } + int length = 2; for (int i = maxWidth; i > 0; i /= 10) { - mask += "0"; + length++; } - return mask; + + return fm.stringWidth(ZEROS.substring(0, length)); } /** @@@ -491,15 -492,20 +490,15 @@@ updateViewport(); AlignmentI al = av.getAlignment(); - FontMetrics fm = getFontMetrics(av.getFont()); - - LABEL_EAST = 0; - LABEL_WEST = 0; - - if (av.getScaleRightWrapped()) + int labelWidth = 0; + if (av.getScaleRightWrapped() || av.getScaleLeftWrapped()) { - LABEL_EAST = fm.stringWidth(getMask()); + FontMetrics fm = getFontMetrics(av.getFont()); + labelWidth = getLabelWidth(fm); } - if (av.getScaleLeftWrapped()) - { - LABEL_WEST = fm.stringWidth(getMask()); - } + labelWidthEast = av.getScaleRightWrapped() ? labelWidth : 0; + labelWidthWest = av.getScaleLeftWrapped() ? labelWidth : 0; int hgap = charHeight; if (av.getScaleAboveWrapped()) @@@ -507,7 -513,7 +506,7 @@@ hgap += charHeight; } - int cWidth = (canvasWidth - LABEL_EAST - LABEL_WEST) / charWidth; + int cWidth = (canvasWidth - labelWidthEast - labelWidthWest) / charWidth; int cHeight = av.getAlignment().getHeight() * charHeight; av.setWrappedWidth(cWidth); @@@ -524,8 -530,6 +523,8 @@@ .findColumnPosition(maxwidth); } + int annotationHeight = getAnnotationHeight(); + while ((ypos <= canvasHeight) && (startRes < maxwidth)) { endx = startRes + cWidth - 1; @@@ -545,12 -549,12 +544,12 @@@ if (av.getScaleRightWrapped()) { - g.translate(canvasWidth - LABEL_EAST, 0); + g.translate(canvasWidth - labelWidthEast, 0); drawEastScale(g, startRes, endx, ypos); - g.translate(-(canvasWidth - LABEL_EAST), 0); + g.translate(-(canvasWidth - labelWidthEast), 0); } - g.translate(LABEL_WEST, 0); + g.translate(labelWidthWest, 0); if (av.getScaleAboveWrapped()) { @@@ -573,10 -577,12 +572,12 @@@ } gg.fillPolygon( - new int[] { res * charWidth - charHeight / 4, + new int[] + { res * charWidth - charHeight / 4, res * charWidth + charHeight / 4, res * charWidth }, - new int[] { ypos - (charHeight / 2), - ypos - (charHeight / 2), ypos - (charHeight / 2) + 8 }, + new int[] + { ypos - (charHeight / 2), ypos - (charHeight / 2), + ypos - (charHeight / 2) + 8 }, 3); } @@@ -606,14 -612,14 +607,14 @@@ annotations = new AnnotationPanel(av); } - annotations.renderer.drawComponent(annotations, av, g, -1, - startRes, endx + 1); + annotations.renderer.drawComponent(annotations, av, g, -1, startRes, + endx + 1); g.translate(0, -cHeight - ypos - 3); } g.setClip(clip); - g.translate(-LABEL_WEST, 0); + g.translate(-labelWidthWest, 0); - ypos += cHeight + getAnnotationHeight() + hgap; + ypos += cHeight + annotationHeight + hgap; startRes += cWidth; } @@@ -637,35 -643,32 +638,35 @@@ } /** - * DOCUMENT ME! + * Draws the visible region of the alignment on the graphics context. If there + * are hidden column markers in the visible region, then each sub-region + * between the markers is drawn separately, followed by the hidden column + * marker. * * @param g1 - * DOCUMENT ME! * @param startRes - * DOCUMENT ME! + * offset of the first column in the visible region (0..) * @param endRes - * DOCUMENT ME! + * offset of the last column in the visible region (0..) * @param startSeq - * DOCUMENT ME! + * offset of the first sequence in the visible region (0..) * @param endSeq - * DOCUMENT ME! - * @param offset - * DOCUMENT ME! + * offset of the last sequence in the visible region (0..) + * @param yOffset + * vertical offset at which to draw (for wrapped alignments) */ - public void drawPanel(Graphics g1, int startRes, int endRes, int startSeq, - int endSeq, int offset) + public void drawPanel(Graphics g1, final int startRes, final int endRes, + final int startSeq, final int endSeq, final int yOffset) { updateViewport(); if (!av.hasHiddenColumns()) { - draw(g1, startRes, endRes, startSeq, endSeq, offset); + draw(g1, startRes, endRes, startSeq, endSeq, yOffset); } else { int screenY = 0; + final int screenYMax = endRes - startRes; int blockStart = startRes; int blockEnd = endRes; @@@ -681,47 -684,38 +682,47 @@@ continue; } - blockEnd = hideStart - 1; + /* + * draw up to just before the next hidden region, or the end of + * the visible region, whichever comes first + */ + blockEnd = Math.min(hideStart - 1, blockStart + screenYMax + - screenY); g1.translate(screenY * charWidth, 0); - draw(g1, blockStart, blockEnd, startSeq, endSeq, offset); + draw(g1, blockStart, blockEnd, startSeq, endSeq, yOffset); - if (av.getShowHiddenMarkers()) + /* + * draw the downline of the hidden column marker (ScalePanel draws the + * triangle on top) if we reached it + */ + if (av.getShowHiddenMarkers() && blockEnd == hideStart - 1) { g1.setColor(Color.blue); g1.drawLine((blockEnd - blockStart + 1) * charWidth - 1, - 0 + offset, (blockEnd - blockStart + 1) * charWidth - 1, - (endSeq - startSeq + 1) * charHeight + offset); + 0 + yOffset, (blockEnd - blockStart + 1) * charWidth - 1, + (endSeq - startSeq + 1) * charHeight + yOffset); } g1.translate(-screenY * charWidth, 0); screenY += blockEnd - blockStart + 1; blockStart = hideEnd + 1; - if (screenY > (endRes - startRes)) + if (screenY > screenYMax) { // already rendered last block return; } } - if (screenY <= (endRes - startRes)) + if (screenY <= screenYMax) { // remaining visible region to render - blockEnd = blockStart + (endRes - startRes) - screenY; + blockEnd = blockStart + screenYMax - screenY; g1.translate(screenY * charWidth, 0); - draw(g1, blockStart, blockEnd, startSeq, endSeq, offset); + draw(g1, blockStart, blockEnd, startSeq, endSeq, yOffset); g1.translate(-screenY * charWidth, 0); } @@@ -729,21 -723,8 +730,21 @@@ } - // int startRes, int endRes, int startSeq, int endSeq, int x, int y, - // int x1, int x2, int y1, int y2, int startx, int starty, + /** + * Draws a region of the visible alignment + * + * @param g1 + * @param startRes + * offset of the first column in the visible region (0..) + * @param endRes + * offset of the last column in the visible region (0..) + * @param startSeq + * offset of the first sequence in the visible region (0..) + * @param endSeq + * offset of the last sequence in the visible region (0..) + * @param yOffset + * vertical offset at which to draw (for wrapped alignments) + */ private void draw(Graphics g, int startRes, int endRes, int startSeq, int endSeq, int offset) { @@@ -768,26 -749,24 +769,26 @@@ if (av.isShowSequenceFeatures()) { - fr.drawSequence(g, nextSeq, startRes, endRes, offset - + ((i - startSeq) * charHeight), false); + fr.drawSequence(g, nextSeq, startRes, endRes, + offset + ((i - startSeq) * charHeight), false); } - // / Highlight search Results once all sequences have been drawn - // //////////////////////////////////////////////////////// + /* + * highlight search Results once sequence has been drawn + */ if (av.hasSearchResults()) { - int[] visibleResults = av.getSearchResults().getResults(nextSeq, + SearchResultsI searchResults = av.getSearchResults(); + int[] visibleResults = searchResults.getResults(nextSeq, startRes, endRes); if (visibleResults != null) { for (int r = 0; r < visibleResults.length; r += 2) { sr.drawHighlightedText(nextSeq, visibleResults[r], - visibleResults[r + 1], (visibleResults[r] - startRes) - * charWidth, offset - + ((i - startSeq) * charHeight)); + visibleResults[r + 1], + (visibleResults[r] - startRes) * charWidth, + offset + ((i - startSeq) * charHeight)); } } } @@@ -844,7 -823,8 +845,8 @@@ { sx = (group.getStartRes() - startRes) * charWidth; sy = offset + ((i - startSeq) * charHeight); - ex = (((group.getEndRes() + 1) - group.getStartRes()) * charWidth) - 1; + ex = (((group.getEndRes() + 1) - group.getStartRes()) * charWidth) + - 1; if (sx + ex < 0 || sx > visWidth) { @@@ -852,21 -832,19 +854,19 @@@ } if ((sx <= (endRes - startRes) * charWidth) - && group.getSequences(null).contains( - av.getAlignment().getSequenceAt(i))) + && group.getSequences(null) + .contains(av.getAlignment().getSequenceAt(i))) { - if ((bottom == -1) - && !group.getSequences(null).contains( - av.getAlignment().getSequenceAt(i + 1))) + if ((bottom == -1) && !group.getSequences(null) + .contains(av.getAlignment().getSequenceAt(i + 1))) { bottom = sy + charHeight; } if (!inGroup) { - if (((top == -1) && (i == 0)) - || !group.getSequences(null).contains( - av.getAlignment().getSequenceAt(i - 1))) + if (((top == -1) && (i == 0)) || !group.getSequences(null) + .contains(av.getAlignment().getSequenceAt(i - 1))) { top = sy; } @@@ -877,8 -855,8 +877,8 @@@ if (group == av.getSelectionGroup()) { g.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT, - BasicStroke.JOIN_ROUND, 3f, new float[] { 5f, 3f }, - 0f)); + BasicStroke.JOIN_ROUND, 3f, new float[] + { 5f, 3f }, 0f)); g.setColor(Color.RED); } else @@@ -996,169 -974,18 +996,169 @@@ } /** - * DOCUMENT ME! + * Highlights search results in the visible region by rendering as white text + * on a black background. Any previous highlighting is removed. Answers true + * if any highlight was left on the visible alignment (so status bar should be + * set to match), else false. + *

+ * Currently fastPaint is not implemented for wrapped alignments. If a wrapped + * alignment had to be scrolled to show the highlighted region, then it should + * be fully redrawn, otherwise a fast paint can be performed. This argument + * could be removed if fast paint of scrolled wrapped alignment is coded in + * future (JAL-2609). * * @param results - * DOCUMENT ME! + * @param noFastPaint + * @return */ - public void highlightSearchResults(SearchResultsI results) + public boolean highlightSearchResults(SearchResultsI results, + boolean noFastPaint) { - img = null; + if (fastpainting) + { + return false; + } + boolean wrapped = av.getWrapAlignment(); - av.setSearchResults(results); + try + { + fastPaint = !noFastPaint; + fastpainting = fastPaint; + + updateViewport(); + + /* + * to avoid redrawing the whole visible region, we instead + * redraw just the minimal regions to remove previous highlights + * and add new ones + */ + SearchResultsI previous = av.getSearchResults(); + av.setSearchResults(results); + boolean redrawn = false; + boolean drawn = false; + if (wrapped) + { + redrawn = drawMappedPositionsWrapped(previous); + drawn = drawMappedPositionsWrapped(results); + redrawn |= drawn; + } + else + { + redrawn = drawMappedPositions(previous); + drawn = drawMappedPositions(results); + redrawn |= drawn; + } - repaint(); + /* + * if highlights were either removed or added, repaint + */ + if (redrawn) + { + repaint(); + } + + /* + * return true only if highlights were added + */ + return drawn; + + } finally + { + fastpainting = false; + } + } + + /** + * Redraws the minimal rectangle in the visible region (if any) that includes + * mapped positions of the given search results. Whether or not positions are + * highlighted depends on the SearchResults set on the Viewport. This allows + * this method to be called to either clear or set highlighting. Answers true + * if any positions were drawn (in which case a repaint is still required), + * else false. + * + * @param results + * @return + */ + protected boolean drawMappedPositions(SearchResultsI results) + { + if (results == null) + { + return false; + } + + /* + * calculate the minimal rectangle to redraw that + * includes both new and existing search results + */ + int firstSeq = Integer.MAX_VALUE; + int lastSeq = -1; + int firstCol = Integer.MAX_VALUE; + int lastCol = -1; + boolean matchFound = false; + + ViewportRanges ranges = av.getRanges(); + int firstVisibleColumn = ranges.getStartRes(); + int lastVisibleColumn = ranges.getEndRes(); + AlignmentI alignment = av.getAlignment(); + if (av.hasHiddenColumns()) + { + firstVisibleColumn = alignment.getHiddenColumns() + .adjustForHiddenColumns(firstVisibleColumn); + lastVisibleColumn = alignment.getHiddenColumns() + .adjustForHiddenColumns(lastVisibleColumn); + } + + for (int seqNo = ranges.getStartSeq(); seqNo <= ranges + .getEndSeq(); seqNo++) + { + SequenceI seq = alignment.getSequenceAt(seqNo); + + int[] visibleResults = results.getResults(seq, firstVisibleColumn, + lastVisibleColumn); + if (visibleResults != null) + { + for (int i = 0; i < visibleResults.length - 1; i += 2) + { + int firstMatchedColumn = visibleResults[i]; + int lastMatchedColumn = visibleResults[i + 1]; + if (firstMatchedColumn <= lastVisibleColumn + && lastMatchedColumn >= firstVisibleColumn) + { + /* + * found a search results match in the visible region - + * remember the first and last sequence matched, and the first + * and last visible columns in the matched positions + */ + matchFound = true; + firstSeq = Math.min(firstSeq, seqNo); + lastSeq = Math.max(lastSeq, seqNo); + firstMatchedColumn = Math.max(firstMatchedColumn, + firstVisibleColumn); + lastMatchedColumn = Math.min(lastMatchedColumn, + lastVisibleColumn); + firstCol = Math.min(firstCol, firstMatchedColumn); + lastCol = Math.max(lastCol, lastMatchedColumn); + } + } + } + } + + if (matchFound) + { + if (av.hasHiddenColumns()) + { + firstCol = alignment.getHiddenColumns() + .findColumnPosition(firstCol); + lastCol = alignment.getHiddenColumns().findColumnPosition(lastCol); + } + int transX = (firstCol - ranges.getStartRes()) * av.getCharWidth(); + int transY = (firstSeq - ranges.getStartSeq()) * av.getCharHeight(); + gg.translate(transX, transY); + drawPanel(gg, firstCol, lastCol, firstSeq, lastSeq, 0); + gg.translate(-transX, -transY); + } + + return matchFound; } @Override @@@ -1210,143 -1037,4 +1210,143 @@@ } } } + + /** + * Redraws any positions in the search results in the visible region of a + * wrapped alignment. Any highlights are drawn depending on the search results + * set on the Viewport, not the results argument. This allows + * this method to be called either to clear highlights (passing the previous + * search results), or to draw new highlights. + * + * @param results + * @return + */ + protected boolean drawMappedPositionsWrapped(SearchResultsI results) + { + if (results == null) + { + return false; + } + + boolean matchFound = false; + + int wrappedWidth = av.getWrappedWidth(); + int wrappedHeight = getRepeatHeightWrapped(); + + ViewportRanges ranges = av.getRanges(); + int canvasHeight = getHeight(); + int repeats = canvasHeight / wrappedHeight; + if (canvasHeight / wrappedHeight > 0) + { + repeats++; + } + + int firstVisibleColumn = ranges.getStartRes(); + int lastVisibleColumn = ranges.getStartRes() + repeats + * ranges.getViewportWidth() - 1; + + AlignmentI alignment = av.getAlignment(); + if (av.hasHiddenColumns()) + { + firstVisibleColumn = alignment.getHiddenColumns() + .adjustForHiddenColumns(firstVisibleColumn); + lastVisibleColumn = alignment.getHiddenColumns() + .adjustForHiddenColumns(lastVisibleColumn); + } + + int gapHeight = charHeight * (av.getScaleAboveWrapped() ? 2 : 1); + + for (int seqNo = ranges.getStartSeq(); seqNo <= ranges + .getEndSeq(); seqNo++) + { + SequenceI seq = alignment.getSequenceAt(seqNo); + + int[] visibleResults = results.getResults(seq, firstVisibleColumn, + lastVisibleColumn); + if (visibleResults != null) + { + for (int i = 0; i < visibleResults.length - 1; i += 2) + { + int firstMatchedColumn = visibleResults[i]; + int lastMatchedColumn = visibleResults[i + 1]; + if (firstMatchedColumn <= lastVisibleColumn + && lastMatchedColumn >= firstVisibleColumn) + { + /* + * found a search results match in the visible region + */ + firstMatchedColumn = Math.max(firstMatchedColumn, + firstVisibleColumn); + lastMatchedColumn = Math.min(lastMatchedColumn, + lastVisibleColumn); + + /* + * draw each mapped position separately (as contiguous positions may + * wrap across lines) + */ + for (int mappedPos = firstMatchedColumn; mappedPos <= lastMatchedColumn; mappedPos++) + { + int displayColumn = mappedPos; + if (av.hasHiddenColumns()) + { + displayColumn = alignment.getHiddenColumns() + .findColumnPosition(displayColumn); + } + + /* + * transX: offset from left edge of canvas to residue position + */ + int transX = labelWidthWest + + ((displayColumn - ranges.getStartRes()) % wrappedWidth) + * av.getCharWidth(); + + /* + * transY: offset from top edge of canvas to residue position + */ + int transY = gapHeight; + transY += (displayColumn - ranges.getStartRes()) + / wrappedWidth * wrappedHeight; + transY += (seqNo - ranges.getStartSeq()) * av.getCharHeight(); + + /* + * yOffset is from graphics origin to start of visible region + */ + int yOffset = 0;// (displayColumn / wrappedWidth) * wrappedHeight; + if (transY < getHeight()) + { + matchFound = true; + gg.translate(transX, transY); + drawPanel(gg, displayColumn, displayColumn, seqNo, seqNo, + yOffset); + gg.translate(-transX, -transY); + } + } + } + } + } + } + + return matchFound; + } + + /** + * Answers the height in pixels of a repeating section of the wrapped + * alignment, including space above, scale above if shown, sequences, and + * annotation panel if shown + * + * @return + */ + protected int getRepeatHeightWrapped() + { + // gap (and maybe scale) above + int repeatHeight = charHeight * (av.getScaleAboveWrapped() ? 2 : 1); + + // add sequences + repeatHeight += av.getRanges().getViewportHeight() * charHeight; + + // add annotations panel height if shown + repeatHeight += getAnnotationHeight(); + + return repeatHeight; + } } diff --combined src/jalview/gui/SeqPanel.java index d14e908,056a602..e8cc68b --- a/src/jalview/gui/SeqPanel.java +++ b/src/jalview/gui/SeqPanel.java @@@ -62,6 -62,7 +62,6 @@@ import java.awt.event.MouseWheelListene import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.ListIterator; import javax.swing.JPanel; import javax.swing.SwingUtilities; @@@ -73,9 -74,9 +73,9 @@@ import javax.swing.ToolTipManager * @author $author$ * @version $Revision: 1.130 $ */ - public class SeqPanel extends JPanel implements MouseListener, - MouseMotionListener, MouseWheelListener, SequenceListener, - SelectionListener + public class SeqPanel extends JPanel + implements MouseListener, MouseMotionListener, MouseWheelListener, + SequenceListener, SelectionListener { /** DOCUMENT ME!! */ @@@ -84,16 -85,6 +84,16 @@@ /** DOCUMENT ME!! */ public AlignmentPanel ap; + /* + * last column position for mouseMoved event + */ + private int lastMouseColumn; + + /* + * last sequence offset for mouseMoved event + */ + private int lastMouseSeq; + protected int lastres; protected int startseq; @@@ -180,9 -171,6 +180,9 @@@ ssm.addStructureViewerListener(this); ssm.addSelectionListener(this); } + + lastMouseColumn = -1; + lastMouseSeq = -1; } int startWrapBlock = -1; @@@ -216,7 -204,7 +216,7 @@@ int y = evt.getY(); y -= hgap; - x = Math.max(0, x - seqCanvas.LABEL_WEST); + x = Math.max(0, x - seqCanvas.labelWidthWest); int cwidth = seqCanvas.getWrappedCanvasWidth(this.getWidth()); if (cwidth < 1) @@@ -275,15 -263,14 +275,14 @@@ y -= hgap; - seq = Math.min((y % cHeight) / av.getCharHeight(), av.getAlignment() - .getHeight() - 1); + seq = Math.min((y % cHeight) / av.getCharHeight(), + av.getAlignment().getHeight() - 1); } else { - seq = Math.min((y / av.getCharHeight()) - + av.getRanges().getStartSeq(), - av - .getAlignment().getHeight() - 1); + seq = Math.min( + (y / av.getCharHeight()) + av.getRanges().getStartSeq(), + av.getAlignment().getHeight() - 1); } return seq; @@@ -300,8 -287,8 +299,8 @@@ if (editCommand != null && editCommand.getSize() > 0) { ap.alignFrame.addHistoryItem(editCommand); - av.firePropertyChange("alignment", null, av.getAlignment() - .getSequences()); + av.firePropertyChange("alignment", null, + av.getAlignment().getSequences()); } } finally { @@@ -359,8 -346,7 +358,7 @@@ HiddenColumns hidden = av.getAlignment().getHiddenColumns(); - if (av.hasHiddenColumns() - && !hidden.isVisible(seqCanvas.cursorX)) + if (av.hasHiddenColumns() && !hidden.isVisible(seqCanvas.cursorX)) { int original = seqCanvas.cursorX - dx; int maxWidth = av.getAlignment().getWidth(); @@@ -683,8 -669,6 +681,8 @@@ } lastSearchResults = results; + boolean wasScrolled = false; + if (av.isFollowHighlight()) { // don't allow highlight of protein/cDNA to also scroll a complementary @@@ -692,19 -676,14 +690,19 @@@ // over residue to change abruptly, causing highlighted residue in panel 2 // to change, causing a scroll in panel 1 etc) ap.setToScrollComplementPanel(false); - if (ap.scrollToPosition(results, false)) + wasScrolled = ap.scrollToPosition(results, false); + if (wasScrolled) { seqCanvas.revalidate(); } ap.setToScrollComplementPanel(true); } - setStatusMessage(results); - seqCanvas.highlightSearchResults(results); + + boolean noFastPaint = wasScrolled && av.getWrapAlignment(); + if (seqCanvas.highlightSearchResults(results, noFastPaint)) + { + setStatusMessage(results); + } } @Override @@@ -740,18 -719,8 +738,18 @@@ int seq = findSeq(evt); if (column < 0 || seq < 0 || seq >= av.getAlignment().getHeight()) { + lastMouseSeq = -1; return; } + if (column == lastMouseColumn && seq == lastMouseSeq) + { + /* + * just a pixel move without change of residue + */ + return; + } + lastMouseColumn = column; + lastMouseSeq = seq; SequenceI sequence = av.getAlignment().getSequenceAt(seq); @@@ -802,7 -771,11 +800,7 @@@ if (av.isShowSequenceFeatures()) { List features = ap.getFeatureRenderer() - .findFeaturesAtRes(sequence.getDatasetSequence(), pos); - if (isGapped) - { - removeAdjacentFeatures(features, column + 1, sequence); - } + .findFeaturesAtColumn(sequence, column + 1); seqARep.appendFeatures(tooltipText, pos, features, this.ap.getSeqPanel().seqCanvas.fr.getMinMax()); } @@@ -813,13 -786,45 +811,13 @@@ } else { - if (lastTooltip == null - || !lastTooltip.equals(tooltipText.toString())) + String textString = tooltipText.toString(); + if (lastTooltip == null || !lastTooltip.equals(textString)) { - String formatedTooltipText = JvSwingUtils.wrapTooltip(true, - tooltipText.toString()); - // String formatedTooltipText = tooltipText.toString(); - setToolTipText(formatedTooltipText); - lastTooltip = tooltipText.toString(); - } - - } - - } - - /** - * Removes from the list of features any that start after, or end before, the - * given column position. This allows us to retain only those features - * adjacent to a gapped position that straddle the position. Contact features - * that 'straddle' the position are also removed, since they are not 'at' the - * position. - * - * @param features - * @param column - * alignment column (1..) - * @param sequence - */ - protected void removeAdjacentFeatures(List features, - final int column, SequenceI sequence) - { - // TODO should this be an AlignViewController method (and reused by applet)? - ListIterator it = features.listIterator(); - while (it.hasNext()) - { - SequenceFeature sf = it.next(); - if (sf.isContactFeature() - || sequence.findIndex(sf.getBegin()) > column - || sequence.findIndex(sf.getEnd()) < column) - { - it.remove(); + String formattedTooltipText = JvSwingUtils.wrapTooltip(true, + textString); + setToolTipText(formattedTooltipText); + lastTooltip = textString; } } } @@@ -840,8 -845,9 +838,9 @@@ Point p = lastp; if (!event.isShiftDown() || p == null) { - p = (tooltipText != null && tooltipText.length() > 6) ? new Point( - event.getX() + wdth, event.getY() - 20) : null; + p = (tooltipText != null && tooltipText.length() > 6) + ? new Point(event.getX() + wdth, event.getY() - 20) + : null; } /* * TODO: try to modify position region is not obcured by tooltip @@@ -877,48 -883,19 +876,48 @@@ * aligned sequence object * @param column * alignment column - * @param seq + * @param seqIndex * index of sequence in alignment * @return sequence position of residue at column, or adjacent residue if at a * gap */ - int setStatusMessage(SequenceI sequence, final int column, int seq) + int setStatusMessage(SequenceI sequence, final int column, int seqIndex) + { + char sequenceChar = sequence.getCharAt(column); + int pos = sequence.findPosition(column); + setStatusMessage(sequence, seqIndex, sequenceChar, pos); + + return pos; + } + + /** + * Builds the status message for the current cursor location and writes it to + * the status bar, for example + * + *

 +   * Sequence 3 ID: FER1_SOLLC
 +   * Sequence 5 ID: FER1_PEA Residue: THR (4)
 +   * Sequence 5 ID: FER1_PEA Residue: B (3)
 +   * Sequence 6 ID: O.niloticus.3 Nucleotide: Uracil (2)
 +   * 
+ * + * @param sequence + * @param seqIndex + * sequence position in the alignment (1..) + * @param sequenceChar + * the character under the cursor + * @param residuePos + * the sequence residue position (if not over a gap) + */ + protected void setStatusMessage(SequenceI sequence, int seqIndex, + char sequenceChar, int residuePos) { StringBuilder text = new StringBuilder(32); /* * Sequence number (if known), and sequence name. */ - String seqno = seq == -1 ? "" : " " + (seq + 1); + String seqno = seqIndex == -1 ? "" : " " + (seqIndex + 1); text.append("Sequence").append(seqno).append(" ID: ") .append(sequence.getName()); @@@ -927,28 -904,31 +926,28 @@@ /* * Try to translate the display character to residue name (null for gap). */ - final String displayChar = String.valueOf(sequence.getCharAt(column)); - boolean isGapped = Comparison.isGap(sequence.getCharAt(column)); - int pos = sequence.findPosition(column); + boolean isGapped = Comparison.isGap(sequenceChar); if (!isGapped) { boolean nucleotide = av.getAlignment().isNucleotide(); + String displayChar = String.valueOf(sequenceChar); if (nucleotide) { residue = ResidueProperties.nucleotideName.get(displayChar); } else { - residue = "X".equalsIgnoreCase(displayChar) ? "X" : ("*" - .equals(displayChar) ? "STOP" - : ResidueProperties.aa2Triplet.get(displayChar)); + residue = "X".equalsIgnoreCase(displayChar) ? "X" + : ("*".equals(displayChar) ? "STOP" + : ResidueProperties.aa2Triplet.get(displayChar)); } text.append(" ").append(nucleotide ? "Nucleotide" : "Residue") .append(": ").append(residue == null ? displayChar : residue); - text.append(" (").append(Integer.toString(pos)).append(")"); + text.append(" (").append(Integer.toString(residuePos)).append(")"); } ap.alignFrame.statusBar.setText(text.toString()); - - return pos; } /** @@@ -976,9 -956,12 +975,9 @@@ if (seq == ds) { - /* - * Convert position in sequence (base 1) to sequence character array - * index (base 0) - */ - int start = m.getStart() - m.getSequence().getStart(); - setStatusMessage(seq, start, sequenceIndex); + int start = m.getStart(); + setStatusMessage(seq, sequenceIndex, seq.getCharAt(start - 1), + start); return; } } @@@ -998,8 -981,8 +997,8 @@@ int oldWidth = av.getCharWidth(); // Which is bigger, left-right or up-down? - if (Math.abs(evt.getY() - lastMousePress.getY()) > Math.abs(evt - .getX() - lastMousePress.getX())) + if (Math.abs(evt.getY() - lastMousePress.getY()) > Math + .abs(evt.getX() - lastMousePress.getX())) { /* * on drag up or down, decrement or increment font size @@@ -1159,8 -1142,9 +1158,9 @@@ } if (editCommand == null) { - editCommand = new EditCommand(MessageManager.formatMessage( - "label.edit_params", new String[] { label })); + editCommand = new EditCommand(MessageManager + .formatMessage("label.edit_params", new String[] + { label })); } } @@@ -1177,9 -1161,8 +1177,8 @@@ ap.alignFrame.statusBar.setText(message.toString()); // Are we editing within a selection group? - if (groupEditing - || (sg != null && sg.getSequences(av.getHiddenRepSequences()) - .contains(seq))) + if (groupEditing || (sg != null + && sg.getSequences(av.getHiddenRepSequences()).contains(seq))) { fixedColumns = true; @@@ -1275,7 -1258,7 +1274,7 @@@ // Find the next gap before the end // of the visible region boundary boolean blank = false; -- for (fixedRight = fixedRight; fixedRight > lastres; fixedRight--) ++ for (; fixedRight > lastres; fixedRight--) { blank = true; @@@ -1367,8 -1350,8 +1366,8 @@@ } else { - appendEdit(Action.INSERT_GAP, groupSeqs, startres, startres - - lastres); + appendEdit(Action.INSERT_GAP, groupSeqs, startres, + startres - lastres); } } else @@@ -1383,8 -1366,8 +1382,8 @@@ } else { - appendEdit(Action.DELETE_GAP, groupSeqs, startres, lastres - - startres); + appendEdit(Action.DELETE_GAP, groupSeqs, startres, + lastres - startres); } } @@@ -1585,13 -1568,19 +1584,13 @@@ } int column = findColumn(evt); - boolean isGapped = Comparison.isGap(sequence.getCharAt(column)); /* * find features at the position (if not gapped), or straddling * the position (if at a gap) */ List features = seqCanvas.getFeatureRenderer() - .findFeaturesAtRes(sequence.getDatasetSequence(), - sequence.findPosition(column)); - if (isGapped) - { - removeAdjacentFeatures(features, column, sequence); - } + .findFeaturesAtColumn(sequence, column + 1); if (!features.isEmpty()) { @@@ -1599,9 -1588,9 +1598,9 @@@ * highlight the first feature at the position on the alignment */ SearchResultsI highlight = new SearchResults(); - highlight.addResult(sequence, features.get(0).getBegin(), - features.get(0).getEnd()); - seqCanvas.highlightSearchResults(highlight); + highlight.addResult(sequence, features.get(0).getBegin(), features + .get(0).getEnd()); + seqCanvas.highlightSearchResults(highlight, false); /* * open the Amend Features dialog; clear highlighting afterwards, @@@ -1610,8 -1599,7 +1609,8 @@@ List seqs = Collections.singletonList(sequence); seqCanvas.getFeatureRenderer().amendFeatures(seqs, features, false, ap); - seqCanvas.highlightSearchResults(null); + av.setSearchResults(null); // clear highlighting + seqCanvas.repaint(); // draw new/amended features } } } @@@ -1663,8 -1651,9 +1662,9 @@@ if (av.getWrapAlignment() && seq > av.getAlignment().getHeight()) { - JvOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager - .getString("label.cannot_edit_annotations_in_wrapped_view"), + JvOptionPane.showInternalMessageDialog(Desktop.desktop, + MessageManager.getString( + "label.cannot_edit_annotations_in_wrapped_view"), MessageManager.getString("label.wrapped_view_no_edit"), JvOptionPane.WARNING_MESSAGE); return; @@@ -1769,11 -1758,12 +1769,11 @@@ */ void showPopupMenu(MouseEvent evt) { - final int res = findColumn(evt); + final int column = findColumn(evt); final int seq = findSeq(evt); SequenceI sequence = av.getAlignment().getSequenceAt(seq); List allFeatures = ap.getFeatureRenderer() - .findFeaturesAtRes(sequence.getDatasetSequence(), - sequence.findPosition(res)); + .findFeaturesAtColumn(sequence, column + 1); List links = new ArrayList<>(); for (SequenceFeature sf : allFeatures) { @@@ -1815,7 -1805,8 +1815,8 @@@ stretchGroup.cs.alignmentChanged(stretchGroup, av.getHiddenRepSequences()); - ResidueShaderI groupColourScheme = stretchGroup.getGroupColourScheme(); + ResidueShaderI groupColourScheme = stretchGroup + .getGroupColourScheme(); String name = stretchGroup.getName(); if (stretchGroup.cs.conservationApplied()) { @@@ -2014,9 -2005,8 +2015,8 @@@ running = av.getRanges().scrollUp(true); } - if (mouseDragging && (evt.getY() >= getHeight()) - && (av.getAlignment().getHeight() > av.getRanges() - .getEndSeq())) + if (mouseDragging && (evt.getY() >= getHeight()) && (av + .getAlignment().getHeight() > av.getRanges().getEndSeq())) { running = av.getRanges().scrollUp(false); } @@@ -2052,8 -2042,10 +2052,10 @@@ // handles selection messages... // TODO: extend config options to allow user to control if selections may be // shared between viewports. - boolean iSentTheSelection = (av == source || (source instanceof AlignViewport && ((AlignmentViewport) source) - .getSequenceSetId().equals(av.getSequenceSetId()))); + boolean iSentTheSelection = (av == source + || (source instanceof AlignViewport + && ((AlignmentViewport) source).getSequenceSetId() + .equals(av.getSequenceSetId()))); if (iSentTheSelection) { @@@ -2155,8 -2147,7 +2157,7 @@@ repaint = true; } - if (copycolsel - && av.hasHiddenColumns() + if (copycolsel && av.hasHiddenColumns() && (av.getAlignment().getHiddenColumns() == null)) { System.err.println("Bad things"); diff --combined src/jalview/gui/SequenceFetcher.java index da026b5,804d1a5..e05230b --- a/src/jalview/gui/SequenceFetcher.java +++ b/src/jalview/gui/SequenceFetcher.java @@@ -136,11 -136,10 +136,10 @@@ public class SequenceFetcher extends JP { if (guiWindow != null) { - guiWindow - .setProgressBar( - MessageManager - .getString("status.waiting_sequence_database_fetchers_init"), - Thread.currentThread().hashCode()); + guiWindow.setProgressBar( + MessageManager.getString( + "status.waiting_sequence_database_fetchers_init"), + Thread.currentThread().hashCode()); } // initting happening on another thread - so wait around to see if it // finishes. @@@ -157,18 -156,17 +156,17 @@@ } if (guiWindow != null) { - guiWindow - .setProgressBar( - MessageManager - .getString("status.waiting_sequence_database_fetchers_init"), - Thread.currentThread().hashCode()); + guiWindow.setProgressBar( + MessageManager.getString( + "status.waiting_sequence_database_fetchers_init"), + Thread.currentThread().hashCode()); } } - if (sfetch == null - || dasRegistry != Cache.getDasSourceRegistry() + if (sfetch == null || dasRegistry != Cache.getDasSourceRegistry() || lastDasSourceRegistry != (Cache.getDasSourceRegistry() - .getDasRegistryURL() + Cache.getDasSourceRegistry() - .getLocalSourceString()).hashCode()) + .getDasRegistryURL() + + Cache.getDasSourceRegistry().getLocalSourceString()) + .hashCode()) { _initingFetcher = true; initingThread = Thread.currentThread(); @@@ -177,8 -175,9 +175,9 @@@ */ if (guiWindow != null) { - guiWindow.setProgressBar(MessageManager - .getString("status.init_sequence_database_fetchers"), + guiWindow.setProgressBar( + MessageManager.getString( + "status.init_sequence_database_fetchers"), Thread.currentThread().hashCode()); } dasRegistry = Cache.getDasSourceRegistry(); @@@ -189,8 -188,8 +188,8 @@@ { guiWindow.setProgressBar(null, Thread.currentThread().hashCode()); } - lastDasSourceRegistry = (dasRegistry.getDasRegistryURL() + dasRegistry - .getLocalSourceString()).hashCode(); + lastDasSourceRegistry = (dasRegistry.getDasRegistryURL() + + dasRegistry.getLocalSourceString()).hashCode(); sfetch = sf; _initingFetcher = false; initingThread = null; @@@ -234,14 -233,12 +233,12 @@@ @Override public void run() { - JvOptionPane - .showInternalMessageDialog( - Desktop.desktop, - MessageManager - .getString("warn.couldnt_create_sequence_fetcher_client"), - MessageManager - .getString("label.couldnt_create_sequence_fetcher"), - JvOptionPane.ERROR_MESSAGE); + JvOptionPane.showInternalMessageDialog(Desktop.desktop, + MessageManager.getString( + "warn.couldnt_create_sequence_fetcher_client"), + MessageManager.getString( + "label.couldnt_create_sequence_fetcher"), + JvOptionPane.ERROR_MESSAGE); } }); @@@ -311,14 -308,15 +308,15 @@@ if (sourcep.getTier() == 0) { database.selection = Arrays - .asList(new DbSourceProxy[] { sourcep }); + .asList(new DbSourceProxy[] + { sourcep }); break; } } if (database.selection == null || database.selection.size() == 0) { - System.err.println("Ignoring fetch parameter db='" + selectedDb - + "'"); + System.err.println( + "Ignoring fetch parameter db='" + selectedDb + "'"); return false; } textArea.setText(queryString); @@@ -379,9 -377,10 +377,10 @@@ private String getFrameTitle() { - return ((alignFrame == null) ? MessageManager - .getString("label.new_sequence_fetcher") : MessageManager - .getString("label.additional_sequence_fetcher")); + return ((alignFrame == null) + ? MessageManager.getString("label.new_sequence_fetcher") + : MessageManager + .getString("label.additional_sequence_fetcher")); } private void jbInit() throws Exception @@@ -398,8 -397,8 +397,8 @@@ replacePunctuation.setHorizontalAlignment(SwingConstants.CENTER); replacePunctuation .setFont(new java.awt.Font("Verdana", Font.ITALIC, 11)); - replacePunctuation.setText(MessageManager - .getString("label.replace_commas_semicolons")); + replacePunctuation.setText( + MessageManager.getString("label.replace_commas_semicolons")); ok.setText(MessageManager.getString("action.ok")); ok.addActionListener(new ActionListener() { @@@ -538,8 -537,9 +537,9 @@@ + database.getSelectedSources().size() + " others)" : "")); String eq = database.getExampleQueries(); - dbeg.setText(MessageManager.formatMessage( - "label.example_query_param", new String[] { eq })); + dbeg.setText(MessageManager.formatMessage("label.example_query_param", + new String[] + { eq })); boolean enablePunct = !(eq != null && eq.indexOf(",") > -1); for (DbSourceProxy dbs : database.getSelectedSources()) { @@@ -621,7 -621,7 +621,7 @@@ if (replacePunctuation.isEnabled() && replacePunctuation.isSelected()) { empty = new com.stevesoft.pat.Regex( - // replace commas and spaces with a semicolon + // replace commas and spaces with a semicolon "(\\s|[,; ])+", ";"); } else @@@ -631,8 -631,8 +631,8 @@@ } textArea.setText(empty.replaceAll(textArea.getText())); // see if there's anthing to search with - if (!new com.stevesoft.pat.Regex("[A-Za-z0-9_.]").search(textArea - .getText())) + if (!new com.stevesoft.pat.Regex("[A-Za-z0-9_.]") + .search(textArea.getText())) { error += "Please enter a (semi-colon separated list of) database id(s)"; } @@@ -652,8 -652,8 +652,8 @@@ Iterator proxies = database.getSelectedSources() .iterator(); String[] qries; - List nextFetch = Arrays.asList(qries = textArea.getText() - .split(";")); + List nextFetch = Arrays + .asList(qries = textArea.getText().split(";")); Iterator en = Arrays.asList(new String[0]).iterator(); int nqueries = qries.length; @@@ -673,13 -673,11 +673,11 @@@ try { // update status - guiWindow - .setProgressBar(MessageManager.formatMessage( - "status.fetching_sequence_queries_from", - new String[] { - Integer.valueOf(nqueries).toString(), - proxy.getDbName() }), Thread.currentThread() - .hashCode()); + guiWindow.setProgressBar(MessageManager.formatMessage( + "status.fetching_sequence_queries_from", new String[] + { Integer.valueOf(nqueries).toString(), + proxy.getDbName() }), + Thread.currentThread().hashCode()); if (proxy.getMaximumQueryCount() == 1) { /* @@@ -703,8 -701,8 +701,8 @@@ } } catch (Exception e) { - showErrorMessage("Error retrieving " + textArea.getText() - + " from " + database.getSelectedItem()); + showErrorMessage("Error retrieving " + textArea.getText() + " from " + + database.getSelectedItem()); // error // +="Couldn't retrieve sequences from "+database.getSelectedItem(); System.err.println("Retrieval failed for source ='" @@@ -714,9 -712,7 +712,7 @@@ } catch (OutOfMemoryError e) { showErrorMessage("Out of Memory when retrieving " - + textArea.getText() - + " from " - + database.getSelectedItem() + + textArea.getText() + " from " + database.getSelectedItem() + "\nPlease see the Jalview FAQ for instructions for increasing the memory available to Jalview.\n"); e.printStackTrace(); } catch (Error e) @@@ -744,8 -740,8 +740,8 @@@ while (aresult.size() > 0) { presult.add(aresult.remove(0)); - presultTitle.add(aresultq.remove(0) + " " - + getDefaultRetrievalTitle()); + presultTitle.add( + aresultq.remove(0) + " " + getDefaultRetrievalTitle()); } } else @@@ -773,15 -769,17 +769,17 @@@ presultTitle.add(titl); } } - guiWindow.setProgressBar(MessageManager - .getString("status.finshed_querying"), Thread.currentThread() - .hashCode()); + guiWindow.setProgressBar( + MessageManager.getString("status.finshed_querying"), + Thread.currentThread().hashCode()); } - guiWindow.setProgressBar( - (presult.size() > 0) ? MessageManager - .getString("status.parsing_results") : MessageManager - .getString("status.processing"), Thread.currentThread() - .hashCode()); + guiWindow + .setProgressBar( + (presult.size() > 0) + ? MessageManager + .getString("status.parsing_results") + : MessageManager.getString("status.processing"), + Thread.currentThread().hashCode()); // process results while (presult.size() > 0) { @@@ -794,8 -792,9 +792,9 @@@ { StringBuffer sb = new StringBuffer(); sb.append("Didn't retrieve the following " - + (nextFetch.size() == 1 ? "query" : nextFetch.size() - + " queries") + ": \n"); + + (nextFetch.size() == 1 ? "query" + : nextFetch.size() + " queries") + + ": \n"); int l = sb.length(), lr = 0; for (String s : nextFetch) { @@@ -830,8 -829,7 +829,7 @@@ */ void fetchMultipleAccessions(DbSourceProxy proxy, Iterator accessions, List aresultq, - List aresult, List nextFetch) - throws Exception + List aresult, List nextFetch) throws Exception { StringBuilder multiacc = new StringBuilder(); List tosend = new ArrayList(); @@@ -906,8 -904,9 +904,9 @@@ indres = proxy.getSequenceRecords(accession); } catch (OutOfMemoryError oome) { - new OOMWarning("fetching " + accession + " from " - + proxy.getDbName(), oome, this); + new OOMWarning( + "fetching " + accession + " from " + proxy.getDbName(), + oome, this); } if (indres != null) { @@@ -917,9 -916,8 +916,8 @@@ } } catch (Exception e) { - Cache.log.info( - "Error retrieving " + accession + " from " - + proxy.getDbName(), e); + Cache.log.info("Error retrieving " + accession + " from " + + proxy.getDbName(), e); } return success; } @@@ -1006,11 -1004,15 +1004,11 @@@ { for (SequenceI sq : alsqs) { - if ((sfs = sq.getSequenceFeatures()) != null) + if (sq.getFeatures().hasFeatures()) { - if (sfs.length > 0) - { - af.setShowSeqFeatures(true); - break; - } + af.setShowSeqFeatures(true); + break; } - } } diff --combined src/jalview/gui/TreePanel.java index 32c5702,80f0c73..5e14fce --- a/src/jalview/gui/TreePanel.java +++ b/src/jalview/gui/TreePanel.java @@@ -158,8 -158,8 +158,8 @@@ public class TreePanel extends GTreePan } if (evt.getNewValue() == null) { - System.out - .println("new alignment sequences vector value is null"); + System.out.println( + "new alignment sequences vector value is null"); } tree.updatePlaceHolders((List) evt.getNewValue()); @@@ -183,8 -183,8 +183,8 @@@ void buildAssociatedViewMenu() { - AlignmentPanel[] aps = PaintRefresher.getAssociatedPanels(av - .getSequenceSetId()); + AlignmentPanel[] aps = PaintRefresher + .getAssociatedPanels(av.getSequenceSetId()); if (aps.length == 1 && treeCanvas.ap == aps[0]) { associateLeavesMenu.setVisible(false); @@@ -193,7 -193,8 +193,8 @@@ associateLeavesMenu.setVisible(true); - if ((viewMenu.getItem(viewMenu.getItemCount() - 2) instanceof JMenuItem)) + if ((viewMenu + .getItem(viewMenu.getItemCount() - 2) instanceof JMenuItem)) { viewMenu.insertSeparator(viewMenu.getItemCount() - 1); } @@@ -275,11 -276,11 +276,11 @@@ } else { - ScoreModelI sm = ScoreModels.getInstance().getScoreModel( - scoreModelName, treeCanvas.ap); - TreeBuilder njtree = treeType.equals(TreeBuilder.NEIGHBOUR_JOINING) ? new NJTree( - av, sm, similarityParams) : new AverageDistanceTree(av, sm, - similarityParams); + ScoreModelI sm = ScoreModels.getInstance() + .getScoreModel(scoreModelName, treeCanvas.ap); + TreeBuilder njtree = treeType.equals(TreeBuilder.NEIGHBOUR_JOINING) + ? new NJTree(av, sm, similarityParams) + : new AverageDistanceTree(av, sm, similarityParams); tree = new TreeModel(njtree); showDistances(true); } @@@ -363,8 -364,8 +364,8 @@@ JalviewFileChooser chooser = new JalviewFileChooser( jalview.bin.Cache.getProperty("LAST_DIRECTORY")); chooser.setFileView(new JalviewFileView()); - chooser.setDialogTitle(MessageManager - .getString("label.save_tree_as_newick")); + chooser.setDialogTitle( + MessageManager.getString("label.save_tree_as_newick")); chooser.setToolTipText(MessageManager.getString("action.save")); int value = chooser.showSaveDialog(null); @@@ -372,15 -373,15 +373,15 @@@ if (value == JalviewFileChooser.APPROVE_OPTION) { String choice = chooser.getSelectedFile().getPath(); - jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser - .getSelectedFile().getParent()); + jalview.bin.Cache.setProperty("LAST_DIRECTORY", + chooser.getSelectedFile().getParent()); try { jalview.io.NewickFile fout = new jalview.io.NewickFile( tree.getTopNode()); - String output = fout.print(tree.hasBootstrap(), - tree.hasDistances(), tree.hasRootDistance()); + String output = fout.print(tree.hasBootstrap(), tree.hasDistances(), + tree.hasRootDistance()); java.io.PrintWriter out = new java.io.PrintWriter( new java.io.FileWriter(choice)); out.println(output); @@@ -411,8 -412,8 +412,8 @@@ AlignmentView originalData = tree.getOriginalData(); if (originalData == null) { - jalview.bin.Cache.log - .info("Unexpected call to originalSeqData_actionPerformed - should have hidden this menu action."); + jalview.bin.Cache.log.info( + "Unexpected call to originalSeqData_actionPerformed - should have hidden this menu action."); return; } // decide if av alignment is sufficiently different to original data to @@@ -439,8 -440,9 +440,9 @@@ // AlignmentOrder origorder = new AlignmentOrder(alAndColsel[0]); AlignmentI al = new Alignment((SequenceI[]) alAndColsel[0]); - AlignmentI dataset = (av != null && av.getAlignment() != null) ? av - .getAlignment().getDataset() : null; + AlignmentI dataset = (av != null && av.getAlignment() != null) + ? av.getAlignment().getDataset() + : null; if (dataset != null) { al.setDataset(dataset); @@@ -450,8 -452,7 +452,7 @@@ { // make a new frame! AlignFrame af = new AlignFrame(al, (HiddenColumns) alAndColsel[1], - AlignFrame.DEFAULT_WIDTH, - AlignFrame.DEFAULT_HEIGHT); + AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT); // >>>This is a fix for the moment, until a better solution is // found!!<<< @@@ -461,8 -462,8 +462,8 @@@ // msaorder); Desktop.addInternalFrame(af, MessageManager.formatMessage( - "label.original_data_for_params", - new Object[] { this.title }), AlignFrame.DEFAULT_WIDTH, + "label.original_data_for_params", new Object[] + { this.title }), AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT); } } @@@ -493,8 -494,8 +494,8 @@@ if (treeCanvas.applyToAllViews) { final ArrayList commands = new ArrayList(); - for (AlignmentPanel ap : PaintRefresher.getAssociatedPanels(av - .getSequenceSetId())) + for (AlignmentPanel ap : PaintRefresher + .getAssociatedPanels(av.getSequenceSetId())) { commands.add(sortAlignmentIn(ap.av.getAlignPanel())); } @@@ -532,8 -533,8 +533,8 @@@ } } }); - for (AlignmentPanel ap : PaintRefresher.getAssociatedPanels(av - .getSequenceSetId())) + for (AlignmentPanel ap : PaintRefresher + .getAssociatedPanels(av.getSequenceSetId())) { // ensure all the alignFrames refresh their GI after adding an undo item ap.alignFrame.updateEditMenuBar(); @@@ -668,8 -669,8 +669,8 @@@ JalviewFileChooser chooser = new JalviewFileChooser( ImageMaker.EPS_EXTENSION, ImageMaker.EPS_EXTENSION); chooser.setFileView(new JalviewFileView()); - chooser.setDialogTitle(MessageManager - .getString("label.create_eps_from_tree")); + chooser.setDialogTitle( + MessageManager.getString("label.create_eps_from_tree")); chooser.setToolTipText(MessageManager.getString("action.save")); int value = chooser.showSaveDialog(this); @@@ -679,11 -680,13 +680,13 @@@ return; } - Cache.setProperty("LAST_DIRECTORY", chooser.getSelectedFile() - .getParent()); + Cache.setProperty("LAST_DIRECTORY", + chooser.getSelectedFile().getParent()); - FileOutputStream out = new FileOutputStream(chooser.getSelectedFile()); - EpsGraphics2D pg = new EpsGraphics2D("Tree", out, 0, 0, width, height); + FileOutputStream out = new FileOutputStream( + chooser.getSelectedFile()); + EpsGraphics2D pg = new EpsGraphics2D("Tree", out, 0, 0, width, + height); pg.setAccurateTextMode(accurateText); @@@ -715,8 -718,8 +718,8 @@@ ImageMaker.PNG_EXTENSION, ImageMaker.PNG_DESCRIPTION); chooser.setFileView(new jalview.io.JalviewFileView()); - chooser.setDialogTitle(MessageManager - .getString("label.create_png_from_tree")); + chooser.setDialogTitle( + MessageManager.getString("label.create_png_from_tree")); chooser.setToolTipText(MessageManager.getString("action.save")); int value = chooser.showSaveDialog(this); @@@ -726,10 -729,11 +729,11 @@@ return; } - jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser - .getSelectedFile().getParent()); + jalview.bin.Cache.setProperty("LAST_DIRECTORY", + chooser.getSelectedFile().getParent()); - FileOutputStream out = new FileOutputStream(chooser.getSelectedFile()); + FileOutputStream out = new FileOutputStream( + chooser.getSelectedFile()); BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); @@@ -770,9 -774,9 +774,9 @@@ if (sq != null) { // search dbrefs, features and annotation - DBRefEntry[] refs = jalview.util.DBRefUtils.selectRefs( - sq.getDBRefs(), - new String[] { labelClass.toUpperCase() }); + DBRefEntry[] refs = jalview.util.DBRefUtils + .selectRefs(sq.getDBRefs(), new String[] + { labelClass.toUpperCase() }); if (refs != null) { for (int i = 0; i < refs.length; i++) @@@ -789,17 -793,19 +793,17 @@@ } if (newname == null) { - SequenceFeature sf[] = sq.getSequenceFeatures(); - for (int i = 0; sf != null && i < sf.length; i++) + List features = sq.getFeatures() + .getPositionalFeatures(labelClass); + for (SequenceFeature feature : features) { - if (sf[i].getType().equals(labelClass)) + if (newname == null) + { + newname = feature.getDescription(); + } + else { - if (newname == null) - { - newname = new String(sf[i].getDescription()); - } - else - { - newname = newname + "; " + sf[i].getDescription(); - } + newname = newname + "; " + feature.getDescription(); } } } @@@ -821,6 -827,7 +825,7 @@@ * Neighbour Joining Using BLOSUM62 *

* For a tree loaded from file, just uses the file name + * * @return */ public String getPanelTitle() @@@ -833,8 -840,8 +838,8 @@@ /* * i18n description of Neighbour Joining or Average Distance method */ - String treecalcnm = MessageManager.getString("label.tree_calc_" - + treeType.toLowerCase()); + String treecalcnm = MessageManager + .getString("label.tree_calc_" + treeType.toLowerCase()); /* * short score model name (long description can be too long) diff --combined src/jalview/io/ClustalFile.java index d618809,6c35ca1..c21b02c --- a/src/jalview/io/ClustalFile.java +++ b/src/jalview/io/ClustalFile.java @@@ -61,7 -61,8 +61,8 @@@ public class ClustalFile extends AlignF boolean flag = false; boolean rna = false; boolean top = false; - StringBuffer pssecstr = new StringBuffer(), consstr = new StringBuffer(); + StringBuffer pssecstr = new StringBuffer(), + consstr = new StringBuffer(); Vector headers = new Vector(); Hashtable seqhash = new Hashtable(); StringBuffer tempseq; @@@ -158,16 -159,15 +159,15 @@@ } Sequence newSeq = parseId(headers.elementAt(i).toString()); - newSeq.setSequence(seqhash.get(headers.elementAt(i).toString()) - .toString()); + newSeq.setSequence( + seqhash.get(headers.elementAt(i).toString()).toString()); seqs.addElement(newSeq); } else { - System.err - .println("Clustal File Reader: Can't find sequence for " - + headers.elementAt(i)); + System.err.println("Clustal File Reader: Can't find sequence for " + + headers.elementAt(i)); } } AlignmentAnnotation lastssa = null; @@@ -186,9 -186,8 +186,8 @@@ AlignmentAnnotation ssa = StockholmFile.parseAnnotationRow(ss, "secondary structure", consstr.toString()); ssa.label = "Consensus Secondary Structure"; - if (lastssa == null - || !lastssa.getRNAStruc().equals( - ssa.getRNAStruc().replace('-', '.'))) + if (lastssa == null || !lastssa.getRNAStruc() + .equals(ssa.getRNAStruc().replace('-', '.'))) { annotations.addElement(ssa); } @@@ -210,7 -209,10 +209,7 @@@ { String tmp = printId(s[i], jvsuffix); - if (s[i].getSequence().length > max) - { - max = s[i].getSequence().length; - } + max = Math.max(max, s[i].getLength()); if (tmp.length() > maxid) { @@@ -236,20 -238,20 +235,20 @@@ while ((j < s.length) && (s[j] != null)) { - out.append(new Format("%-" + maxid + "s").form(printId(s[j], - jvsuffix) + " ")); + out.append(new Format("%-" + maxid + "s") + .form(printId(s[j], jvsuffix) + " ")); int start = i * len; int end = start + len; - if ((end < s[j].getSequence().length) - && (start < s[j].getSequence().length)) + int length = s[j].getLength(); + if ((end < length) && (start < length)) { out.append(s[j].getSequenceAsString(start, end)); } else { - if (start < s[j].getSequence().length) + if (start < length) { out.append(s[j].getSequenceAsString().substring(start)); } diff --combined src/jalview/io/FeaturesFile.java index e1fccaf,4be8d0e..d2282b1 --- a/src/jalview/io/FeaturesFile.java +++ b/src/jalview/io/FeaturesFile.java @@@ -44,9 -44,8 +44,8 @@@ import java.awt.Color import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; - import java.util.Comparator; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@@ -77,19 -76,6 +76,6 @@@ public class FeaturesFile extends Align protected static final String GFF_VERSION = "##gff-version"; - private static final Comparator SORT_NULL_LAST = new Comparator() - { - @Override - public int compare(String o1, String o2) - { - if (o1 == null) - { - return o2 == null ? 0 : 1; - } - return (o2 == null ? -1 : o1.compareTo(o2)); - } - }; - private AlignmentI lastmatchedAl = null; private SequenceIdMatcher matcher = null; @@@ -108,14 -94,14 +94,14 @@@ /** * Constructor which does not parse the file immediately * -- * @param inFile ++ * @param file * @param paste * @throws IOException */ -- public FeaturesFile(String inFile, DataSourceType paste) ++ public FeaturesFile(String file, DataSourceType paste) throws IOException { -- super(false, inFile, paste); ++ super(false, file, paste); } /** @@@ -131,15 -117,14 +117,14 @@@ * Constructor that optionally parses the file immediately * * @param parseImmediately -- * @param inFile ++ * @param file * @param type * @throws IOException */ -- public FeaturesFile(boolean parseImmediately, String inFile, - DataSourceType type) - throws IOException ++ public FeaturesFile(boolean parseImmediately, String file, + DataSourceType type) throws IOException { -- super(parseImmediately, inFile, type); ++ super(parseImmediately, file, type); } /** @@@ -296,7 -281,7 +281,7 @@@ */ for (SequenceI newseq : newseqs) { - if (newseq.getSequenceFeatures() != null) + if (newseq.getFeatures().hasFeatures()) { align.addSequence(newseq); } @@@ -319,7 -304,8 +304,8 @@@ */ protected boolean parseJalviewFeature(String line, String[] gffColumns, AlignmentI alignment, Map featureColours, - boolean removeHTML, boolean relaxedIdMatching, String featureGroup) + boolean removeHTML, boolean relaxedIdMatching, + String featureGroup) { /* * tokens: description seqid seqIndex start end type [score] @@@ -373,23 -359,20 +359,23 @@@ Color colour = ColorUtils.createColourFromName(ft); featureColours.put(ft, new FeatureColour(colour)); } - SequenceFeature sf = new SequenceFeature(ft, desc, "", startPos, endPos, - featureGroup); + SequenceFeature sf = null; if (gffColumns.length > 6) { float score = Float.NaN; try { score = new Float(gffColumns[6]).floatValue(); - // update colourgradient bounds if allowed to } catch (NumberFormatException ex) { - // leave as NaN + sf = new SequenceFeature(ft, desc, startPos, endPos, featureGroup); } - sf.setScore(score); + sf = new SequenceFeature(ft, desc, startPos, endPos, score, + featureGroup); + } + else + { + sf = new SequenceFeature(ft, desc, startPos, endPos, featureGroup); } parseDescriptionHTML(sf, removeHTML); @@@ -489,191 -472,217 +475,191 @@@ ParseHtmlBodyAndLinks parsed = new ParseHtmlBodyAndLinks( sf.getDescription(), removeHTML, newline); - sf.description = (removeHTML) ? parsed.getNonHtmlContent() - : sf.description; + if (removeHTML) + { + sf.setDescription(parsed.getNonHtmlContent()); + } + for (String link : parsed.getLinks()) { sf.addLink(link); } } /** - * generate a features file for seqs includes non-pos features by default. - * - * @param sequences - * source of sequence features - * @param visible - * hash of feature types and colours - * @return features file contents - */ - public String printJalviewFormat(SequenceI[] sequences, - Map visible) - { - return printJalviewFormat(sequences, visible, true, true); - } - - /** - * generate a features file for seqs with colours from visible (if any) + * Returns contents of a Jalview format features file, for visible features, + * as filtered by type and group. Features with a null group are displayed if + * their feature type is visible. Non-positional features may optionally be + * included (with no check on type or group). * * @param sequences * source of features * @param visible - * hash of Colours for each feature type - * @param visOnly - * when true only feature types in 'visible' will be output - * @param nonpos - * indicates if non-positional features should be output (regardless - * of group or type) - * @return features file contents + * map of colour for each visible feature type + * @param visibleFeatureGroups + * @param includeNonPositional + * if true, include non-positional features (regardless of group or + * type) + * @return */ public String printJalviewFormat(SequenceI[] sequences, - Map visible, boolean visOnly, - boolean nonpos) + Map visible, + List visibleFeatureGroups, boolean includeNonPositional) { - StringBuilder out = new StringBuilder(256); - boolean featuresGen = false; - if (visOnly && !nonpos && (visible == null || visible.size() < 1)) + if (!includeNonPositional && (visible == null || visible.isEmpty())) { // no point continuing. return "No Features Visible"; } - if (visible != null && visOnly) + /* + * write out feature colours (if we know them) + */ + // TODO: decide if feature links should also be written here ? + StringBuilder out = new StringBuilder(256); + if (visible != null) { - // write feature colours only if we're given them and we are generating - // viewed features - // TODO: decide if feature links should also be written here ? - Iterator en = visible.keySet().iterator(); - while (en.hasNext()) + for (Entry featureColour : visible.entrySet()) { - String featureType = en.next().toString(); - FeatureColourI colour = visible.get(featureType); - out.append(colour.toJalviewFormat(featureType)).append(newline); + FeatureColourI colour = featureColour.getValue(); + out.append(colour.toJalviewFormat(featureColour.getKey())).append( + newline); } } - // Work out which groups are both present and visible - List groups = new ArrayList(); - int groupIndex = 0; - boolean isnonpos = false; + String[] types = visible == null ? new String[0] : visible.keySet() + .toArray(new String[visible.keySet().size()]); - SequenceFeature[] features; - for (int i = 0; i < sequences.length; i++) + /* + * sort groups alphabetically, and ensure that features with a + * null or empty group are output after those in named groups + */ + List sortedGroups = new ArrayList(visibleFeatureGroups); + sortedGroups.remove(null); + sortedGroups.remove(""); + Collections.sort(sortedGroups); + sortedGroups.add(null); + sortedGroups.add(""); + + boolean foundSome = false; + + /* + * first output any non-positional features + */ + if (includeNonPositional) { - features = sequences[i].getSequenceFeatures(); - if (features != null) + for (int i = 0; i < sequences.length; i++) { - for (int j = 0; j < features.length; j++) + String sequenceName = sequences[i].getName(); + for (SequenceFeature feature : sequences[i].getFeatures() + .getNonPositionalFeatures()) { - isnonpos = features[j].begin == 0 && features[j].end == 0; - if ((!nonpos && isnonpos) || (!isnonpos && visOnly - && !visible.containsKey(features[j].type))) - { - continue; - } - - if (features[j].featureGroup != null - && !groups.contains(features[j].featureGroup)) - { - groups.add(features[j].featureGroup); - } + foundSome = true; + out.append(formatJalviewFeature(sequenceName, feature)); } } } - String group = null; - do + for (String group : sortedGroups) { - if (groups.size() > 0 && groupIndex < groups.size()) + boolean isNamedGroup = (group != null && !"".equals(group)); + if (isNamedGroup) { - group = groups.get(groupIndex); out.append(newline); out.append("STARTGROUP").append(TAB); out.append(group); out.append(newline); } - else - { - group = null; - } + /* + * output positional features within groups + */ for (int i = 0; i < sequences.length; i++) { - features = sequences[i].getSequenceFeatures(); - if (features != null) + String sequenceName = sequences[i].getName(); + List features = new ArrayList(); + if (types.length > 0) { - for (SequenceFeature sequenceFeature : features) - { - isnonpos = sequenceFeature.begin == 0 - && sequenceFeature.end == 0; - if ((!nonpos && isnonpos) || (!isnonpos && visOnly - && !visible.containsKey(sequenceFeature.type))) - { - // skip if feature is nonpos and we ignore them or if we only - // output visible and it isn't non-pos and it's not visible - continue; - } - - if (group != null && (sequenceFeature.featureGroup == null - || !sequenceFeature.featureGroup.equals(group))) - { - continue; - } + features.addAll(sequences[i].getFeatures().getFeaturesForGroup( + true, group, types)); + } - if (group == null && sequenceFeature.featureGroup != null) - { - continue; - } - // we have features to output - featuresGen = true; - if (sequenceFeature.description == null - || sequenceFeature.description.equals("")) - { - out.append(sequenceFeature.type).append(TAB); - } - else - { - if (sequenceFeature.links != null && sequenceFeature - .getDescription().indexOf("") == -1) - { - out.append(""); - } - - out.append(sequenceFeature.description); - if (sequenceFeature.links != null) - { - for (int l = 0; l < sequenceFeature.links.size(); l++) - { - String label = sequenceFeature.links.elementAt(l); - String href = label.substring(label.indexOf("|") + 1); - label = label.substring(0, label.indexOf("|")); - - if (sequenceFeature.description.indexOf(href) == -1) - { - out.append( - " " + label + ""); - } - } - - if (sequenceFeature.getDescription() - .indexOf("") == -1) - { - out.append(""); - } - } - - out.append(TAB); - } - out.append(sequences[i].getName()); - out.append("\t-1\t"); - out.append(sequenceFeature.begin); - out.append(TAB); - out.append(sequenceFeature.end); - out.append(TAB); - out.append(sequenceFeature.type); - if (!Float.isNaN(sequenceFeature.score)) - { - out.append(TAB); - out.append(sequenceFeature.score); - } - out.append(newline); - } + for (SequenceFeature sequenceFeature : features) + { + foundSome = true; + out.append(formatJalviewFeature(sequenceName, sequenceFeature)); } } - if (group != null) + if (isNamedGroup) { out.append("ENDGROUP").append(TAB); out.append(group); out.append(newline); - groupIndex++; } - else + } + + return foundSome ? out.toString() : "No Features Visible"; + } + + /** + * @param out + * @param sequenceName + * @param sequenceFeature + */ + protected String formatJalviewFeature( + String sequenceName, SequenceFeature sequenceFeature) + { + StringBuilder out = new StringBuilder(64); + if (sequenceFeature.description == null + || sequenceFeature.description.equals("")) + { + out.append(sequenceFeature.type).append(TAB); + } + else + { + if (sequenceFeature.links != null + && sequenceFeature.getDescription().indexOf("") == -1) { - break; + out.append(""); } - } while (groupIndex < groups.size() + 1); + out.append(sequenceFeature.description); + if (sequenceFeature.links != null) + { + for (int l = 0; l < sequenceFeature.links.size(); l++) + { + String label = sequenceFeature.links.elementAt(l); + String href = label.substring(label.indexOf("|") + 1); + label = label.substring(0, label.indexOf("|")); + + if (sequenceFeature.description.indexOf(href) == -1) + { + out.append(" " + label + ""); + } + } + + if (sequenceFeature.getDescription().indexOf("") == -1) + { + out.append(""); + } + } - if (!featuresGen) + out.append(TAB); + } + out.append(sequenceName); + out.append("\t-1\t"); + out.append(sequenceFeature.begin); + out.append(TAB); + out.append(sequenceFeature.end); + out.append(TAB); + out.append(sequenceFeature.type); + if (!Float.isNaN(sequenceFeature.score)) { - return "No Features Visible"; + out.append(TAB); + out.append(sequenceFeature.score); } + out.append(newline); return out.toString(); } @@@ -731,90 -740,102 +717,90 @@@ } /** - * Returns features output in GFF2 format, including hidden and non-positional - * features - * - * @param sequences - * the sequences whose features are to be output - * @param visible - * a map whose keys are the type names of visible features - * @return - */ - public String printGffFormat(SequenceI[] sequences, - Map visible) - { - return printGffFormat(sequences, visible, true, true); - } - - /** * Returns features output in GFF2 format * * @param sequences * the sequences whose features are to be output * @param visible * a map whose keys are the type names of visible features - * @param outputVisibleOnly + * @param visibleFeatureGroups * @param includeNonPositionalFeatures * @return */ public String printGffFormat(SequenceI[] sequences, - Map visible, boolean outputVisibleOnly, + Map visible, + List visibleFeatureGroups, boolean includeNonPositionalFeatures) { StringBuilder out = new StringBuilder(256); - int version = gffVersion == 0 ? 2 : gffVersion; - out.append(String.format("%s %d\n", GFF_VERSION, version)); - String source; - boolean isnonpos; + + out.append(String.format("%s %d\n", GFF_VERSION, gffVersion == 0 ? 2 : gffVersion)); + + if (!includeNonPositionalFeatures + && (visible == null || visible.isEmpty())) + { + return out.toString(); + } + + String[] types = visible == null ? new String[0] : visible.keySet() + .toArray( + new String[visible.keySet().size()]); + for (SequenceI seq : sequences) { - SequenceFeature[] features = seq.getSequenceFeatures(); - if (features != null) + List features = new ArrayList(); + if (includeNonPositionalFeatures) { - for (SequenceFeature sf : features) - { - isnonpos = sf.begin == 0 && sf.end == 0; - if (!includeNonPositionalFeatures && isnonpos) - { - /* - * ignore non-positional features if not wanted - */ - continue; - } - // TODO why the test !isnonpos here? - // what about not visible non-positional features? - if (!isnonpos && outputVisibleOnly - && !visible.containsKey(sf.type)) - { - /* - * ignore not visible features if not wanted - */ - continue; - } + features.addAll(seq.getFeatures().getNonPositionalFeatures()); + } + if (visible != null && !visible.isEmpty()) + { + features.addAll(seq.getFeatures().getPositionalFeatures(types)); + } - source = sf.featureGroup; - if (source == null) - { - source = sf.getDescription(); - } + for (SequenceFeature sf : features) + { + String source = sf.featureGroup; + if (!sf.isNonPositional() && source != null + && !visibleFeatureGroups.contains(source)) + { + // group is not visible + continue; + } - out.append(seq.getName()); - out.append(TAB); - out.append(source); - out.append(TAB); - out.append(sf.type); - out.append(TAB); - out.append(sf.begin); - out.append(TAB); - out.append(sf.end); - out.append(TAB); - out.append(sf.score); - out.append(TAB); - - int strand = sf.getStrand(); - out.append(strand == 1 ? "+" : (strand == -1 ? "-" : ".")); - out.append(TAB); - - String phase = sf.getPhase(); - out.append(phase == null ? "." : phase); - - // miscellaneous key-values (GFF column 9) - String attributes = sf.getAttributes(); - if (attributes != null) - { - out.append(TAB).append(attributes); - } + if (source == null) + { + source = sf.getDescription(); + } - out.append(newline); + out.append(seq.getName()); + out.append(TAB); + out.append(source); + out.append(TAB); + out.append(sf.type); + out.append(TAB); + out.append(sf.begin); + out.append(TAB); + out.append(sf.end); + out.append(TAB); + out.append(sf.score); + out.append(TAB); + + int strand = sf.getStrand(); + out.append(strand == 1 ? "+" : (strand == -1 ? "-" : ".")); + out.append(TAB); + + String phase = sf.getPhase(); + out.append(phase == null ? "." : phase); + + // miscellaneous key-values (GFF column 9) + String attributes = sf.getAttributes(); + if (attributes != null) + { + out.append(TAB).append(attributes); } + + out.append(newline); } } @@@ -876,8 -897,8 +862,8 @@@ fromCount = Integer.parseInt(tokens[2]); } catch (NumberFormatException nfe) { - throw new IOException("Invalid number in Align field: " - + nfe.getMessage()); + throw new IOException( + "Invalid number in Align field: " + nfe.getMessage()); } /* @@@ -1075,11 -1096,10 +1061,11 @@@ // rename sequences if GFF handler requested this // TODO a more elegant way e.g. gffHelper.postProcess(newseqs) ? - SequenceFeature[] sfs = seq.getSequenceFeatures(); - if (sfs != null) + List sfs = seq.getFeatures().getPositionalFeatures(); + if (!sfs.isEmpty()) { - String newName = (String) sfs[0].getValue(GffHelperI.RENAME_TOKEN); + String newName = (String) sfs.get(0).getValue( + GffHelperI.RENAME_TOKEN); if (newName != null) { seq.setName(newName); @@@ -1098,9 -1118,8 +1084,8 @@@ * @param newseqs * @throws IOException */ - protected void processGffPragma(String line, - Map gffProps, AlignmentI align, - List newseqs) throws IOException + protected void processGffPragma(String line, Map gffProps, + AlignmentI align, List newseqs) throws IOException { line = line.trim(); if ("###".equals(line)) diff --combined src/jalview/io/IdentifyFile.java index be0df21,7ad8fcd..ff959b0 --- a/src/jalview/io/IdentifyFile.java +++ b/src/jalview/io/IdentifyFile.java @@@ -72,10 -72,11 +72,11 @@@ public class IdentifyFil // preserves original behaviour prior to version 2.3 } - public FileFormatI identify(AlignmentFileReaderI file, boolean closeSource) - throws IOException + public FileFormatI identify(AlignmentFileReaderI file, + boolean closeSource) throws IOException { - FileParse fp = new FileParse(file.getInFile(), file.getDataSourceType()); + FileParse fp = new FileParse(file.getInFile(), + file.getDataSourceType()); return identify(fp, closeSource); } @@@ -274,11 -275,6 +275,11 @@@ // read as a FASTA (probably) break; } + if (data.indexOf("{\"") > -1) + { + reply = FileFormat.Json; + break; + } int lessThan = data.indexOf("<"); if ((lessThan > -1)) // possible Markup Language data i.e HTML, // RNAML, XML @@@ -296,6 -292,11 +297,6 @@@ } } - if (data.indexOf("{\"") > -1) - { - reply = FileFormat.Json; - break; - } if ((data.length() < 1) || (data.indexOf("#") == 0)) { lineswereskipped = true; @@@ -309,9 -310,8 +310,8 @@@ break; } - if ((data.indexOf("//") == 0) - || ((data.indexOf("!!") > -1) && (data.indexOf("!!") < data - .indexOf("_MULTIPLE_ALIGNMENT ")))) + if ((data.indexOf("//") == 0) || ((data.indexOf("!!") > -1) && (data + .indexOf("!!") < data.indexOf("_MULTIPLE_ALIGNMENT ")))) { reply = FileFormat.MSF; @@@ -361,8 -361,8 +361,8 @@@ } if (trimmedLength == 0) { - System.err - .println("File Identification failed! - Empty file was read."); + System.err.println( + "File Identification failed! - Empty file was read."); throw new FileFormatException("EMPTY DATA FILE"); } System.out.println("File format identified as " + reply.toString()); @@@ -428,9 -428,9 +428,9 @@@ type = ider.identify(args[i], DataSourceType.FILE); } catch (FileFormatException e) { - System.err.println(String.format( - "Error '%s' identifying file type for %s", args[i], - e.getMessage())); + System.err.println( + String.format("Error '%s' identifying file type for %s", + args[i], e.getMessage())); } System.out.println("Type of " + args[i] + " is " + type); } diff --combined src/jalview/io/JSONFile.java index 36fe35a,5d9c804..fda22dc --- a/src/jalview/io/JSONFile.java +++ b/src/jalview/io/JSONFile.java @@@ -51,7 -51,6 +51,7 @@@ import jalview.schemes.ColourSchemeProp import jalview.schemes.JalviewColourScheme; import jalview.schemes.ResidueColourScheme; import jalview.util.ColorUtils; +import jalview.util.Format; import jalview.viewmodel.seqfeatures.FeaturesDisplayed; import java.awt.Color; @@@ -219,9 -218,8 +219,8 @@@ public class JSONFile extends AlignFil // are not exported if (globalColourScheme .equalsIgnoreCase(JalviewColourScheme.RNAHelices.toString()) - || globalColourScheme - .equalsIgnoreCase(JalviewColourScheme.TCoffee - .toString())) + || globalColourScheme.equalsIgnoreCase( + JalviewColourScheme.TCoffee.toString())) { jsonAlignmentPojo.setGlobalColorScheme(ResidueColourScheme.NONE); } @@@ -229,7 -227,8 +228,7 @@@ if (exportSettings.isExportFeatures()) { - jsonAlignmentPojo - .setSeqFeatures(sequenceFeatureToJsonPojo(sqs, fr)); + jsonAlignmentPojo.setSeqFeatures(sequenceFeatureToJsonPojo(sqs)); } if (exportSettings.isExportGroups() && seqGroups != null @@@ -309,8 -308,8 +308,8 @@@ return hiddenSections; } - public List sequenceFeatureToJsonPojo( - SequenceI[] sqs, FeatureRenderer fr) + protected List sequenceFeatureToJsonPojo( + SequenceI[] sqs) { displayedFeatures = (fr == null) ? null : fr.getFeaturesDisplayed(); List sequenceFeaturesPojo = new ArrayList<>(); @@@ -321,38 -320,42 +320,38 @@@ FeatureColourFinder finder = new FeatureColourFinder(fr); + String[] visibleFeatureTypes = displayedFeatures == null ? null + : displayedFeatures.getVisibleFeatures().toArray( + new String[displayedFeatures.getVisibleFeatureCount()]); + for (SequenceI seq : sqs) { - SequenceI dataSetSequence = seq.getDatasetSequence(); - SequenceFeature[] seqFeatures = (dataSetSequence == null) ? null - : seq.getDatasetSequence().getSequenceFeatures(); - - seqFeatures = (seqFeatures == null) ? seq.getSequenceFeatures() - : seqFeatures; - if (seqFeatures == null) - { - continue; - } - + /* + * get all features currently visible (and any non-positional features) + */ + List seqFeatures = seq.getFeatures().getAllFeatures( + visibleFeatureTypes); for (SequenceFeature sf : seqFeatures) { - if (displayedFeatures != null - && displayedFeatures.isVisible(sf.getType())) - { - SequenceFeaturesPojo jsonFeature = new SequenceFeaturesPojo( - String.valueOf(seq.hashCode())); - - String featureColour = (fr == null) ? null - : jalview.util.Format.getHexString( - finder.findFeatureColour(Color.white, seq, - seq.findIndex(sf.getBegin()))); - jsonFeature.setXstart(seq.findIndex(sf.getBegin()) - 1); - jsonFeature.setXend(seq.findIndex(sf.getEnd())); - jsonFeature.setType(sf.getType()); - jsonFeature.setDescription(sf.getDescription()); - jsonFeature.setLinks(sf.links); - jsonFeature.setOtherDetails(sf.otherDetails); - jsonFeature.setScore(sf.getScore()); - jsonFeature.setFillColor(featureColour); - jsonFeature.setFeatureGroup(sf.getFeatureGroup()); - sequenceFeaturesPojo.add(jsonFeature); - } + SequenceFeaturesPojo jsonFeature = new SequenceFeaturesPojo( + String.valueOf(seq.hashCode())); + + String featureColour = (fr == null) ? null : Format + .getHexString(finder.findFeatureColour(Color.white, seq, + seq.findIndex(sf.getBegin()))); + int xStart = sf.getBegin() == 0 ? 0 + : seq.findIndex(sf.getBegin()) - 1; + int xEnd = sf.getEnd() == 0 ? 0 : seq.findIndex(sf.getEnd()); + jsonFeature.setXstart(xStart); + jsonFeature.setXend(xEnd); + jsonFeature.setType(sf.getType()); + jsonFeature.setDescription(sf.getDescription()); + jsonFeature.setLinks(sf.links); + jsonFeature.setOtherDetails(sf.otherDetails); + jsonFeature.setScore(sf.getScore()); + jsonFeature.setFillColor(featureColour); + jsonFeature.setFeatureGroup(sf.getFeatureGroup()); + sequenceFeaturesPojo.add(jsonFeature); } } return sequenceFeaturesPojo; @@@ -406,8 -409,8 +405,8 @@@ annotationPojo.setDisplayCharacter(displayChar); if (annotation.colour != null) { - annotationPojo.setColour(jalview.util.Format - .getHexString(annotation.colour)); + annotationPojo.setColour( + jalview.util.Format.getHexString(annotation.colour)); } alignAnnotPojo.getAnnotations().add(annotationPojo); } @@@ -451,8 -454,8 +450,8 @@@ { globalColourScheme = (String) jvSettingsJsonObj .get("globalColorScheme"); - Boolean showFeatures = Boolean.valueOf(jvSettingsJsonObj.get( - "showSeqFeatures").toString()); + Boolean showFeatures = Boolean.valueOf( + jvSettingsJsonObj.get("showSeqFeatures").toString()); setShowSeqFeatures(showFeatures); parseHiddenSeqRefsAsList(jvSettingsJsonObj); parseHiddenCols(jvSettingsJsonObj); @@@ -460,8 -463,8 +459,8 @@@ hiddenSequences = new ArrayList<>(); seqMap = new Hashtable<>(); - for (Iterator sequenceIter = seqJsonArray.iterator(); sequenceIter - .hasNext();) + for (Iterator sequenceIter = seqJsonArray + .iterator(); sequenceIter.hasNext();) { JSONObject sequence = sequenceIter.next(); String sequcenceString = sequence.get("seq").toString(); @@@ -481,22 -484,22 +480,22 @@@ parseFeatures(jsonSeqArray); - for (Iterator seqGrpIter = seqGrpJsonArray.iterator(); seqGrpIter - .hasNext();) + for (Iterator seqGrpIter = seqGrpJsonArray + .iterator(); seqGrpIter.hasNext();) { JSONObject seqGrpObj = seqGrpIter.next(); String grpName = seqGrpObj.get("groupName").toString(); String colourScheme = seqGrpObj.get("colourScheme").toString(); String description = (seqGrpObj.get("description") == null) ? null : seqGrpObj.get("description").toString(); - boolean displayBoxes = Boolean.valueOf(seqGrpObj - .get("displayBoxes").toString()); - boolean displayText = Boolean.valueOf(seqGrpObj.get("displayText") - .toString()); - boolean colourText = Boolean.valueOf(seqGrpObj.get("colourText") - .toString()); - boolean showNonconserved = Boolean.valueOf(seqGrpObj.get( - "showNonconserved").toString()); + boolean displayBoxes = Boolean + .valueOf(seqGrpObj.get("displayBoxes").toString()); + boolean displayText = Boolean + .valueOf(seqGrpObj.get("displayText").toString()); + boolean colourText = Boolean + .valueOf(seqGrpObj.get("colourText").toString()); + boolean showNonconserved = Boolean + .valueOf(seqGrpObj.get("showNonconserved").toString()); int startRes = Integer .valueOf(seqGrpObj.get("startRes").toString()); int endRes = Integer.valueOf(seqGrpObj.get("endRes").toString()); @@@ -518,23 -521,23 +517,23 @@@ } SequenceGroup seqGrp = new SequenceGroup(grpSeqs, grpName, null, displayBoxes, displayText, colourText, startRes, endRes); - seqGrp.setColourScheme(ColourSchemeMapper.getJalviewColourScheme( - colourScheme, seqGrp)); + seqGrp.setColourScheme(ColourSchemeMapper + .getJalviewColourScheme(colourScheme, seqGrp)); seqGrp.setShowNonconserved(showNonconserved); seqGrp.setDescription(description); this.seqGroups.add(seqGrp); } - for (Iterator alAnnotIter = alAnnotJsonArray.iterator(); alAnnotIter - .hasNext();) + for (Iterator alAnnotIter = alAnnotJsonArray + .iterator(); alAnnotIter.hasNext();) { JSONObject alAnnot = alAnnotIter.next(); JSONArray annotJsonArray = (JSONArray) alAnnot.get("annotations"); Annotation[] annotations = new Annotation[annotJsonArray.size()]; int count = 0; - for (Iterator annotIter = annotJsonArray.iterator(); annotIter - .hasNext();) + for (Iterator annotIter = annotJsonArray + .iterator(); annotIter.hasNext();) { JSONObject annot = annotIter.next(); if (annot == null) @@@ -543,59 -546,64 +542,64 @@@ } else { - float val = annot.get("value") == null ? null : Float - .valueOf(annot.get("value").toString()); - String desc = annot.get("description") == null ? null : annot - .get("description").toString(); + float val = annot.get("value") == null ? null + : Float.valueOf(annot.get("value").toString()); + String desc = annot.get("description") == null ? null + : annot.get("description").toString(); char ss = annot.get("secondaryStructure") == null || annot.get("secondaryStructure").toString() - .equalsIgnoreCase("u0000") ? ' ' : annot - .get("secondaryStructure").toString().charAt(0); + .equalsIgnoreCase("u0000") ? ' ' + : annot.get("secondaryStructure") + .toString().charAt(0); String displayChar = annot.get("displayCharacter") == null ? "" : annot.get("displayCharacter").toString(); annotations[count] = new Annotation(displayChar, desc, ss, val); if (annot.get("colour") != null) { - Color color = ColorUtils.parseColourString(annot.get( - "colour").toString()); + Color color = ColorUtils + .parseColourString(annot.get("colour").toString()); annotations[count].colour = color; } } ++count; } - AlignmentAnnotation alignAnnot = new AlignmentAnnotation(alAnnot - .get("label").toString(), alAnnot.get("description") - .toString(), annotations); - alignAnnot.graph = (alAnnot.get("graphType") == null) ? 0 : Integer - .valueOf(alAnnot.get("graphType").toString()); + AlignmentAnnotation alignAnnot = new AlignmentAnnotation( + alAnnot.get("label").toString(), + alAnnot.get("description").toString(), annotations); + alignAnnot.graph = (alAnnot.get("graphType") == null) ? 0 + : Integer.valueOf(alAnnot.get("graphType").toString()); JSONObject diplaySettings = (JSONObject) alAnnot .get("annotationSettings"); if (diplaySettings != null) { - alignAnnot.scaleColLabel = (diplaySettings.get("scaleColLabel") == null) ? false - : Boolean.valueOf(diplaySettings.get("scaleColLabel") - .toString()); + alignAnnot.scaleColLabel = (diplaySettings + .get("scaleColLabel") == null) ? false + : Boolean.valueOf(diplaySettings + .get("scaleColLabel").toString()); alignAnnot.showAllColLabels = (diplaySettings - .get("showAllColLabels") == null) ? true : Boolean - .valueOf(diplaySettings.get("showAllColLabels") - .toString()); + .get("showAllColLabels") == null) ? true + : Boolean.valueOf(diplaySettings + .get("showAllColLabels").toString()); alignAnnot.centreColLabels = (diplaySettings .get("centreColLabels") == null) ? true - : Boolean.valueOf(diplaySettings.get("centreColLabels") - .toString()); - alignAnnot.belowAlignment = (diplaySettings.get("belowAlignment") == null) ? false - : Boolean.valueOf(diplaySettings.get("belowAlignment") - .toString()); - alignAnnot.visible = (diplaySettings.get("visible") == null) ? true - : Boolean.valueOf(diplaySettings.get("visible") - .toString()); - alignAnnot.hasIcons = (diplaySettings.get("hasIcon") == null) ? true - : Boolean.valueOf(diplaySettings.get("hasIcon") - .toString()); + : Boolean.valueOf(diplaySettings + .get("centreColLabels").toString()); + alignAnnot.belowAlignment = (diplaySettings + .get("belowAlignment") == null) ? false + : Boolean.valueOf(diplaySettings + .get("belowAlignment").toString()); + alignAnnot.visible = (diplaySettings.get("visible") == null) + ? true + : Boolean.valueOf( + diplaySettings.get("visible").toString()); + alignAnnot.hasIcons = (diplaySettings.get("hasIcon") == null) + ? true + : Boolean.valueOf( + diplaySettings.get("hasIcon").toString()); } if (alAnnot.get("score") != null) @@@ -604,11 -612,12 +608,12 @@@ .valueOf(alAnnot.get("score").toString()); } - String calcId = (alAnnot.get("calcId") == null) ? "" : alAnnot.get( - "calcId").toString(); + String calcId = (alAnnot.get("calcId") == null) ? "" + : alAnnot.get("calcId").toString(); alignAnnot.setCalcId(calcId); - String seqHash = (alAnnot.get("sequenceRef") != null) ? alAnnot - .get("sequenceRef").toString() : null; + String seqHash = (alAnnot.get("sequenceRef") != null) + ? alAnnot.get("sequenceRef").toString() + : null; Sequence sequence = (seqHash != null) ? seqMap.get(seqHash) : null; if (sequence != null) @@@ -670,31 -679,20 +675,31 @@@ if (jsonSeqFeatures != null) { displayedFeatures = new FeaturesDisplayed(); - for (Iterator seqFeatureItr = jsonSeqFeatures.iterator(); seqFeatureItr - .hasNext();) + for (Iterator seqFeatureItr = jsonSeqFeatures + .iterator(); seqFeatureItr.hasNext();) { JSONObject jsonFeature = seqFeatureItr.next(); Long begin = (Long) jsonFeature.get("xStart"); Long end = (Long) jsonFeature.get("xEnd"); String type = (String) jsonFeature.get("type"); String featureGrp = (String) jsonFeature.get("featureGroup"); - String descripiton = (String) jsonFeature.get("description"); + String description = (String) jsonFeature.get("description"); String seqRef = (String) jsonFeature.get("sequenceRef"); Float score = Float.valueOf(jsonFeature.get("score").toString()); Sequence seq = seqMap.get(seqRef); - SequenceFeature sequenceFeature = new SequenceFeature(); + + /* + * begin/end of 0 is for a non-positional feature + */ + int featureBegin = begin.intValue() == 0 ? 0 : seq + .findPosition(begin.intValue()); + int featureEnd = end.intValue() == 0 ? 0 : seq.findPosition(end + .intValue()) - 1; + + SequenceFeature sequenceFeature = new SequenceFeature(type, + description, featureBegin, featureEnd, score, featureGrp); + JSONArray linksJsonArray = (JSONArray) jsonFeature.get("links"); if (linksJsonArray != null && linksJsonArray.size() > 0) { @@@ -705,7 -703,12 +710,7 @@@ sequenceFeature.addLink(link); } } - sequenceFeature.setFeatureGroup(featureGrp); - sequenceFeature.setScore(score); - sequenceFeature.setDescription(descripiton); - sequenceFeature.setType(type); - sequenceFeature.setBegin(seq.findPosition(begin.intValue())); - sequenceFeature.setEnd(seq.findPosition(end.intValue()) - 1); + seq.addSequenceFeature(sequenceFeature); displayedFeatures.setVisible(type); } @@@ -760,8 -763,8 +765,8 @@@ } } } - globalColourScheme = ColourSchemeProperty.getColourName(viewport - .getGlobalColourScheme()); + globalColourScheme = ColourSchemeProperty + .getColourName(viewport.getGlobalColourScheme()); setDisplayedFeatures(viewport.getFeaturesDisplayed()); showSeqFeatures = viewport.isShowSequenceFeatures(); diff --combined src/jalview/io/JnetAnnotationMaker.java index 2a8a00f,55138e7..c9f1fcf --- a/src/jalview/io/JnetAnnotationMaker.java +++ b/src/jalview/io/JnetAnnotationMaker.java @@@ -59,22 -59,19 +59,19 @@@ public class JnetAnnotationMake // in the future we could search for the query // sequence in the alignment before calling this function. SequenceI seqRef = al.getSequenceAt(firstSeq); - int width = preds[0].getSequence().length; + int width = preds[0].getLength(); int[] gapmap = al.getSequenceAt(firstSeq).gapMap(); if ((delMap != null && delMap.length > width) || (delMap == null && gapmap.length != width)) { - throw (new Exception( - MessageManager - .formatMessage( - "exception.number_of_residues_in_query_sequence_differ_from_prediction", - new String[] { - (delMap == null ? "" : MessageManager - .getString("label.mapped")), - al.getSequenceAt(firstSeq).getName(), - al.getSequenceAt(firstSeq) - .getSequenceAsString(), - Integer.valueOf(width).toString() }))); + throw (new Exception(MessageManager.formatMessage( + "exception.number_of_residues_in_query_sequence_differ_from_prediction", + new String[] + { (delMap == null ? "" + : MessageManager.getString("label.mapped")), + al.getSequenceAt(firstSeq).getName(), + al.getSequenceAt(firstSeq).getSequenceAsString(), + Integer.valueOf(width).toString() }))); } AlignmentAnnotation annot; @@@ -98,7 -95,8 +95,8 @@@ { if (id.startsWith("JNETSOL")) { - float amnt = (id.endsWith("25") ? 3f : id.endsWith("5") ? 6f : 9f); + float amnt = (id.endsWith("25") ? 3f + : id.endsWith("5") ? 6f : 9f); for (int spos = 0; spos < width; spos++) { int sposw = (delMap == null) ? gapmap[spos] @@@ -222,8 -220,7 +220,7 @@@ if (!firstsol) { // add the solvent accessibility - annot = new AlignmentAnnotation( - "Jnet Burial", + annot = new AlignmentAnnotation("Jnet Burial", "Prediction of Solvent Accessibility
levels are

  • 0 - Exposed
  • 3 - 25% or more S.A. accessible
  • 6 - 5% or more S.A. accessible
  • 9 - Buried (<5% exposed)
", sol, 0f, 9f, AlignmentAnnotation.BAR_GRAPH); @@@ -234,8 -231,8 +231,8 @@@ seqRef.addAlignmentAnnotation(annot); } al.addAnnotation(annot); - al.setAnnotationIndex(annot, al.getAlignmentAnnotation().length - - existingAnnotations - 1); + al.setAnnotationIndex(annot, + al.getAlignmentAnnotation().length - existingAnnotations - 1); } // Hashtable scores = prediction.getScores(); diff --combined src/jalview/io/MSFfile.java index b05acff,4dbf950..df2bed2 --- a/src/jalview/io/MSFfile.java +++ b/src/jalview/io/MSFfile.java @@@ -278,10 -278,10 +278,10 @@@ public class MSFfile extends AlignFil i++; } - Format maxLenpad = new Format("%" + (new String("" + max)).length() - + "d"); - Format maxChkpad = new Format("%" + (new String("1" + max)).length() - + "d"); + Format maxLenpad = new Format( + "%" + (new String("" + max)).length() + "d"); + Format maxChkpad = new Format( + "%" + (new String("1" + max)).length() + "d"); i = 0; int bigChecksum = 0; @@@ -294,7 -294,7 +294,7 @@@ } long maxNB = 0; - out.append(" MSF: " + s[0].getSequence().length + " Type: " + out.append(" MSF: " + s[0].getLength() + " Type: " + (is_NA ? "N" : "P") + " Check: " + (bigChecksum % 10000) + " .."); out.append(newline); @@@ -310,9 -310,9 +310,9 @@@ nameBlock[i] = new String(" Name: " + printId(s[i], jvSuffix) + " "); - idBlock[i] = new String("Len: " - + maxLenpad.form(s[i].getSequence().length) + " Check: " - + maxChkpad.form(checksums[i]) + " Weight: 1.00" + newline); + idBlock[i] = new String("Len: " + maxLenpad.form(s[i].getLength()) + + " Check: " + maxChkpad.form(checksums[i]) + + " Weight: 1.00" + newline); if (s[i].getName().length() > maxid) { @@@ -369,9 -369,8 +369,9 @@@ int start = (i * 50) + (k * 10); int end = start + 10; - if ((end < s[j].getSequence().length) - && (start < s[j].getSequence().length)) + int length = s[j].getLength(); + if ((end < length) + && (start < length)) { out.append(s[j].getSequence(start, end)); @@@ -386,7 -385,7 +386,7 @@@ } else { - if (start < s[j].getSequence().length) + if (start < length) { out.append(s[j].getSequenceAsString().substring(start)); out.append(newline); diff --combined src/jalview/io/PfamFile.java index 9f152cc,68aeb68..6b9dc3f --- a/src/jalview/io/PfamFile.java +++ b/src/jalview/io/PfamFile.java @@@ -117,8 -117,8 +117,8 @@@ public class PfamFile extends AlignFil if (noSeqs < 1) { - throw new IOException( - MessageManager.getString("exception.pfam_no_sequences_found")); + throw new IOException(MessageManager + .getString("exception.pfam_no_sequences_found")); } for (i = 0; i < headers.size(); i++) @@@ -131,8 -131,8 +131,8 @@@ } Sequence newSeq = parseId(headers.get(i).toString()); - newSeq.setSequence(seqhash.get(headers.get(i).toString()) - .toString()); + newSeq.setSequence( + seqhash.get(headers.get(i).toString()).toString()); seqs.addElement(newSeq); } else @@@ -157,7 -157,10 +157,7 @@@ { String tmp = printId(s[i], jvsuffix); - if (s[i].getSequence().length > max) - { - max = s[i].getSequence().length; - } + max = Math.max(max, s[i].getLength()); if (tmp.length() > maxid) { diff --combined src/jalview/io/PhylipFile.java index e1d82ee,2a961a2..539826f --- a/src/jalview/io/PhylipFile.java +++ b/src/jalview/io/PhylipFile.java @@@ -27,9 -27,9 +27,9 @@@ import java.io.IOException /** *

- * Parser and exporter for PHYLIP file format, as defined in the - * documentation. The parser imports PHYLIP files in both sequential and + * Parser and exporter for PHYLIP file format, as defined + * in + * the documentation. The parser imports PHYLIP files in both sequential and * interleaved format, and (currently) exports in interleaved format (using 60 * characters per matrix for the sequence). *

@@@ -38,7 -38,8 +38,8 @@@ * The following assumptions have been made for input *

    *
  • Sequences are expressed as letters, not real numbers with decimal points - * separated by blanks (which is a valid option according to the specification)
  • + * separated by blanks (which is a valid option according to the + * specification) *
* * The following assumptions have been made for output @@@ -112,8 -113,8 +113,8 @@@ public class PhylipFile extends AlignFi "First line must contain the number of specifies and number of characters"); } - int numberSpecies = Integer.parseInt(lineElements[0]), numberCharacters = Integer - .parseInt(lineElements[1]); + int numberSpecies = Integer.parseInt(lineElements[0]), + numberCharacters = Integer.parseInt(lineElements[1]); if (numberSpecies <= 0) { @@@ -144,8 -145,8 +145,8 @@@ } else { - sequenceElements[i] = parseId(validateName(potentialName - .substring(0, tabIndex))); + sequenceElements[i] = parseId( + validateName(potentialName.substring(0, tabIndex))); sequences[i] = new StringBuffer( removeWhitespace(line.substring(tabIndex))); } @@@ -222,8 -223,8 +223,8 @@@ { if (name.indexOf(c) > -1) { - throw new IOException("Species name contains illegal character " - + c); + throw new IOException( + "Species name contains illegal character " + c); } } return name; @@@ -247,7 -248,7 +248,7 @@@ sb.append(" "); // if there are no sequences, then define the number of characters as 0 sb.append( - (sqs.length > 0) ? Integer.toString(sqs[0].getSequence().length) +(sqs.length > 0) ? Integer.toString(sqs[0].getLength()) : "0") .append(newline); @@@ -279,13 -280,13 +280,13 @@@ // sequential has the entire sequence following the name if (sequential) { - sb.append(s.getSequence()); + sb.append(s.getSequenceAsString()); } else { // Jalview ensures all sequences are of same length so no need // to keep track of min/max length - sequenceLength = s.getSequence().length; + sequenceLength = s.getLength(); // interleaved breaks the sequence into chunks for // interleavedColumns characters sb.append(s.getSequence(0, @@@ -313,9 -314,8 +314,8 @@@ int start = i * numInterleavedColumns; for (SequenceI s : sqs) { - sb.append( - s.getSequence(start, Math.min(start - + numInterleavedColumns, sequenceLength))) + sb.append(s.getSequence(start, + Math.min(start + numInterleavedColumns, sequenceLength))) .append(newline); } } diff --combined src/jalview/io/PileUpfile.java index 4a0885c,7b5ce0d..f7f718b --- a/src/jalview/io/PileUpfile.java +++ b/src/jalview/io/PileUpfile.java @@@ -92,7 -92,7 +92,7 @@@ public class PileUpfile extends MSFfil i++; } - out.append(" MSF: " + s[0].getSequence().length + out.append(" MSF: " + s[0].getLength() + " Type: P Check: " + bigChecksum % 10000 + " .."); out.append(newline); out.append(newline); @@@ -103,8 -103,8 +103,8 @@@ { String seq = s[i].getSequenceAsString(); out.append(" Name: " + printId(s[i], jvsuffix) + " oo Len: " - + seq.length() - + " Check: " + checksums[i] + " Weight: 1.00"); + + seq.length() + " Check: " + checksums[i] + + " Weight: 1.00"); out.append(newline); if (seq.length() > max) @@@ -151,8 -151,8 +151,8 @@@ int start = (i * 50) + (k * 10); int end = start + 10; - if ((end < s[j].getSequence().length) - && (start < s[j].getSequence().length)) + int length = s[j].getLength(); + if ((end < length) && (start < length)) { out.append(s[j].getSequence(start, end)); @@@ -167,7 -167,7 +167,7 @@@ } else { - if (start < s[j].getSequence().length) + if (start < length) { out.append(s[j].getSequenceAsString().substring(start)); out.append(newline); diff --combined src/jalview/io/SequenceAnnotationReport.java index c3b076c,613c01f..f1ebcac --- a/src/jalview/io/SequenceAnnotationReport.java +++ b/src/jalview/io/SequenceAnnotationReport.java @@@ -57,8 -57,7 +57,8 @@@ public class SequenceAnnotationRepor final String linkImageURL; /* - * Comparator to order DBRefEntry by Source + accession id (case-insensitive) + * Comparator to order DBRefEntry by Source + accession id (case-insensitive), + * with 'Primary' sources placed before others */ private static Comparator comparator = new Comparator() { @@@ -78,14 -77,14 +78,14 @@@ { return 1; } - int comp = s1 == null ? -1 : (s2 == null ? 1 : s1 - .compareToIgnoreCase(s2)); + int comp = s1 == null ? -1 + : (s2 == null ? 1 : s1.compareToIgnoreCase(s2)); if (comp == 0) { String a1 = ref1.getAccessionId(); String a2 = ref2.getAccessionId(); - comp = a1 == null ? -1 : (a2 == null ? 1 : a1 - .compareToIgnoreCase(a2)); + comp = a1 == null ? -1 + : (a2 == null ? 1 : a1.compareToIgnoreCase(a2)); } return comp; } @@@ -151,8 -150,7 +151,7 @@@ sb.append("
"); } sb.append(feature.getType()).append(" ").append(feature.getBegin()) - .append(":") - .append(feature.getEnd()); + .append(":").append(feature.getEnd()); } } else @@@ -224,8 -222,8 +223,8 @@@ // check score should be shown if (!Float.isNaN(feature.getScore())) { - float[][] rng = (minmax == null) ? null : minmax.get(feature - .getType()); + float[][] rng = (minmax == null) ? null + : minmax.get(feature.getType()); if (rng != null && rng[0] != null && rng[0][0] != rng[0][1]) { sb.append(" Score=").append(String.valueOf(feature.getScore())); @@@ -269,21 -267,19 +268,19 @@@ { for (List urllink : createLinksFrom(null, urlstring)) { - sb.append("
" + sb.append("
" + (urllink.get(0).toLowerCase() - .equals(urllink.get(1).toLowerCase()) ? urllink - .get(0) : (urllink.get(0) + ":" + urllink - .get(1))) + .equals(urllink.get(1).toLowerCase()) + ? urllink.get(0) + : (urllink.get(0) + ":" + + urllink.get(1))) + "
"); } } catch (Exception x) { - System.err.println("problem when creating links from " - + urlstring); + System.err.println( + "problem when creating links from " + urlstring); x.printStackTrace(); } } @@@ -357,129 -353,108 +354,129 @@@ { ds = ds.getDatasetSequence(); } + + if (showDbRefs) + { + maxWidth = Math.max(maxWidth, appendDbRefs(sb, ds, summary)); + } + + /* + * add non-positional features if wanted + */ + if (showNpFeats) + { + for (SequenceFeature sf : sequence.getFeatures() + .getNonPositionalFeatures()) + { + int sz = -sb.length(); + appendFeature(sb, 0, minmax, sf); + sz += sb.length(); + maxWidth = Math.max(maxWidth, sz); + } + } + sb.append(""); + return maxWidth; + } + + /** + * A helper method that appends any DBRefs, returning the maximum line length + * added + * + * @param sb + * @param ds + * @param summary + * @return + */ + protected int appendDbRefs(final StringBuilder sb, SequenceI ds, + boolean summary) + { DBRefEntry[] dbrefs = ds.getDBRefs(); - if (showDbRefs && dbrefs != null) + if (dbrefs == null) + { + return 0; + } + + // note this sorts the refs held on the sequence! + Arrays.sort(dbrefs, comparator); + boolean ellipsis = false; + String source = null; + String lastSource = null; + int countForSource = 0; + int sourceCount = 0; + boolean moreSources = false; + int maxLineLength = 0; + int lineLength = 0; + + for (DBRefEntry ref : dbrefs) { - // note this sorts the refs held on the sequence! - Arrays.sort(dbrefs, comparator); - boolean ellipsis = false; - String source = null; - String lastSource = null; - int countForSource = 0; - int sourceCount = 0; - boolean moreSources = false; - int lineLength = 0; - - for (DBRefEntry ref : dbrefs) + source = ref.getSource(); + if (source == null) { - source = ref.getSource(); - if (source == null) - { - // shouldn't happen - continue; - } - boolean sourceChanged = !source.equals(lastSource); - if (sourceChanged) - { - lineLength = 0; - countForSource = 0; - sourceCount++; - } - if (sourceCount > MAX_SOURCES && summary) - { - ellipsis = true; - moreSources = true; - break; - } - lastSource = source; - countForSource++; - if (countForSource == 1 || !summary) - { - sb.append("
"); - } - if (countForSource <= MAX_REFS_PER_SOURCE || !summary) - { - String accessionId = ref.getAccessionId(); - lineLength += accessionId.length() + 1; - if (countForSource > 1 && summary) - { - sb.append(", ").append(accessionId); - lineLength++; - } - else - { - sb.append(source).append(" ").append(accessionId); - lineLength += source.length(); - } - maxWidth = Math.max(maxWidth, lineLength); - } - if (countForSource == MAX_REFS_PER_SOURCE && summary) - { - sb.append(COMMA).append(ELLIPSIS); - ellipsis = true; - } + // shouldn't happen + continue; } - if (moreSources) + boolean sourceChanged = !source.equals(lastSource); + if (sourceChanged) { - sb.append("
").append(ELLIPSIS).append(COMMA).append(source) - .append(COMMA).append(ELLIPSIS); + lineLength = 0; + countForSource = 0; + sourceCount++; } - if (ellipsis) + if (sourceCount > MAX_SOURCES && summary) { - sb.append("
("); - sb.append(MessageManager.getString("label.output_seq_details")); - sb.append(")"); + ellipsis = true; + moreSources = true; + break; } - } - - /* - * add non-positional features if wanted - */ - SequenceFeature[] features = sequence.getSequenceFeatures(); - if (showNpFeats && features != null) - { - for (int i = 0; i < features.length; i++) + lastSource = source; + countForSource++; + if (countForSource == 1 || !summary) + { + sb.append("
"); + } + if (countForSource <= MAX_REFS_PER_SOURCE || !summary) { - if (features[i].begin == 0 && features[i].end == 0) + String accessionId = ref.getAccessionId(); + lineLength += accessionId.length() + 1; + if (countForSource > 1 && summary) { - int sz = -sb.length(); - appendFeature(sb, 0, minmax, features[i]); - sz += sb.length(); - maxWidth = Math.max(maxWidth, sz); + sb.append(", ").append(accessionId); + lineLength++; } + else + { + sb.append(source).append(" ").append(accessionId); + lineLength += source.length(); + } + maxLineLength = Math.max(maxLineLength, lineLength); + } + if (countForSource == MAX_REFS_PER_SOURCE && summary) + { + sb.append(COMMA).append(ELLIPSIS); + ellipsis = true; } } - sb.append(""); - return maxWidth; + if (moreSources) + { + sb.append("
").append(source) + .append(COMMA).append(ELLIPSIS); + } + if (ellipsis) + { + sb.append("
("); + sb.append(MessageManager.getString("label.output_seq_details")); + sb.append(")"); + } + + return maxLineLength; } public void createTooltipAnnotationReport(final StringBuilder tip, SequenceI sequence, boolean showDbRefs, boolean showNpFeats, Map minmax) { - int maxWidth = createSequenceAnnotationReport(tip, sequence, - showDbRefs, showNpFeats, minmax, true); + int maxWidth = createSequenceAnnotationReport(tip, sequence, showDbRefs, + showNpFeats, minmax, true); if (maxWidth > 60) { diff --combined src/jalview/io/StockholmFile.java index 798a77e,e22ee0a..f5b5177 --- a/src/jalview/io/StockholmFile.java +++ b/src/jalview/io/StockholmFile.java @@@ -74,8 -74,6 +74,8 @@@ import fr.orsay.lri.varna.models.rna.RN */ public class StockholmFile extends AlignFile { + private static final String ANNOTATION = "annotation"; + private static final Regex OPEN_PAREN = new Regex("(<|\\[)", "("); private static final Regex CLOSE_PAREN = new Regex("(>|\\])", ")"); @@@ -165,8 -163,8 +165,8 @@@ for (int k = 0; k < rna.length(); k++) { - ann[k] = new Annotation(annot[k], "", Rna.getRNASecStrucState( - annot[k]).charAt(0), 0f); + ann[k] = new Annotation(annot[k], "", + Rna.getRNASecStrucState(annot[k]).charAt(0), 0f); } AlignmentAnnotation align = new AlignmentAnnotation("Sec. str.", @@@ -209,9 -207,8 +209,8 @@@ r = new Regex("# STOCKHOLM ([\\d\\.]+)"); if (!r.search(nextLine())) { - throw new IOException( - MessageManager - .getString("exception.stockholm_invalid_format")); + throw new IOException(MessageManager + .getString("exception.stockholm_invalid_format")); } else { @@@ -394,7 -391,7 +393,7 @@@ while (j.hasMoreElements()) { String desc = j.nextElement().toString(); - if ("annotations".equals(desc) && annotsAdded) + if (ANNOTATION.equals(desc) && annotsAdded) { // don't add features if we already added an annotation row continue; @@@ -414,7 -411,7 +413,7 @@@ int new_pos = posmap[k]; // look up nearest seqeunce // position to this column SequenceFeature feat = new SequenceFeature(type, desc, - new_pos, new_pos, 0f, null); + new_pos, new_pos, null); seqO.addSequenceFeature(feat); } @@@ -441,8 -438,8 +440,8 @@@ { // logger.error("Could not parse sequence line: " + line); throw new IOException(MessageManager.formatMessage( - "exception.couldnt_parse_sequence_line", - new String[] { line })); + "exception.couldnt_parse_sequence_line", new String[] + { line })); } String ns = seqs.get(x.stringMatched(1)); if (ns == null) @@@ -637,7 -634,7 +636,7 @@@ content = new Hashtable(); features.put(this.id2type(type), content); } - String ns = (String) content.get("annotation"); + String ns = (String) content.get(ANNOTATION); if (ns == null) { @@@ -645,7 -642,7 +644,7 @@@ } // finally, append the annotation line ns += seq; - content.put("annotation", ns); + content.put(ANNOTATION, ns); // // end of wrapped annotation block. // // Now a new row is created with the current set of data @@@ -673,8 -670,8 +672,8 @@@ // } else { - System.err - .println("Warning - couldn't parse sequence annotation row line:\n" + System.err.println( + "Warning - couldn't parse sequence annotation row line:\n" + line); // throw new IOException("Error parsing " + line); } @@@ -682,8 -679,8 +681,8 @@@ else { throw new IOException(MessageManager.formatMessage( - "exception.unknown_annotation_detected", new String[] { - annType, annContent })); + "exception.unknown_annotation_detected", new String[] + { annType, annContent })); } } } @@@ -796,8 -793,10 +795,10 @@@ { for (DBRefEntry d : dbrs) { - jalview.util.MapList mp = new jalview.util.MapList(new int[] { - seqO.getStart(), seqO.getEnd() }, new int[] { st, en }, 1, 1); + jalview.util.MapList mp = new jalview.util.MapList( + new int[] + { seqO.getStart(), seqO.getEnd() }, new int[] { st, en }, 1, + 1); jalview.datamodel.Mapping mping = new Mapping(mp); d.setMap(mping); } @@@ -817,8 -816,9 +818,9 @@@ String type = label; if (label.contains("_cons")) { - type = (label.indexOf("_cons") == label.length() - 5) ? label - .substring(0, label.length() - 5) : label; + type = (label.indexOf("_cons") == label.length() - 5) + ? label.substring(0, label.length() - 5) + : label; } boolean ss = false, posterior = false; type = id2type(type); @@@ -852,14 -852,14 +854,14 @@@ ann.secondaryStructure = ResidueProperties.getDssp3state(pos) .charAt(0); - if (ann.secondaryStructure == pos.charAt(0)) - { - ann.displayCharacter = ""; // null; // " "; - } - else - { - ann.displayCharacter = " " + ann.displayCharacter; - } + if (ann.secondaryStructure == pos.charAt(0)) + { + ann.displayCharacter = ""; // null; // " "; + } + else + { + ann.displayCharacter = " " + ann.displayCharacter; + } } } @@@ -930,7 -930,10 +932,7 @@@ while ((in < s.length) && (s[in] != null)) { String tmp = printId(s[in], jvSuffix); - if (s[in].getSequence().length > max) - { - max = s[in].getSequence().length; - } + max = Math.max(max, s[in].getLength()); if (tmp.length() > maxid) { @@@ -979,8 -982,8 +981,8 @@@ { Object idd = en.nextElement(); String type = (String) dataRef.remove(idd); - out.append(new Format("%-" + (maxid - 2) + "s").form("#=GS " - + idd.toString() + " ")); + out.append(new Format("%-" + (maxid - 2) + "s") + .form("#=GS " + idd.toString() + " ")); if (type.contains("PFAM") || type.contains("RFAM")) { @@@ -1020,8 -1023,8 +1022,8 @@@ } // out.append("#=GR "); - out.append(new Format("%-" + maxid + "s").form("#=GR " - + printId(s[i], jvSuffix) + " " + key + " ")); + out.append(new Format("%-" + maxid + "s").form( + "#=GR " + printId(s[i], jvSuffix) + " " + key + " ")); ann = alAnot[j].annotations; String seq = ""; for (int k = 0; k < ann.length; k++) @@@ -1076,8 -1079,8 +1078,8 @@@ } label = label.replace(" ", "_"); - out.append(new Format("%-" + maxid + "s").form("#=GC " + label - + " ")); + out.append( + new Format("%-" + maxid + "s").form("#=GC " + label + " ")); boolean isrna = aa.isValidStruc(); for (int j = 0; j < aa.annotations.length; j++) { @@@ -1109,8 -1112,10 +1111,10 @@@ { char seq = ' '; Annotation annot = ann[k]; - String ch = (annot == null) ? ((sequenceI == null) ? "-" : Character - .toString(sequenceI.getCharAt(k))) : annot.displayCharacter; + String ch = (annot == null) + ? ((sequenceI == null) ? "-" + : Character.toString(sequenceI.getCharAt(k))) + : annot.displayCharacter; if (key != null && key.equals("SS")) { if (annot == null) @@@ -1187,8 -1192,8 +1191,8 @@@ { return (String) typeIds.get(id); } - System.err.println("Warning : Unknown Stockholm annotation type code " - + id); + System.err.println( + "Warning : Unknown Stockholm annotation type code " + id); return id; } @@@ -1209,8 -1214,8 +1213,8 @@@ { return key; } - System.err.println("Warning : Unknown Stockholm annotation type: " - + type); + System.err.println( + "Warning : Unknown Stockholm annotation type: " + type); return key; } diff --combined src/jalview/io/StructureFile.java index 7628115,40bb8be..3025907 --- a/src/jalview/io/StructureFile.java +++ b/src/jalview/io/StructureFile.java @@@ -191,11 -191,13 +191,13 @@@ public abstract class StructureFile ext { // TODO: use the PDB ID of the structure if one is available, to save // bandwidth and avoid uploading the whole structure to the service - Object annotate3d = cl.getConstructor(new Class[] {}).newInstance( - new Object[] {}); - AlignmentI al = ((AlignmentI) cl.getMethod("getRNAMLFor", - new Class[] { FileParse.class }).invoke(annotate3d, - new Object[] { new FileParse(getDataName(), dataSourceType) })); + Object annotate3d = cl.getConstructor(new Class[] {}) + .newInstance(new Object[] {}); + AlignmentI al = ((AlignmentI) cl + .getMethod("getRNAMLFor", new Class[] + { FileParse.class }) + .invoke(annotate3d, new Object[] + { new FileParse(getDataName(), dataSourceType) })); for (SequenceI sq : al.getSequences()) { if (sq.getDatasetSequence() != null) @@@ -222,8 -224,8 +224,8 @@@ } @SuppressWarnings("unchecked") - protected void replaceAndUpdateChains(List prot, - AlignmentI al, String pep, boolean b) + protected void replaceAndUpdateChains(List prot, AlignmentI al, + String pep, boolean b) { List> replaced = AlignSeq .replaceMatchingSeqsWith(seqs, annotations, prot, al, pep, @@@ -288,8 -290,8 +290,8 @@@ processWithJmolParser(proteinSequences); } catch (Exception x) { - System.err - .println("Exceptions from Jmol when processing data in pdb file"); + System.err.println( + "Exceptions from Jmol when processing data in pdb file"); x.printStackTrace(); } } @@@ -304,8 -306,11 +306,11 @@@ Class cl = Class.forName("jalview.ext.jmol.JmolParser"); if (cl != null) { - final Constructor constructor = cl.getConstructor(new Class[] {FileParse.class }); - final Object[] args = new Object[] { new FileParse(getDataName(), dataSourceType) }; + final Constructor constructor = cl + .getConstructor(new Class[] + { FileParse.class }); + final Object[] args = new Object[] { + new FileParse(getDataName(), dataSourceType) }; StructureImportSettings.setShowSeqFeatures(false); StructureImportSettings.setVisibleChainAnnotation(false); @@@ -314,8 -319,8 +319,8 @@@ StructureImportSettings .setExternalSecondaryStructure(externalSecondaryStructure); Object jmf = constructor.newInstance(args); - AlignmentI al = new Alignment((SequenceI[]) cl.getMethod( - "getSeqsAsArray", new Class[] {}).invoke(jmf)); + AlignmentI al = new Alignment((SequenceI[]) cl + .getMethod("getSeqsAsArray", new Class[] {}).invoke(jmf)); cl.getMethod("addAnnotations", new Class[] { AlignmentI.class }) .invoke(jmf, al); for (SequenceI sq : al.getSequences()) @@@ -392,10 -397,8 +397,10 @@@ public static boolean isRNA(SequenceI seq) { - for (char c : seq.getSequence()) + int length = seq.getLength(); + for (int i = 0; i < length; i++) { + char c = seq.getCharAt(i); if ((c != 'A') && (c != 'C') && (c != 'G') && (c != 'U')) { return false; @@@ -418,7 -421,8 +423,8 @@@ { dataName = dataName.substring(p + 1); } - if(dataName.indexOf(".") > -1){ + if (dataName.indexOf(".") > -1) + { dataName = dataName.substring(0, dataName.lastIndexOf(".")); } return dataName; diff --combined src/jalview/io/gff/ExonerateHelper.java index 873fd27,91add1a..da0c245 --- a/src/jalview/io/gff/ExonerateHelper.java +++ b/src/jalview/io/gff/ExonerateHelper.java @@@ -165,7 -165,8 +165,8 @@@ public class ExonerateHelper extends Gf SequenceI mapFromSequence = seq; SequenceI mapToSequence = mappedSequence; if ((type == MappingType.NucleotideToPeptide && featureIsOnTarget) - || (type == MappingType.PeptideToNucleotide && !featureIsOnTarget)) + || (type == MappingType.PeptideToNucleotide + && !featureIsOnTarget)) { mapFromSequence = mappedSequence; mapToSequence = seq; @@@ -267,8 -268,8 +268,8 @@@ { fromStart = alignToStart; toStart = alignFromStart; - toEnd = forwardStrand ? toStart + alignCount - 1 : toStart - - (alignCount - 1); + toEnd = forwardStrand ? toStart + alignCount - 1 + : toStart - (alignCount - 1); int toLength = Math.abs(toEnd - toStart) + 1; int fromLength = toLength * type.getFromRatio() / type.getToRatio(); fromEnd = fromStart + fromLength - 1; @@@ -352,16 -353,12 +353,16 @@@ return false; } + /** + * An override to set feature group to "exonerate" instead of the default GFF + * source value (column 2) + */ @Override protected SequenceFeature buildSequenceFeature(String[] gff, Map> set) { - SequenceFeature sf = super.buildSequenceFeature(gff, set); - sf.setFeatureGroup("exonerate"); + SequenceFeature sf = super.buildSequenceFeature(gff, TYPE_COL, + "exonerate", set); return sf; } diff --combined src/jalview/io/gff/Gff3Helper.java index 28941f5,594040a..c7e1d7a --- a/src/jalview/io/gff/Gff3Helper.java +++ b/src/jalview/io/gff/Gff3Helper.java @@@ -152,8 -152,8 +152,8 @@@ public class Gff3Helper extends GffHelp */ if ("-".equals(strand)) { - System.err - .println("Skipping mapping from reverse complement as not yet supported"); + System.err.println( + "Skipping mapping from reverse complement as not yet supported"); return null; } @@@ -244,7 -244,8 +244,8 @@@ * @return */ @SuppressWarnings("unused") - protected String findTargetId(String target, Map> set) + protected String findTargetId(String target, + Map> set) { return target; } @@@ -275,8 -276,8 +276,8 @@@ * @throws IOException */ protected SequenceFeature processProteinMatch( - Map> set, SequenceI seq, - String[] gffColumns, AlignmentI align, List newseqs, + Map> set, SequenceI seq, String[] gffColumns, + AlignmentI align, List newseqs, boolean relaxedIdMatching) { // This is currently tailored to InterProScan GFF output: @@@ -310,9 -311,10 +311,9 @@@ * give the mapped sequence a copy of the sequence feature, with * start/end range adjusted */ - SequenceFeature sf2 = new SequenceFeature(sf); - sf2.setBegin(1); int sequenceFeatureLength = 1 + sf.getEnd() - sf.getBegin(); - sf2.setEnd(sequenceFeatureLength); + SequenceFeature sf2 = new SequenceFeature(sf, 1, + sequenceFeatureLength, sf.getFeatureGroup(), sf.getScore()); mappedSequence.addSequenceFeature(sf2); /* @@@ -320,8 -322,8 +321,8 @@@ * renamed with its qualified accession id; renaming has to wait until * all sequence reference resolution is complete */ - String accessionId = StringUtils.listToDelimitedString( - set.get(NAME), ","); + String accessionId = StringUtils + .listToDelimitedString(set.get(NAME), ","); if (accessionId.length() > 0) { String database = sf.getType(); // TODO InterProScan only?? @@@ -361,11 -363,9 +362,11 @@@ */ @Override protected SequenceFeature buildSequenceFeature(String[] gff, + int typeColumn, String group, Map> attributes) { - SequenceFeature sf = super.buildSequenceFeature(gff, attributes); + SequenceFeature sf = super.buildSequenceFeature(gff, typeColumn, group, + attributes); String desc = getDescription(sf, attributes); if (desc != null) { diff --combined src/jalview/io/gff/GffHelperBase.java index 41f141b,301aaec..1d4d3ac --- a/src/jalview/io/gff/GffHelperBase.java +++ b/src/jalview/io/gff/GffHelperBase.java @@@ -150,8 -150,8 +150,8 @@@ public abstract class GffHelperBase imp * restrict from range to make them match up * it's kind of arbitrary which end we truncate - here it is the end */ - System.err.print("Truncating mapping from " + Arrays.toString(from) - + " to "); + System.err.print( + "Truncating mapping from " + Arrays.toString(from) + " to "); if (from[1] > from[0]) { from[1] -= fromOverlap / toRatio; @@@ -169,8 -169,8 +169,8 @@@ /* * restrict to range to make them match up */ - System.err.print("Truncating mapping to " + Arrays.toString(to) - + " to "); + System.err.print( + "Truncating mapping to " + Arrays.toString(to) + " to "); if (to[1] > to[0]) { to[1] -= fromOverlap / fromRatio; @@@ -261,7 -261,8 +261,8 @@@ /** * Parses the input line to a map of name / value(s) pairs. For example the * line
- * Notes=Fe-S;Method=manual curation, prediction; source = Pfam; Notes = Metal
+ * Notes=Fe-S;Method=manual curation, prediction; source = Pfam; Notes = Metal + *
* if parsed with delimiter=";" and separators {' ', '='}
* would return a map with { Notes={Fe=S, Metal}, Method={manual curation, * prediction}, source={Pfam}}
@@@ -337,19 -338,6 +338,19 @@@ protected SequenceFeature buildSequenceFeature(String[] gff, Map> attributes) { + return buildSequenceFeature(gff, TYPE_COL, gff[SOURCE_COL], attributes); + } + + /** + * @param gff + * @param typeColumn + * @param group + * @param attributes + * @return + */ + protected SequenceFeature buildSequenceFeature(String[] gff, + int typeColumn, String group, Map> attributes) + { try { int start = Integer.parseInt(gff[START_COL]); @@@ -368,8 -356,8 +369,8 @@@ // e.g. '.' - leave as zero } - SequenceFeature sf = new SequenceFeature(gff[TYPE_COL], - gff[SOURCE_COL], start, end, score, gff[SOURCE_COL]); + SequenceFeature sf = new SequenceFeature(gff[typeColumn], + gff[SOURCE_COL], start, end, score, group); sf.setStrand(gff[STRAND_COL]); @@@ -388,8 -376,8 +389,8 @@@ */ for (Entry> attr : attributes.entrySet()) { - String values = StringUtils.listToDelimitedString( - attr.getValue(), ","); + String values = StringUtils.listToDelimitedString(attr.getValue(), + ","); sf.setValue(attr.getKey(), values); if (NOTE.equals(attr.getKey())) { diff --combined src/jalview/io/gff/InterProScanHelper.java index 0aa3b74,c05593f..948cdd2 --- a/src/jalview/io/gff/InterProScanHelper.java +++ b/src/jalview/io/gff/InterProScanHelper.java @@@ -73,19 -73,13 +73,19 @@@ public class InterProScanHelper extend } /** - * - */ + * An override that + *
    + *
  • uses Source (column 2) as feature type instead of the default column 3
  • + *
  • sets "InterProScan" as the feature group
  • + *
  • extracts "signature_desc" attribute as the feature description
  • + *
+ */ @Override protected SequenceFeature buildSequenceFeature(String[] gff, Map> attributes) { - SequenceFeature sf = super.buildSequenceFeature(gff, attributes); + SequenceFeature sf = super.buildSequenceFeature(gff, SOURCE_COL, + INTER_PRO_SCAN, attributes); /* * signature_desc is a more informative source of description @@@ -97,6 -91,13 +97,6 @@@ sf.setDescription(description); } - /* - * Set sequence feature group as 'InterProScan', and type as the source - * database for this match (e.g. 'Pfam') - */ - sf.setType(gff[SOURCE_COL]); - sf.setFeatureGroup(INTER_PRO_SCAN); - return sf; } @@@ -111,8 -112,8 +111,8 @@@ SequenceOntologyI so = SequenceOntologyFactory.getInstance(); String type = columns[TYPE_COL]; if (so.isA(type, SequenceOntologyI.PROTEIN_MATCH) - || (".".equals(columns[SOURCE_COL]) && so.isA(type, - SequenceOntologyI.POLYPEPTIDE))) + || (".".equals(columns[SOURCE_COL]) + && so.isA(type, SequenceOntologyI.POLYPEPTIDE))) { return true; } @@@ -124,7 -125,8 +124,8 @@@ * GFF field 'ID' rather than the usual 'Target' :-O */ @Override - protected String findTargetId(String target, Map> set) + protected String findTargetId(String target, + Map> set) { List ids = set.get(ID); if (ids == null || ids.size() != 1) diff --combined src/jalview/io/vamsas/Datasetsequence.java index e1340e2,462f5af..a399c04 --- a/src/jalview/io/vamsas/Datasetsequence.java +++ b/src/jalview/io/vamsas/Datasetsequence.java @@@ -21,12 -21,9 +21,12 @@@ package jalview.io.vamsas; import jalview.datamodel.DBRefEntry; +import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; import jalview.io.VamsasAppDatastore; +import java.util.List; + import uk.ac.vamsas.objects.core.DataSet; import uk.ac.vamsas.objects.core.DbRef; import uk.ac.vamsas.objects.core.Sequence; @@@ -48,12 -45,12 +48,12 @@@ public class Datasetsequence extends Da // private AlignmentI jvdset; public Datasetsequence(VamsasAppDatastore vamsasAppDatastore, -- SequenceI sq, String dict, DataSet dataset) ++ SequenceI sq, String theDict, DataSet theDataset) { super(vamsasAppDatastore, sq, uk.ac.vamsas.objects.core.Sequence.class); -- this.dataset = dataset; ++ this.dataset = theDataset; // this.jvdset = jvdset; -- this.dict = dict; ++ this.dict = theDict; doSync(); } @@@ -64,7 -61,6 +64,7 @@@ doJvUpdate(); } + @Override public void addFromDocument() { Sequence vseq = (Sequence) vobj; @@@ -77,14 -73,14 +77,15 @@@ modified = true; } + @Override public void updateFromDoc() { Sequence sq = (Sequence) vobj; SequenceI sequence = (SequenceI) jvobj; if (!sequence.getSequenceAsString().equals(sq.getSequence())) { - log.warn("Potential Client Error ! - mismatch of dataset sequence: and jalview internal dataset sequence."); + log.warn( + "Potential Client Error ! - mismatch of dataset sequence: and jalview internal dataset sequence."); } else { @@@ -133,21 -129,25 +134,21 @@@ */ private boolean updateSqFeatures() { - boolean modified = false; + boolean changed = false; SequenceI sq = (SequenceI) jvobj; // add or update any new features/references on dataset sequence - if (sq.getSequenceFeatures() != null) + List sfs = sq.getSequenceFeatures(); + for (SequenceFeature sf : sfs) { - int sfSize = sq.getSequenceFeatures().length; - - for (int sf = 0; sf < sfSize; sf++) - { - modified |= new jalview.io.vamsas.Sequencefeature(datastore, - (jalview.datamodel.SequenceFeature) sq - .getSequenceFeatures()[sf], - dataset, (Sequence) vobj).docWasUpdated(); - } + changed |= new jalview.io.vamsas.Sequencefeature(datastore, sf, + dataset, (Sequence) vobj).docWasUpdated(); } - return modified; + + return changed; } + @Override public void addToDocument() { SequenceI sq = (SequenceI) jvobj; @@@ -184,7 -184,7 +185,7 @@@ for (int db = 0; db < entries.length; db++) { modifiedthedoc |= new jalview.io.vamsas.Dbref(datastore, - // dbentry = + // dbentry = entries[db], sq, (Sequence) vobj, dataset).docWasUpdated(); } @@@ -211,24 -211,23 +212,25 @@@ for (int db = 0; db < entries.length; db++) { modifiedtheseq |= new jalview.io.vamsas.Dbref(datastore, - // dbentry = + // dbentry = entries[db], vsq, sq).jvWasUpdated(); } } return modifiedtheseq; } + @Override public void conflict() { - log.warn("Conflict in dataset sequence update to document. Overwriting document"); + log.warn( + "Conflict in dataset sequence update to document. Overwriting document"); // TODO: could try to import from document data to jalview first. and then updateToDoc(); } boolean modified = false; + @Override public void updateToDoc() { SequenceI sq = (SequenceI) jvobj; diff --combined src/jalview/io/vamsas/Sequencefeature.java index 363f6f1,31d64f5..74f73d4 --- a/src/jalview/io/vamsas/Sequencefeature.java +++ b/src/jalview/io/vamsas/Sequencefeature.java @@@ -97,10 -97,8 +97,8 @@@ public class Sequencefeature extends Ra DataSetAnnotations dsa = (DataSetAnnotations) vobj; if (dsa.getSeqRefCount() != 1) { - Cache.log - .warn("Not binding " - + dsa.getVorbaId() - + " to Sequence Feature - has multiple dataset sequence references."); + Cache.log.warn("Not binding " + dsa.getVorbaId() + + " to Sequence Feature - has multiple dataset sequence references."); return; } jalview.datamodel.SequenceFeature sf = (jalview.datamodel.SequenceFeature) jvobj; @@@ -130,8 -128,8 +128,8 @@@ if (dsa.getSeqRefCount() != 1) { replaceJvObjMapping(feature, null); - Cache.log - .warn("Binding of annotation to jalview feature has changed. Removing binding and recreating."); + Cache.log.warn( + "Binding of annotation to jalview feature has changed. Removing binding and recreating."); doSync(); // re-verify bindings. } else @@@ -158,10 -156,8 +156,8 @@@ { // conflicting update from document - we cannot map this feature anymore. replaceJvObjMapping(feature, null); - Cache.log - .warn("annotation (" - + dsa.getVorbaId() - + " bound to jalview feature cannot be mapped. Removing binding, deleting feature, and deleting feature."); + Cache.log.warn("annotation (" + dsa.getVorbaId() + + " bound to jalview feature cannot be mapped. Removing binding, deleting feature, and deleting feature."); // - consider deleting the feature ? dsSeq.deleteFeature(feature); // doSync(); @@@ -202,8 -198,8 +198,8 @@@ vSeg.setInclusive(true); if (dsa.getSegCount() > 1) { - Cache.log - .debug("About to destroy complex annotation in vamsas document mapped to sequence feature (" + Cache.log.debug( + "About to destroy complex annotation in vamsas document mapped to sequence feature (" + dsa.getVorbaId() + ")"); } dsa.setSeg(new Seg[] { vSeg }); @@@ -256,7 -252,8 +252,8 @@@ else if (vlu instanceof Integer) { valid = true; - nprop.setType(uk.ac.vamsas.objects.utils.Properties.INTEGERTYPE); + nprop.setType( + uk.ac.vamsas.objects.utils.Properties.INTEGERTYPE); } else if (vlu instanceof Float) { @@@ -284,39 -281,9 +281,39 @@@ private SequenceFeature getJalviewSeqFeature(RangeAnnotation dseta) { int[] se = getBounds(dseta); - SequenceFeature sf = new jalview.datamodel.SequenceFeature( - dseta.getType(), dseta.getDescription(), dseta.getStatus(), - se[0], se[1], dseta.getGroup()); + + /* + * try to identify feature score + */ + boolean scoreFound = false; + float theScore = 0f; + String featureType = dseta.getType(); + if (dseta.getScoreCount() > 0) + { + Enumeration scr = dseta.enumerateScore(); + while (scr.hasMoreElements()) + { + Score score = (Score) scr.nextElement(); + if (score.getName().equals(featureType)) + { + theScore = score.getContent(); + scoreFound = true; + } + } + } + + SequenceFeature sf = null; + if (scoreFound) + { + sf = new SequenceFeature(featureType, dseta.getDescription(), se[0], + se[1], theScore, dseta.getGroup()); + } + else + { + sf = new SequenceFeature(featureType, dseta.getDescription(), se[0], + se[1], dseta.getGroup()); + } + sf.setStatus(dseta.getStatus()); if (dseta.getLinkCount() > 0) { Link[] links = dseta.getLink(); @@@ -332,7 -299,11 +329,7 @@@ while (scr.hasMoreElements()) { Score score = (Score) scr.nextElement(); - if (score.getName().equals(sf.getType())) - { - sf.setScore(score.getContent()); - } - else + if (!score.getName().equals(sf.getType())) { sf.setValue(score.getName(), "" + score.getContent()); } diff --combined src/jalview/renderer/seqfeatures/FeatureColourFinder.java index ba63834,00cbd2c..cfe2735 --- a/src/jalview/renderer/seqfeatures/FeatureColourFinder.java +++ b/src/jalview/renderer/seqfeatures/FeatureColourFinder.java @@@ -1,3 -1,23 +1,23 @@@ + /* + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors + * + * This file is part of Jalview. + * + * Jalview is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * Jalview is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. + */ package jalview.renderer.seqfeatures; import jalview.api.FeatureRenderer; @@@ -55,7 -75,7 +75,7 @@@ public class FeatureColourFinde * @param defaultColour * @param seq * @param column - * alignment column position (base zero) + * alignment column position (0..) * @return */ public Color findFeatureColour(Color defaultColour, SequenceI seq, @@@ -81,7 -101,7 +101,7 @@@ } } - Color c = featureRenderer.findFeatureColour(seq, column, g); + Color c = featureRenderer.findFeatureColour(seq, column + 1, g); if (c == null) { return defaultColour; diff --combined src/jalview/renderer/seqfeatures/FeatureRenderer.java index 8feee1f,9f57510..e81e519 --- a/src/jalview/renderer/seqfeatures/FeatureRenderer.java +++ b/src/jalview/renderer/seqfeatures/FeatureRenderer.java @@@ -21,8 -21,6 +21,8 @@@ package jalview.renderer.seqfeatures; import jalview.api.AlignViewportI; +import jalview.api.FeatureColourI; +import jalview.datamodel.Range; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; import jalview.util.Comparison; @@@ -33,7 -31,6 +33,7 @@@ import java.awt.Color import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; +import java.util.List; public class FeatureRenderer extends FeatureRendererModel { @@@ -101,8 -98,7 +101,7 @@@ g.setColor(featureColour); - g.fillRect((i - start) * charWidth, y1, charWidth, - charHeight); + g.fillRect((i - start) * charWidth, y1, charWidth, charHeight); if (colourOnly || !validCharWidth) { @@@ -111,8 -107,8 +110,8 @@@ g.setColor(Color.white); int charOffset = (charWidth - fm.charWidth(s)) / 2; - g.drawString(String.valueOf(s), charOffset - + (charWidth * (i - start)), pady); + g.drawString(String.valueOf(s), + charOffset + (charWidth * (i - start)), pady); } return true; } @@@ -200,8 -196,8 +199,8 @@@ g.setColor(Color.black); int charOffset = (charWidth - fm.charWidth(s)) / 2; - g.drawString(String.valueOf(s), charOffset - + (charWidth * (i - start)), pady); + g.drawString(String.valueOf(s), + charOffset + (charWidth * (i - start)), pady); } return true; } @@@ -217,11 -213,18 +216,11 @@@ return null; } - SequenceFeature[] sequenceFeatures = seq.getSequenceFeatures(); - - if (sequenceFeatures == null || sequenceFeatures.length == 0) - { - return null; - } - if (Comparison.isGap(seq.getCharAt(column))) { /* * returning null allows the colour scheme to provide gap colour - * - normally white, but can be customised otherwise + * - normally white, but can be customised */ return null; } @@@ -232,7 -235,7 +231,7 @@@ /* * simple case - just find the topmost rendered visible feature colour */ - renderedColour = findFeatureColour(seq, seq.findPosition(column)); + renderedColour = findFeatureColour(seq, column); } else { @@@ -269,11 -272,8 +268,11 @@@ final SequenceI seq, int start, int end, int y1, boolean colourOnly) { - SequenceFeature[] sequenceFeatures = seq.getSequenceFeatures(); - if (sequenceFeatures == null || sequenceFeatures.length == 0) + /* + * if columns are all gapped, or sequence has no features, nothing to do + */ + Range visiblePositions = seq.findPositions(start+1, end+1); + if (visiblePositions == null || !seq.getFeatures().hasFeatures()) { return null; } @@@ -287,6 -287,10 +286,6 @@@ transparency)); } - int startPos = seq.findPosition(start); - int endPos = seq.findPosition(end); - - int sfSize = sequenceFeatures.length; Color drawnColour = null; /* @@@ -300,55 -304,54 +299,55 @@@ continue; } - // loop through all features in sequence to find - // current feature to render - for (int sfindex = 0; sfindex < sfSize; sfindex++) + FeatureColourI fc = getFeatureStyle(type); + List overlaps = seq.getFeatures().findFeatures( + visiblePositions.getBegin(), visiblePositions.getEnd(), type); + + filterFeaturesForDisplay(overlaps, fc); + + for (SequenceFeature sf : overlaps) { - final SequenceFeature sequenceFeature = sequenceFeatures[sfindex]; - if (!sequenceFeature.type.equals(type)) + Color featureColour = fc.getColor(sf); + if (featureColour == null) { + // score feature outwith threshold for colouring continue; } /* - * a feature type may be flagged as shown but the group - * an instance of it belongs to may be hidden + * if feature starts/ends outside the visible range, + * restrict to visible positions (or if a contact feature, + * to a single position) */ - if (featureGroupNotShown(sequenceFeature)) + int visibleStart = sf.getBegin(); + if (visibleStart < visiblePositions.getBegin()) { - continue; + visibleStart = sf.isContactFeature() ? sf.getEnd() + : visiblePositions.getBegin(); } - - /* - * check feature overlaps the target range - * TODO: efficient retrieval of features overlapping a range - */ - if (sequenceFeature.getBegin() > endPos - || sequenceFeature.getEnd() < startPos) + int visibleEnd = sf.getEnd(); + if (visibleEnd > visiblePositions.getEnd()) { - continue; + visibleEnd = sf.isContactFeature() ? sf.getBegin() + : visiblePositions.getEnd(); } - Color featureColour = getColour(sequenceFeature); - if (featureColour == null) - { - // score feature outwith threshold for colouring - continue; - } + int featureStartCol = seq.findIndex(visibleStart); + int featureEndCol = sf.begin == sf.end ? featureStartCol : seq + .findIndex(visibleEnd); + + // Color featureColour = getColour(sequenceFeature); - boolean isContactFeature = sequenceFeature.isContactFeature(); + boolean isContactFeature = sf.isContactFeature(); if (isContactFeature) { - boolean drawn = renderFeature(g, seq, - seq.findIndex(sequenceFeature.begin) - 1, - seq.findIndex(sequenceFeature.begin) - 1, featureColour, - start, end, y1, colourOnly); - drawn |= renderFeature(g, seq, - seq.findIndex(sequenceFeature.end) - 1, - seq.findIndex(sequenceFeature.end) - 1, featureColour, - start, end, y1, colourOnly); + boolean drawn = renderFeature(g, seq, featureStartCol - 1, + featureStartCol - 1, featureColour, start, end, y1, + colourOnly); + drawn |= renderFeature(g, seq, featureEndCol - 1, + featureEndCol - 1, featureColour, start, end, y1, + colourOnly); if (drawn) { drawnColour = featureColour; @@@ -356,10 -359,6 +355,10 @@@ } else { + /* + * showing feature score by height of colour + * is not implemented as a selectable option + * if (av.isShowSequenceFeaturesHeight() && !Float.isNaN(sequenceFeature.score)) { @@@ -375,16 -374,15 +374,16 @@@ } else { + */ boolean drawn = renderFeature(g, seq, - seq.findIndex(sequenceFeature.begin) - 1, - seq.findIndex(sequenceFeature.end) - 1, featureColour, + featureStartCol - 1, + featureEndCol - 1, featureColour, start, end, y1, colourOnly); if (drawn) { drawnColour = featureColour; } - } + /*}*/ } } } @@@ -402,6 -400,23 +401,27 @@@ } /** ++<<<<<<< HEAD ++======= + * Answers true if the feature belongs to a feature group which is not + * currently displayed, else false + * + * @param sequenceFeature + * @return + */ ++ @Override + protected boolean featureGroupNotShown( + final SequenceFeature sequenceFeature) + { + return featureGroups != null && sequenceFeature.featureGroup != null + && sequenceFeature.featureGroup.length() != 0 + && featureGroups.containsKey(sequenceFeature.featureGroup) + && !featureGroups.get(sequenceFeature.featureGroup) + .booleanValue(); + } + + /** ++>>>>>>> refs/heads/develop * Called when alignment in associated view has new/modified features to * discover and display. * @@@ -413,23 -428,23 +433,23 @@@ } /** - * Returns the sequence feature colour rendered at the given sequence - * position, or null if none found. The feature of highest render order (i.e. - * on top) is found, subject to both feature type and feature group being - * visible, and its colour returned. + * Returns the sequence feature colour rendered at the given column position, + * or null if none found. The feature of highest render order (i.e. on top) is + * found, subject to both feature type and feature group being visible, and + * its colour returned. This method is suitable when no feature transparency + * applied (only the topmost visible feature colour is rendered). + *

+ * Note this method does not check for a gap in the column so would return the + * colour for features enclosing a gapped column. Check for gap before calling + * if different behaviour is wanted. * * @param seq - * @param pos + * @param column + * (1..) * @return */ - Color findFeatureColour(SequenceI seq, int pos) + Color findFeatureColour(SequenceI seq, int column) { - SequenceFeature[] sequenceFeatures = seq.getSequenceFeatures(); - if (sequenceFeatures == null || sequenceFeatures.length == 0) - { - return null; - } - /* * check for new feature added while processing */ @@@ -439,7 -454,8 +459,8 @@@ * inspect features in reverse renderOrder (the last in the array is * displayed on top) until we find one that is rendered at the position */ - for (int renderIndex = renderOrder.length - 1; renderIndex >= 0; renderIndex--) + for (int renderIndex = renderOrder.length + - 1; renderIndex >= 0; renderIndex--) { String type = renderOrder[renderIndex]; if (!showFeatureOfType(type)) @@@ -447,21 -463,37 +468,21 @@@ continue; } - for (int sfindex = 0; sfindex < sequenceFeatures.length; sfindex++) + List overlaps = seq.findFeatures(column, column, + type); + for (SequenceFeature sequenceFeature : overlaps) { - SequenceFeature sequenceFeature = sequenceFeatures[sfindex]; - if (!sequenceFeature.type.equals(type)) - { - continue; - } - - if (featureGroupNotShown(sequenceFeature)) + if (!featureGroupNotShown(sequenceFeature)) { - continue; - } - - /* - * check the column position is within the feature range - * (or is one of the two contact positions for a contact feature) - */ - boolean featureIsAtPosition = sequenceFeature.begin <= pos - && sequenceFeature.end >= pos; - if (sequenceFeature.isContactFeature()) - { - featureIsAtPosition = sequenceFeature.begin == pos - || sequenceFeature.end == pos; - } - if (featureIsAtPosition) - { - return getColour(sequenceFeature); + Color col = getColour(sequenceFeature); + if (col != null) + { + return col; + } } } } - + /* * no displayed feature found at position */ diff --combined src/jalview/schemes/ClustalxColourScheme.java index 9df7ab8,ccbad44..ec13343 --- a/src/jalview/schemes/ClustalxColourScheme.java +++ b/src/jalview/schemes/ClustalxColourScheme.java @@@ -43,8 -43,8 +43,8 @@@ public class ClustalxColourScheme exten { RED(0.9f, 0.2f, 0.1f), BLUE(0.5f, 0.7f, 0.9f), GREEN(0.1f, 0.8f, 0.1f), ORANGE(0.9f, 0.6f, 0.3f), CYAN(0.1f, 0.7f, 0.7f), - PINK(0.9f, 0.5f, 0.5f), MAGENTA(0.8f, 0.3f, 0.8f), YELLOW(0.8f, 0.8f, - 0.0f); + PINK(0.9f, 0.5f, 0.5f), MAGENTA(0.8f, 0.3f, 0.8f), + YELLOW(0.8f, 0.8f, 0.0f); final Color colour; @@@ -53,6 -53,7 +53,7 @@@ colour = new Color(r, g, b); } } + private class ConsensusColour { Consensus[] cons; @@@ -106,18 -107,19 +107,18 @@@ for (SequenceI sq : seqs) { - char[] seq = sq.getSequence(); - - int end_j = seq.length - 1; + int end_j = sq.getLength() - 1; + int length = sq.getLength(); for (int i = 0; i <= end_j; i++) { - if ((seq.length - 1) < i) + if (length - 1 < i) { res = 23; } else { - res = ResidueProperties.aaIndex[seq[i]]; + res = ResidueProperties.aaIndex[sq.getCharAt(i)]; } cons2[i][res]++; } @@@ -296,8 -298,7 +297,7 @@@ for (int k = 0; k < residueColour[i].cons.length; k++) { - if (residueColour[i].cons[k].isConserved(cons2, j, size, - includeGaps)) + if (residueColour[i].cons[k].isConserved(cons2, j, size, includeGaps)) { colour = residueColour[i].c; } diff --combined src/jalview/schemes/FeatureColour.java index b748d9e,a40a690..54d1c6c --- a/src/jalview/schemes/FeatureColour.java +++ b/src/jalview/schemes/FeatureColour.java @@@ -125,8 -125,8 +125,8 @@@ public class FeatureColour implements F Color colour = ColorUtils.parseColourString(descriptor); if (colour == null) { - throw new IllegalArgumentException("Invalid colour descriptor: " - + descriptor); + throw new IllegalArgumentException( + "Invalid colour descriptor: " + descriptor); } return new FeatureColour(colour); } @@@ -236,8 -236,8 +236,8 @@@ { if (!ttype.toLowerCase().startsWith("no")) { - System.err.println("Ignoring unrecognised threshold type : " - + ttype); + System.err.println( + "Ignoring unrecognised threshold type : " + ttype); } } } @@@ -256,8 -256,8 +256,8 @@@ } if (gcol.hasMoreTokens()) { - System.err - .println("Ignoring additional tokens in parameters in graduated colour specification\n"); + System.err.println( + "Ignoring additional tokens in parameters in graduated colour specification\n"); while (gcol.hasMoreTokens()) { System.err.println("|" + gcol.nextToken()); @@@ -542,8 -542,7 +542,7 @@@ { if (isColourByLabel()) { - return ColorUtils - .createColourFromName(feature.getDescription()); + return ColorUtils.createColourFromName(feature.getDescription()); } if (!isGraduatedColour()) @@@ -551,27 -550,16 +550,27 @@@ return getColour(); } - // todo should we check for above/below threshold here? - if (range == 0.0) - { - return getMaxColour(); - } + /* + * graduated colour case, optionally with threshold + * Float.NaN is assigned minimum visible score colour + */ float scr = feature.getScore(); if (Float.isNaN(scr)) { return getMinColour(); } + if (isAboveThreshold() && scr <= threshold) + { + return null; + } + if (isBelowThreshold() && scr >= threshold) + { + return null; + } + if (range == 0.0) + { + return getMaxColour(); + } float scl = (scr - base) / range; if (isHighToLow) { @@@ -613,6 -601,44 +612,6 @@@ return (isHighToLow) ? (base + range) : base; } - /** - * Answers true if the feature has a simple colour, or is coloured by label, - * or has a graduated colour and the score of this feature instance is within - * the range to render (if any), i.e. does not lie below or above any - * threshold set. - * - * @param feature - * @return - */ - @Override - public boolean isColored(SequenceFeature feature) - { - if (isColourByLabel() || !isGraduatedColour()) - { - return true; - } - - float val = feature.getScore(); - if (Float.isNaN(val)) - { - return true; - } - if (Float.isNaN(this.threshold)) - { - return true; - } - - if (isAboveThreshold() && val <= threshold) - { - return false; - } - if (isBelowThreshold() && val >= threshold) - { - return false; - } - return true; - } - @Override public boolean isSimpleColour() { diff --combined src/jalview/util/Comparison.java index 94d6300,17d3a70..d4fc233 --- a/src/jalview/util/Comparison.java +++ b/src/jalview/util/Comparison.java @@@ -40,8 -40,9 +40,9 @@@ public class Compariso public static final char GAP_DASH = '-'; - public static final String GapChars = new String(new char[] { GAP_SPACE, - GAP_DOT, GAP_DASH }); + public static final String GapChars = new String( + new char[] + { GAP_SPACE, GAP_DOT, GAP_DASH }); /** * DOCUMENT ME! @@@ -71,7 -72,8 +72,8 @@@ * int * @return float */ - public static float compare(SequenceI ii, SequenceI jj, int start, int end) + public static float compare(SequenceI ii, SequenceI jj, int start, + int end) { String si = ii.getSequenceAsString(); String sj = jj.getSequenceAsString(); @@@ -97,8 -99,8 +99,8 @@@ { for (int j = 0; j < jlen; j++) { - if (si.substring(start + j, start + j + 1).equals( - sj.substring(start + j, start + j + 1))) + if (si.substring(start + j, start + j + 1) + .equals(sj.substring(start + j, start + j + 1))) { match++; } @@@ -112,8 -114,8 +114,8 @@@ { for (int j = 0; j < jlen; j++) { - if (si.substring(start + j, start + j + 1).equals( - sj.substring(start + j, start + j + 1))) + if (si.substring(start + j, start + j + 1) + .equals(sj.substring(start + j, start + j + 1))) { match++; } @@@ -150,7 -152,8 +152,8 @@@ * @deprecated use PIDModel.computePID() */ @Deprecated - public final static float PID(String seq1, String seq2, int start, int end) + public final static float PID(String seq1, String seq2, int start, + int end) { return PID(seq1, seq2, start, end, true, false); } @@@ -282,10 -285,35 +285,10 @@@ { return false; } - char[][] letters = new char[seqs.length][]; - for (int i = 0; i < seqs.length; i++) - { - if (seqs[i] != null) - { - char[] sequence = seqs[i].getSequence(); - if (sequence != null) - { - letters[i] = sequence; - } - } - } - - return areNucleotide(letters); - } - /** - * Answers true if more than 85% of the sequence residues (ignoring gaps) are - * A, G, C, T or U, else false. This is just a heuristic guess and may give a - * wrong answer (as AGCT are also amino acid codes). - * - * @param letters - * @return - */ - static final boolean areNucleotide(char[][] letters) - { int ntCount = 0; int aaCount = 0; - for (char[] seq : letters) + for (SequenceI seq : seqs) { if (seq == null) { @@@ -293,10 -321,8 +296,10 @@@ } // TODO could possibly make an informed guess just from the first sequence // to save a lengthy calculation - for (char c : seq) + int len = seq.getLength(); + for (int i = 0; i < len; i++) { + char c = seq.getCharAt(i); if (isNucleotide(c)) { ntCount++; @@@ -396,8 -422,8 +399,8 @@@ flattened.add(s); } } - final SequenceI[] oneDArray = flattened.toArray(new SequenceI[flattened - .size()]); + final SequenceI[] oneDArray = flattened + .toArray(new SequenceI[flattened.size()]); return isNucleotide(oneDArray); } diff --combined src/jalview/viewmodel/ViewportRanges.java index 49d0f65,f8115a1..42d490e --- a/src/jalview/viewmodel/ViewportRanges.java +++ b/src/jalview/viewmodel/ViewportRanges.java @@@ -456,42 -456,18 +456,42 @@@ public class ViewportRanges extends Vie } /** - * Scroll a wrapped alignment so that the specified residue is visible. Fires - * a property change event. + * Scroll a wrapped alignment so that the specified residue is in the first + * repeat of the wrapped view. Fires a property change event. Answers true if + * the startRes changed, else false. * * @param res * residue position to scroll to + * @return */ - public void scrollToWrappedVisible(int res) + public boolean scrollToWrappedVisible(int res) { - // get the start residue of the wrapped row which res is in - // and set that as our start residue + int oldStartRes = startRes; int width = getViewportWidth(); - setStartRes((res / width) * width); + + if (res >= oldStartRes && res < oldStartRes + width) + { + return false; + } + + boolean up = res < oldStartRes; + int widthsToScroll = Math.abs((res - oldStartRes) / width); + if (up) + { + widthsToScroll++; + } + + int residuesToScroll = width * widthsToScroll; + int newStartRes = up ? oldStartRes - residuesToScroll : oldStartRes + + residuesToScroll; + if (newStartRes < 0) + { + newStartRes = 0; + } + + setStartRes(newStartRes); + + return true; } /** @@@ -529,7 -505,7 +529,7 @@@ } } } - + /** * Adjust sequence position for page up. Fires a property change event. */ @@@ -545,7 -521,7 +545,7 @@@ getViewportHeight()); } } - + /** * Adjust sequence position for page down. Fires a property change event. */ diff --combined src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java index 231cfbe,81d1b7e..2f30e94 --- a/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java +++ b/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java @@@ -26,7 -26,6 +26,7 @@@ import jalview.api.FeaturesDisplayedI import jalview.datamodel.AlignmentI; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; +import jalview.datamodel.features.SequenceFeatures; import jalview.renderer.seqfeatures.FeatureRenderer; import jalview.schemes.FeatureColour; import jalview.util.ColorUtils; @@@ -45,8 -44,8 +45,8 @@@ import java.util.Map import java.util.Set; import java.util.concurrent.ConcurrentHashMap; - public abstract class FeatureRendererModel implements - jalview.api.FeatureRenderer + public abstract class FeatureRendererModel + implements jalview.api.FeatureRenderer { /** @@@ -117,10 -116,11 +117,10 @@@ synchronized (fd) { fd.clear(); - java.util.Iterator fdisp = _fr.getFeaturesDisplayed() - .getVisibleFeatures(); - while (fdisp.hasNext()) + for (String type : _fr.getFeaturesDisplayed() + .getVisibleFeatures()) { - fd.setVisible(fdisp.next()); + fd.setVisible(type); } } } @@@ -215,7 -215,8 +215,8 @@@ if (r[0] != 0 || mm[0] < 0.0) { r[0] = 1; - r[1] = (byte) ((int) 128.0 + 127.0 * (sequenceFeature.score / mm[1])); + r[1] = (byte) ((int) 128.0 + + 127.0 * (sequenceFeature.score / mm[1])); } else { @@@ -264,40 -265,49 +265,40 @@@ } @Override - public List findFeaturesAtRes(SequenceI sequence, - int res) + public List findFeaturesAtColumn(SequenceI sequence, int column) { - ArrayList tmp = new ArrayList(); - SequenceFeature[] features = sequence.getSequenceFeatures(); - - if (features != null) + /* + * include features at the position provided their feature type is + * displayed, and feature group is null or marked for display + */ + List result = new ArrayList(); + if (!av.areFeaturesDisplayed() || getFeaturesDisplayed() == null) { - for (int i = 0; i < features.length; i++) - { - if (!av.areFeaturesDisplayed() || !av.getFeaturesDisplayed() - .isVisible(features[i].getType())) - { - continue; - } + return result; + } - if (features[i].featureGroup != null && featureGroups != null - && featureGroups.containsKey(features[i].featureGroup) - && !featureGroups.get(features[i].featureGroup) - .booleanValue()) - { - continue; - } + Set visibleFeatures = getFeaturesDisplayed() + .getVisibleFeatures(); + String[] visibleTypes = visibleFeatures + .toArray(new String[visibleFeatures.size()]); + List features = sequence.findFeatures(column, column, + visibleTypes); - // check if start/end are at res, and if not a contact feature, that res - // lies between start and end - if ((features[i].getBegin() == res || features[i].getEnd() == res) - || (!features[i].isContactFeature() - && (features[i].getBegin() < res) - && (features[i].getEnd() >= res))) - { - tmp.add(features[i]); - } + for (SequenceFeature sf : features) + { + if (!featureGroupNotShown(sf)) + { + result.add(sf); } } - return tmp; + return result; } /** * Searches alignment for all features and updates colours * * @param newMadeVisible - * if true newly added feature types will be rendered immediatly + * if true newly added feature types will be rendered immediately * TODO: check to see if this method should actually be proxied so * repaint events can be propagated by the renderer code */ @@@ -319,7 -329,8 +320,7 @@@ } FeaturesDisplayedI featuresDisplayed = av.getFeaturesDisplayed(); - ArrayList allfeatures = new ArrayList(); - ArrayList oldfeatures = new ArrayList(); + Set oldfeatures = new HashSet(); if (renderOrder != null) { for (int i = 0; i < renderOrder.length; i++) @@@ -330,110 -341,107 +331,110 @@@ } } } - if (minmax == null) - { - minmax = new Hashtable(); - } - Set oldGroups = new HashSet(featureGroups.keySet()); AlignmentI alignment = av.getAlignment(); + List allfeatures = new ArrayList(); + for (int i = 0; i < alignment.getHeight(); i++) { SequenceI asq = alignment.getSequenceAt(i); - SequenceFeature[] features = asq.getSequenceFeatures(); - - if (features == null) - { - continue; - } - - int index = 0; - while (index < features.length) + for (String group : asq.getFeatures().getFeatureGroups(true)) { - String fgrp = features[index].getFeatureGroup(); - oldGroups.remove(fgrp); - if (!featuresDisplayed.isRegistered(features[index].getType())) + boolean groupDisplayed = true; + if (group != null) { - if (fgrp != null) + if (featureGroups.containsKey(group)) { - Boolean groupDisplayed = featureGroups.get(fgrp); - if (groupDisplayed == null) - { - groupDisplayed = Boolean.valueOf(newMadeVisible); - featureGroups.put(fgrp, groupDisplayed); - } - if (!groupDisplayed.booleanValue()) - { - index++; - continue; - } + groupDisplayed = featureGroups.get(group); } - if (!(features[index].begin == 0 && features[index].end == 0)) + else { - // If beginning and end are 0, the feature is for the whole sequence - // and we don't want to render the feature in the normal way - - if (newMadeVisible - && !oldfeatures.contains(features[index].getType())) - { - // this is a new feature type on the alignment. Mark it for - // display. - featuresDisplayed.setVisible(features[index].getType()); - setOrder(features[index].getType(), 0); - } + groupDisplayed = newMadeVisible; + featureGroups.put(group, groupDisplayed); } } - if (!allfeatures.contains(features[index].getType())) + if (groupDisplayed) { - allfeatures.add(features[index].getType()); - } - if (!Float.isNaN(features[index].score)) - { - int nonpos = features[index].getBegin() >= 1 ? 0 : 1; - float[][] mm = minmax.get(features[index].getType()); - if (mm == null) - { - mm = new float[][] { null, null }; - minmax.put(features[index].getType(), mm); - } - if (mm[nonpos] == null) - { - mm[nonpos] = new float[] { features[index].score, - features[index].score }; - - } - else + Set types = asq.getFeatures().getFeatureTypesForGroups( + true, group); + for (String type : types) { - if (mm[nonpos][0] > features[index].score) + if (!allfeatures.contains(type)) // or use HashSet and no test? { - mm[nonpos][0] = features[index].score; - } - if (mm[nonpos][1] < features[index].score) - { - mm[nonpos][1] = features[index].score; + allfeatures.add(type); } + updateMinMax(asq, type, true); // todo: for all features? } } } } - /* - * oldGroups now consists of groups that no longer - * have any feature in them - remove these - */ - for (String grp : oldGroups) + // uncomment to add new features in alphebetical order (but JAL-2575) + // Collections.sort(allfeatures, String.CASE_INSENSITIVE_ORDER); + if (newMadeVisible) { - featureGroups.remove(grp); + for (String type : allfeatures) + { + if (!oldfeatures.contains(type)) + { + featuresDisplayed.setVisible(type); + setOrder(type, 0); + } + } } updateRenderOrder(allfeatures); findingFeatures = false; } + /** + * Updates the global (alignment) min and max values for a feature type from + * the score for a sequence, if the score is not NaN. Values are stored + * separately for positional and non-positional features. + * + * @param seq + * @param featureType + * @param positional + */ + protected void updateMinMax(SequenceI seq, String featureType, + boolean positional) + { + float min = seq.getFeatures().getMinimumScore(featureType, positional); + if (Float.isNaN(min)) + { + return; + } + + float max = seq.getFeatures().getMaximumScore(featureType, positional); + + /* + * stored values are + * { {positionalMin, positionalMax}, {nonPositionalMin, nonPositionalMax} } + */ + if (minmax == null) + { + minmax = new Hashtable(); + } + synchronized (minmax) + { + float[][] mm = minmax.get(featureType); + int index = positional ? 0 : 1; + if (mm == null) + { + mm = new float[][] { null, null }; + minmax.put(featureType, mm); + } + if (mm[index] == null) + { + mm[index] = new float[] { min, max }; + } + else + { + mm[index][0] = Math.min(mm[index][0], min); + mm[index][1] = Math.max(mm[index][1], max); + } + } + } protected Boolean firing = Boolean.FALSE; /** @@@ -462,7 -470,8 +463,8 @@@ { if (initOrders) { - setOrder(oldRender[j], (1 - (1 + (float) j) / oldRender.length)); + setOrder(oldRender[j], + (1 - (1 + (float) j) / oldRender.length)); } if (allfeatures.contains(oldRender[j])) { @@@ -559,8 -568,7 +561,8 @@@ * Returns the configured colour for a particular feature instance. This * includes calculation of 'colour by label', or of a graduated score colour, * if applicable. It does not take into account feature visibility or colour - * transparency. + * transparency. Returns null for a score feature whose score value lies + * outside any colour threshold. * * @param feature * @return @@@ -568,7 -576,21 +570,7 @@@ public Color getColour(SequenceFeature feature) { FeatureColourI fc = getFeatureStyle(feature.getType()); - return fc.isColored(feature) ? fc.getColor(feature) : null; - } - - /** - * Answers true unless the feature has a score value which lies outside a - * minimum or maximum threshold configured for colouring. This method does not - * check feature type or group visibility. - * - * @param sequenceFeature - * @return - */ - protected boolean showFeature(SequenceFeature sequenceFeature) - { - FeatureColourI fc = getFeatureStyle(sequenceFeature.type); - return fc.isColored(sequenceFeature); + return fc.getColor(feature); } /** @@@ -658,8 -680,7 +660,8 @@@ } /** - * Sets the priority order for features + * Sets the priority order for features, with the highest priority (displayed + * on top) at the start of the data array * * @param data * { String(Type), Colour(Type), Boolean(Displayed) } @@@ -686,7 -707,8 +688,8 @@@ } else { - av.setFeaturesDisplayed(av_featuresdisplayed = new FeaturesDisplayed()); + av.setFeaturesDisplayed( + av_featuresdisplayed = new FeaturesDisplayed()); } } else @@@ -798,11 -820,12 +801,12 @@@ { // conflict between applet and desktop - featureGroups returns the map in // the desktop featureRenderer - return (featureGroups == null) ? Arrays.asList(new String[0]) : Arrays - .asList(featureGroups.keySet().toArray(new String[0])); + return (featureGroups == null) ? Arrays.asList(new String[0]) + : Arrays.asList(featureGroups.keySet().toArray(new String[0])); } - public boolean checkGroupVisibility(String group, boolean newGroupsVisible) + public boolean checkGroupVisibility(String group, + boolean newGroupsVisible) { if (featureGroups == null) { @@@ -883,10 -906,11 +887,10 @@@ { return fcols; } - Iterator features = getViewport().getFeaturesDisplayed() + Set features = getViewport().getFeaturesDisplayed() .getVisibleFeatures(); - while (features.hasNext()) + for (String feature : features) { - String feature = features.next(); fcols.put(feature, getFeatureStyle(feature)); } return fcols; @@@ -928,117 -952,25 +932,117 @@@ public List getDisplayedFeatureGroups() { List _gps = new ArrayList(); - boolean valid = false; for (String gp : getFeatureGroups()) { if (checkGroupVisibility(gp, false)) { - valid = true; _gps.add(gp); } - if (!valid) + } + return _gps; + } + + /** + * Answers true if the feature belongs to a feature group which is not + * currently displayed, else false + * + * @param sequenceFeature + * @return + */ + protected boolean featureGroupNotShown(final SequenceFeature sequenceFeature) + { + return featureGroups != null + && sequenceFeature.featureGroup != null + && sequenceFeature.featureGroup.length() != 0 + && featureGroups.containsKey(sequenceFeature.featureGroup) + && !featureGroups.get(sequenceFeature.featureGroup) + .booleanValue(); + } + + /** + * {@inheritDoc} + */ + @Override + public List findFeaturesAtResidue(SequenceI sequence, + int resNo) + { + List result = new ArrayList(); + if (!av.areFeaturesDisplayed() || getFeaturesDisplayed() == null) + { + return result; + } + + /* + * include features at the position provided their feature type is + * displayed, and feature group is null or the empty string + * or marked for display + */ + Set visibleFeatures = getFeaturesDisplayed() + .getVisibleFeatures(); + String[] visibleTypes = visibleFeatures + .toArray(new String[visibleFeatures.size()]); + List features = sequence.getFeatures().findFeatures( + resNo, resNo, visibleTypes); + + for (SequenceFeature sf : features) + { + if (!featureGroupNotShown(sf)) { - return null; + result.add(sf); } - else + } + return result; + } + + /** + * Removes from the list of features any that have a feature group that is not + * displayed, or duplicate the location of a feature of the same type (unless + * a graduated colour scheme or colour by label is applied). Should be used + * only for features of the same feature colour (which normally implies the + * same feature type). + * + * @param features + * @param fc + */ + public void filterFeaturesForDisplay(List features, + FeatureColourI fc) + { + if (features.isEmpty()) + { + return; + } + SequenceFeatures.sortFeatures(features, true); + boolean simpleColour = fc == null || fc.isSimpleColour(); + SequenceFeature lastFeature = null; + + Iterator it = features.iterator(); + while (it.hasNext()) + { + SequenceFeature sf = it.next(); + if (featureGroupNotShown(sf)) { - // gps = new String[_gps.size()]; - // _gps.toArray(gps); + it.remove(); + continue; } + + /* + * a feature is redundant for rendering purposes if it has the + * same extent as another (so would just redraw the same colour); + * (checking type and isContactFeature as a fail-safe here, although + * currently they are guaranteed to match in this context) + */ + if (simpleColour) + { + if (lastFeature != null && sf.getBegin() == lastFeature.getBegin() + && sf.getEnd() == lastFeature.getEnd() + && sf.isContactFeature() == lastFeature.isContactFeature() + && sf.getType().equals(lastFeature.getType())) + { + it.remove(); + } + } + lastFeature = sf; } - return _gps; } } diff --combined src/jalview/ws/DBRefFetcher.java index 8c8a717,ea6c5f2..fb8864d --- a/src/jalview/ws/DBRefFetcher.java +++ b/src/jalview/ws/DBRefFetcher.java @@@ -26,6 -26,7 +26,6 @@@ import jalview.datamodel.AlignmentI import jalview.datamodel.DBRefEntry; import jalview.datamodel.DBRefSource; import jalview.datamodel.Mapping; -import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; import jalview.gui.CutAndPasteTransfer; import jalview.gui.DasSourceBrowser; @@@ -164,9 -165,9 +164,9 @@@ public class DBRefFetcher implements Ru // af.featureSettings_actionPerformed(null); String[] defdb = null; List selsources = new ArrayList(); - Vector dasselsrc = (featureSettings != null) ? featureSettings - .getSelectedSources() : new DasSourceBrowser() - .getSelectedSources(); + Vector dasselsrc = (featureSettings != null) + ? featureSettings.getSelectedSources() + : new DasSourceBrowser().getSelectedSources(); for (jalviewSourceI src : dasselsrc) { @@@ -250,7 -251,8 +250,8 @@@ DbSourceProxy[] newsrc = new DbSourceProxy[dbSources.length + otherdb.length]; System.arraycopy(dbSources, 0, newsrc, 0, dbSources.length); - System.arraycopy(otherdb, 0, newsrc, dbSources.length, otherdb.length); + System.arraycopy(otherdb, 0, newsrc, dbSources.length, + otherdb.length); dbSources = newsrc; } } @@@ -330,9 -332,8 +331,8 @@@ { if (dbSources == null) { - throw new Error( - MessageManager - .getString("error.implementation_error_must_init_dbsources")); + throw new Error(MessageManager + .getString("error.implementation_error_must_init_dbsources")); } running = true; long startTime = System.currentTimeMillis(); @@@ -397,8 -398,8 +397,8 @@@ String query = queries.elementAt(0); if (dbsource.isValidReference(query)) { - queryString.append((numq == 0) ? "" : dbsource - .getAccessionSeparator()); + queryString.append( + (numq == 0) ? "" : dbsource.getAccessionSeparator()); queryString.append(query); numq++; } @@@ -432,12 -433,13 +432,13 @@@ else { // make some more strings for use as queries - for (int i = 0; (seqIndex < dataset.length) && (i < 50); seqIndex++, i++) + for (int i = 0; (seqIndex < dataset.length) + && (i < 50); seqIndex++, i++) { SequenceI sequence = dataset[seqIndex]; - DBRefEntry[] uprefs = DBRefUtils.selectRefs( - sequence.getDBRefs(), - new String[] { dbsource.getDbSource() }); // jalview.datamodel.DBRefSource.UNIPROT + DBRefEntry[] uprefs = DBRefUtils + .selectRefs(sequence.getDBRefs(), new String[] + { dbsource.getDbSource() }); // jalview.datamodel.DBRefSource.UNIPROT // }); // check for existing dbrefs to use if (uprefs != null && uprefs.length > 0) @@@ -445,7 -447,8 +446,8 @@@ for (int j = 0; j < uprefs.length; j++) { addSeqId(sequence, uprefs[j].getAccessionId()); - queries.addElement(uprefs[j].getAccessionId().toUpperCase()); + queries.addElement( + uprefs[j].getAccessionId().toUpperCase()); } } else @@@ -462,14 -465,13 +464,13 @@@ // resolve the string against PICR to recover valid IDs try { - presp = picrClient - .getUPIForAccession(token, null, - picrClient.getMappedDatabaseNames(), - null, true); + presp = picrClient.getUPIForAccession(token, null, + picrClient.getMappedDatabaseNames(), null, + true); } catch (Exception e) { - System.err.println("Exception with Picr for '" + token - + "'\n"); + System.err.println( + "Exception with Picr for '" + token + "'\n"); e.printStackTrace(); } } @@@ -481,8 -483,8 +482,8 @@@ // present, and do a transferReferences // otherwise transfer non sequence x-references directly. } - System.out - .println("Validated ID against PICR... (for what its worth):" + System.out.println( + "Validated ID against PICR... (for what its worth):" + token); addSeqId(sequence, token); queries.addElement(token.toUpperCase()); @@@ -490,7 -492,8 +491,8 @@@ else { // if () - // System.out.println("Not querying source with token="+token+"\n"); + // System.out.println("Not querying source with + // token="+token+"\n"); addSeqId(sequence, token); queries.addElement(token.toUpperCase()); } @@@ -514,7 -517,8 +516,8 @@@ output.setText(sb.toString()); Desktop.addInternalFrame(output, - MessageManager.getString("label.sequences_updated"), 600, 300); + MessageManager.getString("label.sequences_updated"), 600, + 300); // The above is the dataset, we must now find out the index // of the viewed sequence @@@ -561,8 -565,8 +564,8 @@@ } boolean modified = false; - SequenceI[] retrieved = recoverDbSequences(retrievedAl - .getSequencesArray()); + SequenceI[] retrieved = recoverDbSequences( + retrievedAl.getSequencesArray()); SequenceI sequence = null; for (SequenceI retrievedSeq : retrieved) @@@ -571,8 -575,9 +574,9 @@@ // taking into account all accessionIds and names in the file Vector sequenceMatches = new Vector(); // look for corresponding accession ids - DBRefEntry[] entryRefs = DBRefUtils.selectRefs( - retrievedSeq.getDBRefs(), new String[] { dbSource }); + DBRefEntry[] entryRefs = DBRefUtils + .selectRefs(retrievedSeq.getDBRefs(), new String[] + { dbSource }); if (entryRefs == null) { System.err @@@ -649,8 -654,9 +653,9 @@@ final int sequenceStart = sequence.getStart(); boolean remoteEnclosesLocal = false; - String nonGapped = AlignSeq.extractGaps("-. ", - sequence.getSequenceAsString()).toUpperCase(); + String nonGapped = AlignSeq + .extractGaps("-. ", sequence.getSequenceAsString()) + .toUpperCase(); int absStart = entrySeq.indexOf(nonGapped); if (absStart == -1) { @@@ -680,10 -686,14 +685,14 @@@ * So create a mapping to the external entry from the matching region of * the local sequence, and leave local start/end untouched. */ - mp = new Mapping(null, new int[] { sequenceStart + absStart, - sequenceStart + absStart + entrySeq.length() - 1 }, new int[] - { retrievedSeq.getStart(), - retrievedSeq.getStart() + entrySeq.length() - 1 }, 1, 1); + mp = new Mapping(null, + new int[] + { sequenceStart + absStart, + sequenceStart + absStart + entrySeq.length() - 1 }, + new int[] + { retrievedSeq.getStart(), + retrievedSeq.getStart() + entrySeq.length() - 1 }, + 1, 1); updateRefFrame = false; } else @@@ -696,13 -706,28 +705,13 @@@ if (updateRefFrame) { - SequenceFeature[] sfs = sequence.getSequenceFeatures(); - if (sfs != null) + /* + * relocate existing sequence features by offset + */ + int startShift = absStart - sequenceStart + 1; + if (startShift != 0) { - /* - * relocate existing sequence features by offset - */ - int start = sequenceStart; - int end = sequence.getEnd(); - int startShift = 1 - absStart - start; - - if (startShift != 0) - { - for (SequenceFeature sf : sfs) - { - if (sf.getBegin() >= start && sf.getEnd() <= end) - { - sf.setBegin(sf.getBegin() + startShift); - sf.setEnd(sf.getEnd() + startShift); - modified = true; - } - } - } + modified |= sequence.getFeatures().shiftFeatures(startShift); } } } @@@ -725,8 -750,8 +734,8 @@@ sequence.setSequence(retrievedSeqString); modified = true; addWarningMessage(warningMessages, - "Sequence for " + sequence.getName() - + " expanded from " + retrievedSeq.getName()); + "Sequence for " + sequence.getName() + " expanded from " + + retrievedSeq.getName()); } if (sequence.getStart() != retrievedSeq.getStart()) { @@@ -734,9 -759,9 +743,9 @@@ modified = true; if (absStart != sequenceStart) { - addWarningMessage(warningMessages, "Start/end position for " - + sequence.getName() + " updated from " - + retrievedSeq.getName()); + addWarningMessage(warningMessages, + "Start/end position for " + sequence.getName() + + " updated from " + retrievedSeq.getName()); } } } @@@ -752,9 -777,9 +761,9 @@@ sequence.setStart(absStart); sequence.setEnd(absEnd); modified = true; - addWarningMessage(warningMessages, "Start/end for " - + sequence.getName() + " updated from " - + retrievedSeq.getName()); + addWarningMessage(warningMessages, + "Start/end for " + sequence.getName() + + " updated from " + retrievedSeq.getName()); } } // search for alignment sequences to update coordinate frame for @@@ -762,16 -787,17 +771,17 @@@ { if (alseqs[alsq].getDatasetSequence() == sequence) { - String ngAlsq = AlignSeq.extractGaps("-. ", - alseqs[alsq].getSequenceAsString()).toUpperCase(); + String ngAlsq = AlignSeq + .extractGaps("-. ", + alseqs[alsq].getSequenceAsString()) + .toUpperCase(); int oldstrt = alseqs[alsq].getStart(); alseqs[alsq].setStart(sequence.getSequenceAsString() - .toUpperCase().indexOf(ngAlsq) - + sequence.getStart()); + .toUpperCase().indexOf(ngAlsq) + sequence.getStart()); if (oldstrt != alseqs[alsq].getStart()) { - alseqs[alsq].setEnd(ngAlsq.length() - + alseqs[alsq].getStart() - 1); + alseqs[alsq].setEnd( + ngAlsq.length() + alseqs[alsq].getStart() - 1); modified = true; } } @@@ -815,7 -841,8 +825,8 @@@ private SequenceI[] recoverDbSequences(SequenceI[] sequencesArray) { Vector nseq = new Vector(); - for (int i = 0; sequencesArray != null && i < sequencesArray.length; i++) + for (int i = 0; sequencesArray != null + && i < sequencesArray.length; i++) { nseq.addElement(sequencesArray[i]); DBRefEntry[] dbr = sequencesArray[i].getDBRefs(); diff --combined src/jalview/ws/dbsources/Uniprot.java index 7261cba,30808fb..c868576 --- a/src/jalview/ws/dbsources/Uniprot.java +++ b/src/jalview/ws/dbsources/Uniprot.java @@@ -28,9 -28,8 +28,9 @@@ import jalview.datamodel.PDBEntry import jalview.datamodel.Sequence; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; -import jalview.datamodel.UniprotEntry; -import jalview.datamodel.UniprotFile; +import jalview.datamodel.xdb.uniprot.UniprotEntry; +import jalview.datamodel.xdb.uniprot.UniprotFeature; +import jalview.datamodel.xdb.uniprot.UniprotFile; import jalview.ws.ebi.EBIFetchClient; import jalview.ws.seqfetcher.DbSourceProxyImpl; @@@ -167,7 -166,8 +167,8 @@@ public class Uniprot extends DbSourcePr // uniprotkb dbname changed introduced december 2008 File file = ebi.fetchDataAsFile("uniprotkb:" + queries, "uniprotxml", "xml"); - Vector entries = getUniprotEntries(new FileReader(file)); + Vector entries = getUniprotEntries( + new FileReader(file)); if (entries != null) { @@@ -197,8 -197,8 +198,8 @@@ public SequenceI uniprotEntryToSequenceI(UniprotEntry entry) { String id = getUniprotEntryId(entry); - SequenceI sequence = new Sequence(id, entry.getUniprotSequence() - .getContent()); + SequenceI sequence = new Sequence(id, + entry.getUniprotSequence().getContent()); sequence.setDescription(getUniprotEntryDescription(entry)); final String dbVersion = getDbVersion(); @@@ -249,23 -249,22 +250,23 @@@ String cdsId = (String) pdb.getProperty("protein sequence ID"); if (cdsId != null && cdsId.trim().length() > 0) { - dbr = new DBRefEntry(DBRefSource.ENSEMBL, DBRefSource.UNIPROT - + ":" + dbVersion, cdsId.trim()); + dbr = new DBRefEntry(DBRefSource.ENSEMBL, + DBRefSource.UNIPROT + ":" + dbVersion, cdsId.trim()); dbRefs.add(dbr); } } - } sequence.setPDBId(onlyPdbEntries); if (entry.getFeature() != null) { - for (SequenceFeature sf : entry.getFeature()) + for (UniprotFeature uf : entry.getFeature()) { - sf.setFeatureGroup("Uniprot"); - sequence.addSequenceFeature(sf); + SequenceFeature copy = new SequenceFeature(uf.getType(), + uf.getDescription(), uf.getBegin(), uf.getEnd(), "Uniprot"); + copy.setStatus(uf.getStatus()); + sequence.addSequenceFeature(copy); } } for (DBRefEntry dbr : dbRefs) diff --combined src/jalview/ws/jws2/AADisorderClient.java index b877d20,fb6ffc4..c24ea05 --- a/src/jalview/ws/jws2/AADisorderClient.java +++ b/src/jalview/ws/jws2/AADisorderClient.java @@@ -20,6 -20,7 +20,6 @@@ */ package jalview.ws.jws2; -import jalview.api.AlignCalcWorkerI; import jalview.api.FeatureColourI; import jalview.bin.Cache; import jalview.datamodel.AlignmentAnnotation; @@@ -62,9 -63,9 +62,9 @@@ public class AADisorderClient extends J AlignFrame af; public AADisorderClient(Jws2Instance sh, AlignFrame alignFrame, -- WsParamSetI preset, List paramset) ++ WsParamSetI thePreset, List paramset) { -- super(sh, alignFrame, preset, paramset); ++ super(sh, alignFrame, thePreset, paramset); af = alignFrame; typeName = sh.action; methodName = sh.serviceType; @@@ -103,8 -104,9 +103,9 @@@ Map fmap; featureMap.put(compbio.ws.client.Services.IUPredWS.toString(), fmap = new HashMap()); - fmap.put("Glob", new String[] { "Globular Domain", - "Predicted globular domain" }); + fmap.put("Glob", + new String[] + { "Globular Domain", "Predicted globular domain" }); featureMap.put(compbio.ws.client.Services.JronnWS.toString(), fmap = new HashMap()); featureMap.put(compbio.ws.client.Services.DisemblWS.toString(), @@@ -114,10 -116,12 +115,12 @@@ fmap.put("COILS", new String[] { "COILS", "Random coil" }); featureMap.put(compbio.ws.client.Services.GlobPlotWS.toString(), fmap = new HashMap()); - fmap.put("GlobDoms", new String[] { "Globular Domain", - "Predicted globular domain" }); - fmap.put("Disorder", new String[] { "Protein Disorder", - "Probable unstructured peptide region" }); + fmap.put("GlobDoms", + new String[] + { "Globular Domain", "Predicted globular domain" }); + fmap.put("Disorder", + new String[] + { "Protein Disorder", "Probable unstructured peptide region" }); Map> amap; annotMap = new HashMap>>(); annotMap.put(compbio.ws.client.Services.GlobPlotWS.toString(), @@@ -206,9 -210,7 +209,7 @@@ { Cache.log .info("Couldn't recover disorder prediction for sequence " - + seq.getName() - + "(Prediction name was " - + seqId + + seq.getName() + "(Prediction name was " + seqId + ")" + "\nSee http://issues.jalview.org/browse/JAL-1319 for one possible reason why disorder predictions might fail."); } @@@ -237,13 -239,13 +238,13 @@@ } if (vals.hasNext()) { - sf = new SequenceFeature(type[0], type[1], base + rn.from, - base + rn.to, val = vals.next().floatValue(), - methodName); + val = vals.next().floatValue(); + sf = new SequenceFeature(type[0], type[1], + base + rn.from, base + rn.to, val, methodName); } else { - sf = new SequenceFeature(type[0], type[1], null, + sf = new SequenceFeature(type[0], type[1], base + rn.from, base + rn.to, methodName); } dseq.addSequenceFeature(sf); @@@ -267,13 -269,15 +268,15 @@@ typename = service.serviceType + " (" + scr.getMethod() + ")", calcName = service.getServiceTypeURI() + "/" - + scr.getMethod(), aseq, base + 1, scr); + + scr.getMethod(), + aseq, base + 1, scr); annot.graph = AlignmentAnnotation.LINE_GRAPH; Map styleMap = (annotTypeMap == null) ? null : annotTypeMap.get(scr.getMethod()); - annot.visible = (styleMap == null || styleMap.get(INVISIBLE) == null); + annot.visible = (styleMap == null + || styleMap.get(INVISIBLE) == null); double[] thrsh = (styleMap == null) ? null : (double[]) styleMap.get(THRESHOLD); float[] range = (styleMap == null) ? null @@@ -307,8 -311,8 +310,8 @@@ annot.description += "
" + threshNote; } annot.description += ""; - Color col = ColorUtils.createColourFromName(typeName - + scr.getMethod()); + Color col = ColorUtils + .createColourFromName(typeName + scr.getMethod()); for (int p = 0, ps = annot.annotations.length; p < ps; p++) { if (annot.annotations[p] != null) diff --combined src/jalview/ws/rest/params/SeqVector.java index 578e7cc,e03cd64..55ca3ff --- a/src/jalview/ws/rest/params/SeqVector.java +++ b/src/jalview/ws/rest/params/SeqVector.java @@@ -65,7 -65,7 +65,7 @@@ public class SeqVector extends InputTyp { idvector.append(sep); } - idvector.append(seq.getSequence()); + idvector.append(seq.getSequenceAsString()); } return new StringBody(idvector.toString()); } @@@ -107,8 -107,8 +107,8 @@@ return true; } catch (Exception x) { - warnings.append("Invalid molecule type '" + val - + "'. Must be one of ("); + warnings.append( + "Invalid molecule type '" + val + "'. Must be one of ("); for (molType v : molType.values()) { warnings.append(" " + v); @@@ -125,8 -125,8 +125,8 @@@ List lst = getBaseOptions(); lst.add(new Option("sep", "Separator character between elements of vector", true, ",", - sep, Arrays.asList(new String[] { " ", ",", ";", "\t", "|" }), - null)); + sep, Arrays.asList(new String[] + { " ", ",", ";", "\t", "|" }), null)); lst.add(createMolTypeOption("type", "Sequence type", false, type, molType.MIX));