X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fio%2FAnnotationFile.java;h=3d8096ba4c199d83ecef4951cee02728f8b39f19;hb=c409accc368019ba99d508e6b9053a053e052e2d;hp=668aa3cdb717897b02f801945862204a1dc7f2cd;hpb=47168f025aefdaa044802bd5f8f510ffe43a4808;p=jalview.git diff --git a/src/jalview/io/AnnotationFile.java b/src/jalview/io/AnnotationFile.java index 668aa3c..3d8096b 100755 --- a/src/jalview/io/AnnotationFile.java +++ b/src/jalview/io/AnnotationFile.java @@ -1,6 +1,6 @@ /* - * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2) - * Copyright (C) 2014 The Jalview Authors + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors * * This file is part of Jalview. * @@ -20,13 +20,39 @@ */ package jalview.io; -import java.io.*; -import java.net.*; -import java.util.*; - -import jalview.analysis.*; -import jalview.datamodel.*; -import jalview.schemes.*; +import jalview.analysis.Conservation; +import jalview.api.AlignViewportI; +import jalview.datamodel.AlignmentAnnotation; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.Annotation; +import jalview.datamodel.ColumnSelection; +import jalview.datamodel.GraphLine; +import jalview.datamodel.HiddenColumns; +import jalview.datamodel.HiddenSequences; +import jalview.datamodel.SequenceGroup; +import jalview.datamodel.SequenceI; +import jalview.schemes.ColourSchemeI; +import jalview.schemes.ColourSchemeProperty; +import jalview.util.ColorUtils; + +import java.awt.Color; +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.InputStreamReader; +import java.io.StringReader; +import java.net.URL; +import java.util.ArrayList; +import java.util.BitSet; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.Vector; public class AnnotationFile { @@ -67,18 +93,19 @@ public class AnnotationFile } /** - * convenience method for pre-2.4 feature files which have no view, hidden + * convenience method for pre-2.9 annotation files which have no view, hidden * columns or hidden row keywords. * * @param annotations * @param list * @param properties - * @return feature file as a string. + * @return annotation file as a string. */ public String printAnnotations(AlignmentAnnotation[] annotations, List list, Hashtable properties) { - return printAnnotations(annotations, list, properties, null); + return printAnnotations(annotations, list, properties, null, null, + null); } @@ -88,23 +115,22 @@ public class AnnotationFile */ public class ViewDef { - public String viewname; - - public HiddenSequences hidseqs; + // TODO this class is not used - remove? + public final String viewname; - public ColumnSelection hiddencols; + public final HiddenSequences hidseqs; - public Vector visibleGroups; + public final HiddenColumns hiddencols; - public Hashtable hiddenRepSeqs; + public final Hashtable hiddenRepSeqs; - public ViewDef(String viewname, HiddenSequences hidseqs, - ColumnSelection hiddencols, Hashtable hiddenRepSeqs) + public ViewDef(String vname, HiddenSequences hseqs, HiddenColumns hcols, + Hashtable hRepSeqs) { - this.viewname = viewname; - this.hidseqs = hidseqs; - this.hiddencols = hiddencols; - this.hiddenRepSeqs = hiddenRepSeqs; + this.viewname = vname; + this.hidseqs = hseqs; + this.hiddencols = hcols; + this.hiddenRepSeqs = hRepSeqs; } } @@ -119,10 +145,43 @@ public class AnnotationFile * @return annotation file */ public String printAnnotations(AlignmentAnnotation[] annotations, - List list, Hashtable properties, ViewDef[] views) + List list, Hashtable properties, HiddenColumns cs, + AlignmentI al, ViewDef view) { - // TODO: resolve views issue : annotationFile could contain visible region, - // or full data + hidden region specifications for a view. + if (view != null) + { + if (view.viewname != null) + { + text.append("VIEW_DEF\t" + view.viewname + "\n"); + } + if (list == null) + { + // list = view.visibleGroups; + } + if (cs == null) + { + cs = view.hiddencols; + } + if (al == null) + { + // add hidden rep sequences. + } + } + // first target - store and restore all settings for a view. + if (al != null && al.hasSeqrep()) + { + text.append("VIEW_SETREF\t" + al.getSeqrep().getName() + "\n"); + } + if (cs != null && cs.hasHiddenColumns()) + { + text.append("VIEW_HIDECOLS\t"); + + String regions = cs.regionsToString(",", "-"); + text.append(regions); + text.append("\n"); + } + // TODO: allow efficient recovery of annotation data shown in several + // different views if (annotations != null) { boolean oneColour = true; @@ -134,8 +193,8 @@ public class AnnotationFile StringBuffer colours = new StringBuffer(); StringBuffer graphLine = new StringBuffer(); StringBuffer rowprops = new StringBuffer(); - Hashtable graphGroup = new Hashtable(); - Hashtable graphGroup_refs = new Hashtable(); + Hashtable graphGroup = new Hashtable<>(); + Hashtable graphGroup_refs = new Hashtable<>(); BitSet graphGroupSeen = new BitSet(); java.awt.Color color; @@ -144,22 +203,24 @@ public class AnnotationFile { row = annotations[i]; - if (!row.visible && !row.hasScore() && !(row.graphGroup>-1 && graphGroupSeen.get(row.graphGroup))) + if (!row.visible && !row.hasScore() && !(row.graphGroup > -1 + && graphGroupSeen.get(row.graphGroup))) { continue; } color = null; oneColour = true; - + // mark any sequence references for the row - writeSequence_Ref(refSeq ,row.sequenceRef); + writeSequence_Ref(refSeq, row.sequenceRef); refSeq = row.sequenceRef; // mark any group references for the row writeGroup_Ref(refGroup, row.groupRef); refGroup = row.groupRef; - boolean hasGlyphs = row.hasIcons, hasLabels = row.hasText, hasValues = row.hasScore, hasText = false; + boolean hasGlyphs = row.hasIcons, hasLabels = row.hasText, + hasValues = row.hasScore, hasText = false; // lookahead to check what the annotation row object actually contains. for (int j = 0; row.annotations != null && j < row.annotations.length @@ -168,14 +229,15 @@ public class AnnotationFile if (row.annotations[j] != null) { hasLabels |= (row.annotations[j].displayCharacter != null - && row.annotations[j].displayCharacter.length() > 0 && !row.annotations[j].displayCharacter - .equals(" ")); - hasGlyphs |= (row.annotations[j].secondaryStructure != 0 && row.annotations[j].secondaryStructure != ' '); - hasValues |= (row.annotations[j].value != Float.NaN); // NaNs can't + && row.annotations[j].displayCharacter.length() > 0 + && !row.annotations[j].displayCharacter.equals(" ")); + hasGlyphs |= (row.annotations[j].secondaryStructure != 0 + && row.annotations[j].secondaryStructure != ' '); + hasValues |= (!Float.isNaN(row.annotations[j].value)); // NaNs can't // be // rendered.. - hasText |= (row.annotations[j].description != null && row.annotations[j].description - .length() > 0); + hasText |= (row.annotations[j].description != null + && row.annotations[j].description.length() > 0); } } @@ -208,8 +270,8 @@ public class AnnotationFile graphLine.append("\t"); graphLine.append(row.getThreshold().label); graphLine.append("\t"); - graphLine.append(jalview.util.Format.getHexString(row - .getThreshold().colour)); + graphLine.append(jalview.util.Format + .getHexString(row.getThreshold().colour)); graphLine.append(newline); } @@ -220,11 +282,11 @@ public class AnnotationFile if (graphGroup.containsKey(key)) { graphGroup.put(key, graphGroup.get(key) + "\t" + row.label); - + } else { - graphGroup_refs.put(key, new Object[] { refSeq, refGroup}); + graphGroup_refs.put(key, new Object[] { refSeq, refGroup }); graphGroup.put(key, row.label); } } @@ -260,13 +322,13 @@ public class AnnotationFile } if (hasValues) { - if (row.annotations[j].value != Float.NaN) + if (!Float.isNaN(row.annotations[j].value)) { text.append(comma + row.annotations[j].value); } else { - System.err.println("Skipping NaN - not valid value."); + // System.err.println("Skipping NaN - not valid value."); text.append(comma + 0f);// row.annotations[j].value); } comma = ","; @@ -304,11 +366,8 @@ public class AnnotationFile if (row.annotations[j].colour != null && row.annotations[j].colour != java.awt.Color.black) { - text.append(comma - + "[" - + jalview.util.Format - .getHexString(row.annotations[j].colour) - + "]"); + text.append(comma + "[" + jalview.util.Format + .getHexString(row.annotations[j].colour) + "]"); comma = ","; } } @@ -316,7 +375,9 @@ public class AnnotationFile } if (row.hasScore()) + { text.append("\t" + row.score); + } text.append(newline); @@ -341,7 +402,8 @@ public class AnnotationFile rowprops.append(row.centreColLabels); rowprops.append(newline); } - if (graphLine.length()>0) { + if (graphLine.length() > 0) + { text.append(graphLine.toString()); graphLine.setLength(0); } @@ -354,22 +416,24 @@ public class AnnotationFile { SequenceI oldRefSeq = refSeq; SequenceGroup oldRefGroup = refGroup; - for (Map.Entry combine_statement:graphGroup.entrySet()) - { - Object[] seqRefAndGroup=graphGroup_refs.get(combine_statement.getKey()); - - writeSequence_Ref(refSeq, (SequenceI)seqRefAndGroup[0]); - refSeq = (SequenceI)seqRefAndGroup[0]; - - writeGroup_Ref(refGroup, (SequenceGroup)seqRefAndGroup[1]); - refGroup = (SequenceGroup)seqRefAndGroup[1]; + for (Map.Entry combine_statement : graphGroup + .entrySet()) + { + Object[] seqRefAndGroup = graphGroup_refs + .get(combine_statement.getKey()); + + writeSequence_Ref(refSeq, (SequenceI) seqRefAndGroup[0]); + refSeq = (SequenceI) seqRefAndGroup[0]; + + writeGroup_Ref(refGroup, (SequenceGroup) seqRefAndGroup[1]); + refGroup = (SequenceGroup) seqRefAndGroup[1]; text.append("COMBINE\t"); text.append(combine_statement.getValue()); text.append(newline); } writeSequence_Ref(refSeq, oldRefSeq); refSeq = oldRefSeq; - + writeGroup_Ref(refGroup, oldRefGroup); refGroup = oldRefGroup; } @@ -396,13 +460,16 @@ public class AnnotationFile text.append(properties.get(key)); } // TODO: output alignment visualization settings here if required - + // iterate through one or more views, defining, marking columns and rows + // as visible/hidden, and emmitting view properties. + // View specific annotation is } return text.toString(); } - private Object writeGroup_Ref(SequenceGroup refGroup, SequenceGroup next_refGroup) + private Object writeGroup_Ref(SequenceGroup refGroup, + SequenceGroup next_refGroup) { if (next_refGroup == null) { @@ -427,13 +494,13 @@ public class AnnotationFile return true; } } - return false; + return false; } - + private boolean writeSequence_Ref(SequenceI refSeq, SequenceI next_refSeq) { - if (next_refSeq==null) + if (next_refSeq == null) { if (refSeq != null) { @@ -458,7 +525,7 @@ public class AnnotationFile return false; } - public void printGroups(List list) + protected void printGroups(List list) { SequenceI seqrep = null; for (SequenceGroup sg : list) @@ -504,7 +571,8 @@ public class AnnotationFile if (sg.cs != null) { text.append("colour="); - text.append(ColourSchemeProperty.getColourName(sg.cs)); + text.append(ColourSchemeProperty + .getColourName(sg.cs.getColourScheme())); text.append("\t"); if (sg.cs.getThreshold() != 0) { @@ -582,26 +650,56 @@ public class AnnotationFile String refSeqId = null; + public boolean annotateAlignmentView(AlignViewportI viewport, String file, + DataSourceType protocol) + { + ColumnSelection colSel = viewport.getColumnSelection(); + HiddenColumns hidden = viewport.getAlignment().getHiddenColumns(); + if (colSel == null) + { + colSel = new ColumnSelection(); + } + if (hidden == null) + { + hidden = new HiddenColumns(); + } + boolean rslt = readAnnotationFile(viewport.getAlignment(), hidden, file, + protocol); + if (rslt && (colSel.hasSelectedColumns() || hidden.hasHiddenColumns())) + { + viewport.setColumnSelection(colSel); + viewport.getAlignment().setHiddenColumns(hidden); + } + + return rslt; + } + public boolean readAnnotationFile(AlignmentI al, String file, - String protocol) + DataSourceType sourceType) + { + return readAnnotationFile(al, null, file, sourceType); + } + + public boolean readAnnotationFile(AlignmentI al, HiddenColumns hidden, + String file, DataSourceType sourceType) { BufferedReader in = null; try { - if (protocol.equals(AppletFormatAdapter.FILE)) + if (sourceType == DataSourceType.FILE) { in = new BufferedReader(new FileReader(file)); } - else if (protocol.equals(AppletFormatAdapter.URL)) + else if (sourceType == DataSourceType.URL) { URL url = new URL(file); in = new BufferedReader(new InputStreamReader(url.openStream())); } - else if (protocol.equals(AppletFormatAdapter.PASTE)) + else if (sourceType == DataSourceType.PASTE) { in = new BufferedReader(new StringReader(file)); } - else if (protocol.equals(AppletFormatAdapter.CLASSLOADER)) + else if (sourceType == DataSourceType.CLASSLOADER) { java.io.InputStream is = getClass().getResourceAsStream("/" + file); if (is != null) @@ -611,405 +709,502 @@ public class AnnotationFile } if (in != null) { - return parseAnnotationFrom(al, in); + return parseAnnotationFrom(al, hidden, in); } } catch (Exception ex) { ex.printStackTrace(); System.out.println("Problem reading annotation file: " + ex); - if (nlinesread>0) { - System.out.println("Last read line "+nlinesread+": '"+lastread+"' (first 80 chars) ..."); + if (nlinesread > 0) + { + System.out.println("Last read line " + nlinesread + ": '" + lastread + + "' (first 80 chars) ..."); } return false; } return false; } - long nlinesread=0; - String lastread=""; - private static String GRAPHLINE="GRAPHLINE", COMBINE="COMBINE"; - public boolean parseAnnotationFrom(AlignmentI al, BufferedReader in) - throws Exception + + long nlinesread = 0; + + String lastread = ""; + + private static String GRAPHLINE = "GRAPHLINE", COMBINE = "COMBINE"; + + public boolean parseAnnotationFrom(AlignmentI al, HiddenColumns hidden, + BufferedReader in) throws Exception { nlinesread = 0; - ArrayList combineAnnotation_calls = new ArrayList(); - ArrayList deferredAnnotation_calls = new ArrayList(); + List combineAnnotation_calls = new ArrayList<>(); + List deferredAnnotation_calls = new ArrayList<>(); boolean modified = false; String groupRef = null; - Hashtable groupRefRows = new Hashtable(); - - Hashtable autoAnnots = new Hashtable(); + Map> groupRefRows = new HashMap<>(); + + Set autoAnnots = new HashSet<>(); + String line, label, description, token; + int graphStyle, index; + int refSeqIndex = 1; + int existingAnnotationCount = 0; + // when true - will add new rows regardless of whether they are duplicate + // auto-annotation like consensus or conservation graphs + boolean overrideAutoAnnot = false; + if (al.getAlignmentAnnotation() != null) { - String line, label, description, token; - int graphStyle, index; - int refSeqIndex = 1; - int existingAnnotations = 0; - // when true - will add new rows regardless of whether they are duplicate - // auto-annotation like consensus or conservation graphs - boolean overrideAutoAnnot = false; - if (al.getAlignmentAnnotation() != null) - { - existingAnnotations = al.getAlignmentAnnotation().length; - if (existingAnnotations > 0) - { - AlignmentAnnotation[] aa = al.getAlignmentAnnotation(); - for (int aai = 0; aai < aa.length; aai++) + existingAnnotationCount = al.getAlignmentAnnotation().length; + if (existingAnnotationCount > 0) + { + AlignmentAnnotation[] aa = al.getAlignmentAnnotation(); + for (int aai = 0; aai < aa.length; aai++) + { + if (aa[aai].autoCalculated) { - if (aa[aai].autoCalculated) - { - // make a note of the name and description - autoAnnots.put( - autoAnnotsKey(aa[aai], aa[aai].sequenceRef, - (aa[aai].groupRef == null ? null - : aa[aai].groupRef.getName())), - new Integer(1)); - } + // make a note of the name and description + autoAnnots.add(autoAnnotsKey(aa[aai], aa[aai].sequenceRef, + (aa[aai].groupRef == null ? null + : aa[aai].groupRef.getName()))); } } } + } - int alWidth = al.getWidth(); + int alWidth = al.getWidth(); - StringTokenizer st; - Annotation[] annotations; - AlignmentAnnotation annotation = null; + StringTokenizer st; + Annotation[] annotations; + AlignmentAnnotation annotation = null; - // First confirm this is an Annotation file - boolean jvAnnotationFile = false; - while ((line = in.readLine()) != null) + // First confirm this is an Annotation file + boolean jvAnnotationFile = false; + while ((line = in.readLine()) != null) + { + nlinesread++; + lastread = new String(line); + if (line.indexOf("#") == 0) { - nlinesread++;lastread = new String(line); - if (line.indexOf("#") == 0) - { - continue; - } - - if (line.indexOf("JALVIEW_ANNOTATION") > -1) - { - jvAnnotationFile = true; - break; - } + continue; } - if (!jvAnnotationFile) + if (line.indexOf("JALVIEW_ANNOTATION") > -1) { - in.close(); - return false; + jvAnnotationFile = true; + break; } + } + + if (!jvAnnotationFile) + { + in.close(); + return false; + } - while ((line = in.readLine()) != null) + while ((line = in.readLine()) != null) + { + nlinesread++; + lastread = new String(line); + if (line.indexOf("#") == 0 || line.indexOf("JALVIEW_ANNOTATION") > -1 + || line.length() == 0) { - nlinesread++;lastread = new String(line); - if (line.indexOf("#") == 0 - || line.indexOf("JALVIEW_ANNOTATION") > -1 - || line.length() == 0) - { - continue; - } + continue; + } - st = new StringTokenizer(line, "\t"); - token = st.nextToken(); - if (token.equalsIgnoreCase("COLOUR")) - { - // TODO: use graduated colour def'n here too - colourAnnotations(al, st.nextToken(), st.nextToken()); - modified = true; - continue; - } + st = new StringTokenizer(line, "\t"); + token = st.nextToken(); + if (token.equalsIgnoreCase("COLOUR")) + { + // TODO: use graduated colour def'n here too + colourAnnotations(al, st.nextToken(), st.nextToken()); + modified = true; + continue; + } - else if (token.equalsIgnoreCase(COMBINE)) - { - // keep a record of current state and resolve groupRef at end - combineAnnotation_calls.add(new Object[] { st, refSeq, groupRef}); - modified = true; - continue; - } - else if (token.equalsIgnoreCase("ROWPROPERTIES")) - { - addRowProperties(al, st); - modified = true; - continue; - } - else if (token.equalsIgnoreCase(GRAPHLINE)) - { - // resolve at end - deferredAnnotation_calls.add(new Object[] { GRAPHLINE, st, refSeq, groupRef}); - modified = true; - continue; - } + else if (token.equalsIgnoreCase(COMBINE)) + { + // keep a record of current state and resolve groupRef at end + combineAnnotation_calls.add(new Object[] { st, refSeq, groupRef }); + modified = true; + continue; + } + else if (token.equalsIgnoreCase("ROWPROPERTIES")) + { + addRowProperties(al, st); + modified = true; + continue; + } + else if (token.equalsIgnoreCase(GRAPHLINE)) + { + // resolve at end + deferredAnnotation_calls + .add(new Object[] + { GRAPHLINE, st, refSeq, groupRef }); + modified = true; + continue; + } - else if (token.equalsIgnoreCase("SEQUENCE_REF")) + else if (token.equalsIgnoreCase("SEQUENCE_REF")) + { + if (st.hasMoreTokens()) { - if (st.hasMoreTokens()) + refSeq = al.findName(refSeqId = st.nextToken()); + if (refSeq == null) { - refSeq = al.findName(refSeqId = st.nextToken()); - if (refSeq == null) - { - refSeqId = null; - } - try - { - refSeqIndex = Integer.parseInt(st.nextToken()); - if (refSeqIndex < 1) - { - refSeqIndex = 1; - System.out - .println("WARNING: SEQUENCE_REF index must be > 0 in AnnotationFile"); - } - } catch (Exception ex) + refSeqId = null; + } + try + { + refSeqIndex = Integer.parseInt(st.nextToken()); + if (refSeqIndex < 1) { refSeqIndex = 1; + System.out.println( + "WARNING: SEQUENCE_REF index must be > 0 in AnnotationFile"); } - } - else + } catch (Exception ex) { - refSeq = null; - refSeqId = null; + refSeqIndex = 1; } - continue; } - else if (token.equalsIgnoreCase("GROUP_REF")) + else { - // Group references could be forward or backwards, so they are - // resolved after the whole file is read in - groupRef = null; - if (st.hasMoreTokens()) + refSeq = null; + refSeqId = null; + } + continue; + } + else if (token.equalsIgnoreCase("GROUP_REF")) + { + // Group references could be forward or backwards, so they are + // resolved after the whole file is read in + groupRef = null; + if (st.hasMoreTokens()) + { + groupRef = st.nextToken(); + if (groupRef.length() < 1) { - groupRef = st.nextToken(); - if (groupRef.length() < 1) - { - groupRef = null; // empty string - } - else + groupRef = null; // empty string + } + else + { + if (groupRefRows.get(groupRef) == null) { - if (groupRefRows.get(groupRef) == null) - { - groupRefRows.put(groupRef, new Vector()); - } + groupRefRows.put(groupRef, new Vector<>()); } } - continue; } - else if (token.equalsIgnoreCase("SEQUENCE_GROUP")) + continue; + } + else if (token.equalsIgnoreCase("SEQUENCE_GROUP")) + { + addGroup(al, st); + modified = true; + continue; + } + + else if (token.equalsIgnoreCase("PROPERTIES")) + { + addProperties(al, st); + modified = true; + continue; + } + + else if (token.equalsIgnoreCase("BELOW_ALIGNMENT")) + { + setBelowAlignment(al, st); + modified = true; + continue; + } + else if (token.equalsIgnoreCase("ALIGNMENT")) + { + addAlignmentDetails(al, st); + modified = true; + continue; + } + // else if (token.equalsIgnoreCase("VIEW_DEF")) + // { + // addOrSetView(al,st); + // modified = true; + // continue; + // } + else if (token.equalsIgnoreCase("VIEW_SETREF")) + { + if (refSeq != null) { - addGroup(al, st); - modified=true; - continue; + al.setSeqrep(refSeq); } - - else if (token.equalsIgnoreCase("PROPERTIES")) + modified = true; + continue; + } + else if (token.equalsIgnoreCase("VIEW_HIDECOLS")) + { + if (st.hasMoreTokens()) { - addProperties(al, st); - modified = true; - continue; + if (hidden == null) + { + hidden = new HiddenColumns(); + } + parseHideCols(hidden, st.nextToken()); } - - else if (token.equalsIgnoreCase("BELOW_ALIGNMENT")) + modified = true; + continue; + } + else if (token.equalsIgnoreCase("HIDE_INSERTIONS")) + { + SequenceI sr = refSeq == null ? al.getSeqrep() : refSeq; + if (sr == null) { - setBelowAlignment(al, st); - modified = true; - continue; + sr = al.getSequenceAt(0); } - else if (token.equalsIgnoreCase("ALIGNMENT")) + if (sr != null) { - addAlignmentDetails(al, st); - modified = true; - continue; + if (hidden == null) + { + System.err.println( + "Cannot process HIDE_INSERTIONS without an alignment view: Ignoring line: " + + line); + } + else + { + // consider deferring this till after the file has been parsed ? + hidden.hideList(sr.getInsertions()); + } } + modified = true; + continue; + } - // Parse out the annotation row - graphStyle = AlignmentAnnotation.getGraphValueFromString(token); - label = st.nextToken(); - - index = 0; - annotations = new Annotation[alWidth]; - description = null; - float score = Float.NaN; + // Parse out the annotation row + graphStyle = AlignmentAnnotation.getGraphValueFromString(token); + label = st.nextToken(); - if (st.hasMoreTokens()) - { - line = st.nextToken(); + index = 0; + annotations = new Annotation[alWidth]; + description = null; + float score = Float.NaN; - if (line.indexOf("|") == -1) - { - description = line; - if (st.hasMoreTokens()) - line = st.nextToken(); - } + if (st.hasMoreTokens()) + { + line = st.nextToken(); + if (line.indexOf("|") == -1) + { + description = line; if (st.hasMoreTokens()) { - // This must be the score - score = Float.valueOf(st.nextToken()).floatValue(); + line = st.nextToken(); } + } - st = new StringTokenizer(line, "|", true); + if (st.hasMoreTokens()) + { + // This must be the score + score = Float.valueOf(st.nextToken()).floatValue(); + } - boolean emptyColumn = true; - boolean onlyOneElement = (st.countTokens() == 1); + st = new StringTokenizer(line, "|", true); - while (st.hasMoreElements() && index < alWidth) - { - token = st.nextToken().trim(); + boolean emptyColumn = true; + boolean onlyOneElement = (st.countTokens() == 1); - if (onlyOneElement) - { - try - { - score = Float.valueOf(token).floatValue(); - break; - } catch (NumberFormatException ex) - { - } - } + while (st.hasMoreElements() && index < alWidth) + { + token = st.nextToken().trim(); - if (token.equals("|")) + if (onlyOneElement) + { + try { - if (emptyColumn) - { - index++; - } - - emptyColumn = true; - } - else + score = Float.valueOf(token).floatValue(); + break; + } catch (NumberFormatException ex) { - annotations[index++] = parseAnnotation(token, graphStyle); - emptyColumn = false; } } - } - - annotation = new AlignmentAnnotation(label, description, - (index == 0) ? null : annotations, 0, 0, graphStyle); - - annotation.score = score; - if (!overrideAutoAnnot - && autoAnnots.containsKey(autoAnnotsKey(annotation, refSeq, - groupRef))) - { - // skip - we've already got an automatic annotation of this type. - continue; - } - // otherwise add it! - if (refSeq != null) - { - - annotation.belowAlignment = false; - // make a copy of refSeq so we can find other matches in the alignment - SequenceI referedSeq = refSeq; - do + if (token.equals("|")) { - // copy before we do any mapping business. - // TODO: verify that undo/redo with 1:many sequence associated - // annotations can be undone correctly - AlignmentAnnotation ann = new AlignmentAnnotation(annotation); - annotation - .createSequenceMapping(referedSeq, refSeqIndex, false); - annotation.adjustForAlignment(); - referedSeq.addAlignmentAnnotation(annotation); - al.addAnnotation(annotation); - al.setAnnotationIndex(annotation, - al.getAlignmentAnnotation().length - - existingAnnotations - 1); - if (groupRef != null) + if (emptyColumn) { - ((Vector) groupRefRows.get(groupRef)).addElement(annotation); + index++; } - // and recover our virgin copy to use again if necessary. - annotation = ann; - } while (refSeqId != null - && (referedSeq = al.findName(referedSeq, refSeqId, true)) != null); + emptyColumn = true; + } + else + { + annotations[index++] = parseAnnotation(token, graphStyle); + emptyColumn = false; + } } - else - { + + } + + annotation = new AlignmentAnnotation(label, description, + (index == 0) ? null : annotations, 0, 0, graphStyle); + + annotation.score = score; + if (!overrideAutoAnnot && autoAnnots + .contains(autoAnnotsKey(annotation, refSeq, groupRef))) + { + // skip - we've already got an automatic annotation of this type. + continue; + } + // otherwise add it! + if (refSeq != null) + { + + annotation.belowAlignment = false; + // make a copy of refSeq so we can find other matches in the alignment + SequenceI referedSeq = refSeq; + do + { + // copy before we do any mapping business. + // TODO: verify that undo/redo with 1:many sequence associated + // annotations can be undone correctly + AlignmentAnnotation ann = new AlignmentAnnotation(annotation); + annotation.createSequenceMapping(referedSeq, refSeqIndex, false); + annotation.adjustForAlignment(); + referedSeq.addAlignmentAnnotation(annotation); al.addAnnotation(annotation); al.setAnnotationIndex(annotation, - al.getAlignmentAnnotation().length - existingAnnotations - - 1); + al.getAlignmentAnnotation().length + - existingAnnotationCount - 1); if (groupRef != null) { - ((Vector) groupRefRows.get(groupRef)).addElement(annotation); + groupRefRows.get(groupRef).addElement(annotation); } + // and recover our virgin copy to use again if necessary. + annotation = ann; + + } while (refSeqId != null && (referedSeq = al.findName(referedSeq, + refSeqId, true)) != null); + } + else + { + al.addAnnotation(annotation); + al.setAnnotationIndex(annotation, al.getAlignmentAnnotation().length + - existingAnnotationCount - 1); + if (groupRef != null) + { + groupRefRows.get(groupRef).addElement(annotation); } - // and set modification flag - modified = true; } - // Resolve the groupRefs - Hashtable groupRefLookup=new Hashtable(); - Enumeration en = groupRefRows.keys(); + // and set modification flag + modified = true; + } + // Resolve the groupRefs + Hashtable groupRefLookup = new Hashtable<>(); + Iterator en = groupRefRows.keySet().iterator(); - while (en.hasMoreElements()) + while (en.hasNext()) + { + groupRef = en.next(); + boolean matched = false; + // Resolve group: TODO: add a getGroupByName method to alignments + for (SequenceGroup theGroup : al.getGroups()) { - groupRef = (String) en.nextElement(); - boolean matched = false; - // Resolve group: TODO: add a getGroupByName method to alignments - for (SequenceGroup theGroup : al.getGroups()) + if (theGroup.getName().equals(groupRef)) { - if (theGroup.getName().equals(groupRef)) + if (matched) { - if (matched) - { - // TODO: specify and implement duplication of alignment annotation - // for multiple group references. - System.err - .println("Ignoring 1:many group reference mappings for group name '" - + groupRef + "'"); - } - else + // TODO: specify and implement duplication of alignment annotation + // for multiple group references. + System.err.println( + "Ignoring 1:many group reference mappings for group name '" + + groupRef + "'"); + } + else + { + matched = true; + Vector rowset = groupRefRows.get(groupRef); + groupRefLookup.put(groupRef, theGroup); + if (rowset != null && rowset.size() > 0) { - matched = true; - Vector rowset = (Vector) groupRefRows.get(groupRef); - groupRefLookup.put(groupRef, theGroup); - if (rowset != null && rowset.size() > 0) + AlignmentAnnotation alan = null; + for (int elm = 0, elmSize = rowset + .size(); elm < elmSize; elm++) { - AlignmentAnnotation alan = null; - for (int elm = 0, elmSize = rowset.size(); elm < elmSize; elm++) - { - alan = (AlignmentAnnotation) rowset.elementAt(elm); - alan.groupRef = theGroup; - } + alan = rowset.elementAt(elm); + alan.groupRef = theGroup; } } } } - ((Vector) groupRefRows.get(groupRef)).removeAllElements(); } - // process any deferred attribute settings for each context - for (Object[] _deferred_args : deferredAnnotation_calls) + groupRefRows.get(groupRef).removeAllElements(); + } + // process any deferred attribute settings for each context + for (Object[] _deferred_args : deferredAnnotation_calls) + { + if (_deferred_args[0] == GRAPHLINE) { - if (_deferred_args[0] == GRAPHLINE) + addLine(al, (StringTokenizer) _deferred_args[1], // st + (SequenceI) _deferred_args[2], // refSeq + (_deferred_args[3] == null) ? null + : groupRefLookup.get(_deferred_args[3]) // the + // reference + // group, or + // null + ); + } + } + + // finally, combine all the annotation rows within each context. + /** + * number of combine statements in this annotation file. Used to create new + * groups for combined annotation graphs without disturbing existing ones + */ + int combinecount = 0; + for (Object[] _combine_args : combineAnnotation_calls) + { + combineAnnotations(al, ++combinecount, + (StringTokenizer) _combine_args[0], // st + (SequenceI) _combine_args[1], // refSeq + (_combine_args[2] == null) ? null + : groupRefLookup.get(_combine_args[2]) // the reference + // group, + // or null + ); + } + + return modified; + } + + private void parseHideCols(HiddenColumns hidden, String nextToken) + { + StringTokenizer inval = new StringTokenizer(nextToken, ","); + while (inval.hasMoreTokens()) + { + String range = inval.nextToken().trim(); + int from, to = range.indexOf("-"); + if (to == -1) + { + from = to = Integer.parseInt(range); + if (from >= 0) + { + hidden.hideColumns(from, to); + } + } + else + { + from = Integer.parseInt(range.substring(0, to)); + if (to < range.length() - 1) { - addLine(al, - (StringTokenizer) _deferred_args[1], // st - (SequenceI) _deferred_args[2], // refSeq - (_deferred_args[3] == null) ? null : groupRefLookup - .get((String) _deferred_args[3]) // the reference - // group, or null - ); + to = Integer.parseInt(range.substring(to + 1)); + } + else + { + to = from; + } + if (from > 0 && to >= from) + { + hidden.hideColumns(from, to); } - } - - // finally, combine all the annotation rows within each context. - /** - * number of combine statements in this annotation file. Used to create new groups for combined annotation graphs without disturbing existing ones - */ - int combinecount = 0; - for (Object[] _combine_args:combineAnnotation_calls) { - combineAnnotations(al, - ++combinecount, - (StringTokenizer) _combine_args[0], // st - (SequenceI) _combine_args[1], // refSeq - (_combine_args[2]==null) ? null : groupRefLookup.get((String)_combine_args[2]) // the reference group, or null - ); } } - return modified; } - private Object autoAnnotsKey(AlignmentAnnotation annotation, + private String autoAnnotsKey(AlignmentAnnotation annotation, SequenceI refSeq, String groupRef) { return annotation.graph + "\t" + annotation.label + "\t" @@ -1019,29 +1214,20 @@ public class AnnotationFile Annotation parseAnnotation(String string, int graphStyle) { - boolean hasSymbols = (graphStyle == AlignmentAnnotation.NO_GRAPH); // don't - // do the - // glyph - // test - // if we - // don't - // want - // secondary - // structure + // don't do the glyph test if we don't want secondary structure + boolean hasSymbols = (graphStyle == AlignmentAnnotation.NO_GRAPH); String desc = null, displayChar = null; char ss = ' '; // secondaryStructure float value = 0; boolean parsedValue = false, dcset = false; // find colour here - java.awt.Color colour = null; + Color colour = null; int i = string.indexOf("["); int j = string.indexOf("]"); if (i > -1 && j > -1) { - UserColourScheme ucs = new UserColourScheme(); - - colour = ucs.getColourFromString(string.substring(i + 1, j)); + colour = ColorUtils.parseColourString(string.substring(i + 1, j)); if (i > 0 && string.charAt(i - 1) == ',') { // clip the preceding comma as well @@ -1094,9 +1280,9 @@ public class AnnotationFile displayChar = token; } } - if (hasSymbols - && (token.equals("H") || token.equals("E") - || token.equals("S") || token.equals(" "))) + if (hasSymbols && (token.length() == 1 + && "()<>[]{}AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz" + .contains(token))) { // Either this character represents a helix or sheet // or an integer which can be displayed @@ -1143,7 +1329,7 @@ public class AnnotationFile void colourAnnotations(AlignmentI al, String label, String colour) { - UserColourScheme ucs = new UserColourScheme(colour); + Color awtColour = ColorUtils.parseColourString(colour); Annotation[] annotations; for (int i = 0; i < al.getAlignmentAnnotation().length; i++) { @@ -1154,38 +1340,42 @@ public class AnnotationFile { if (annotations[j] != null) { - annotations[j].colour = ucs.findColour('A'); + annotations[j].colour = awtColour; } } } } } - void combineAnnotations(AlignmentI al, int combineCount, StringTokenizer st, SequenceI seqRef, SequenceGroup groupRef) + void combineAnnotations(AlignmentI al, int combineCount, + StringTokenizer st, SequenceI seqRef, SequenceGroup groupRef) { String group = st.nextToken(); // First make sure we are not overwriting the graphIndex - int graphGroup=0; + int graphGroup = 0; if (al.getAlignmentAnnotation() != null) { for (int i = 0; i < al.getAlignmentAnnotation().length; i++) { AlignmentAnnotation aa = al.getAlignmentAnnotation()[i]; - - if (aa.graphGroup>graphGroup) + + if (aa.graphGroup > graphGroup) { // try to number graphGroups in order of occurence. - graphGroup=aa.graphGroup+1; + graphGroup = aa.graphGroup + 1; } - if (aa.sequenceRef==seqRef && aa.groupRef==groupRef && aa.label.equalsIgnoreCase(group)) + if (aa.sequenceRef == seqRef && aa.groupRef == groupRef + && aa.label.equalsIgnoreCase(group)) { - if (aa.graphGroup>-1) + if (aa.graphGroup > -1) { graphGroup = aa.graphGroup; - } else { + } + else + { if (graphGroup <= combineCount) { - graphGroup=combineCount+1; + graphGroup = combineCount + 1; } aa.graphGroup = graphGroup; } @@ -1200,7 +1390,8 @@ public class AnnotationFile for (int i = 0; i < al.getAlignmentAnnotation().length; i++) { AlignmentAnnotation aa = al.getAlignmentAnnotation()[i]; - if (aa.sequenceRef==seqRef && aa.groupRef==groupRef && aa.label.equalsIgnoreCase(group)) + if (aa.sequenceRef == seqRef && aa.groupRef == groupRef + && aa.label.equalsIgnoreCase(group)) { aa.graphGroup = graphGroup; break; @@ -1210,38 +1401,44 @@ public class AnnotationFile } else { - System.err - .println("Couldn't combine annotations. None are added to alignment yet!"); + System.err.println( + "Couldn't combine annotations. None are added to alignment yet!"); } } - void addLine(AlignmentI al, StringTokenizer st, SequenceI seqRef, SequenceGroup groupRef) + void addLine(AlignmentI al, StringTokenizer st, SequenceI seqRef, + SequenceGroup groupRef) { String group = st.nextToken(); - AlignmentAnnotation annotation = null, alannot[] = al - .getAlignmentAnnotation(); - float value = new Float(st.nextToken()).floatValue(); + AlignmentAnnotation[] alannot = al.getAlignmentAnnotation(); + String nextToken = st.nextToken(); + float value = 0f; + try + { + value = Float.valueOf(nextToken); + } catch (NumberFormatException e) + { + System.err.println("line " + nlinesread + ": Threshold '" + nextToken + + "' invalid, setting to zero"); + } String label = st.hasMoreTokens() ? st.nextToken() : null; - java.awt.Color colour = null; + Color colour = null; if (st.hasMoreTokens()) { - UserColourScheme ucs = new UserColourScheme(st.nextToken()); - colour = ucs.findColour('A'); + colour = ColorUtils.parseColourString(st.nextToken()); } if (alannot != null) { for (int i = 0; i < alannot.length; i++) { - if (alannot[i].label.equalsIgnoreCase(group) && (seqRef==null || alannot[i].sequenceRef==seqRef) && (groupRef==null || alannot[i].groupRef==groupRef)) + if (alannot[i].label.equalsIgnoreCase(group) + && (seqRef == null || alannot[i].sequenceRef == seqRef) + && (groupRef == null || alannot[i].groupRef == groupRef)) { alannot[i].setThreshold(new GraphLine(value, label, colour)); } } } - if (annotation == null) - { - return; - } } void addGroup(AlignmentI al, StringTokenizer st) @@ -1271,8 +1468,8 @@ public class AnnotationFile } } catch (Exception e) { - System.err - .println("Couldn't parse Group Start or End Field as '*' or a valid column or sequence index: '" + System.err.println( + "Couldn't parse Group Start or End Field as '*' or a valid column or sequence index: '" + rng + "' - assuming alignment width for group."); // assume group is full width sg.setStartRes(0); @@ -1318,7 +1515,8 @@ public class AnnotationFile } else { - sg.addSequence(al.getSequenceAt(Integer.parseInt(tmp) - 1), false); + sg.addSequence(al.getSequenceAt(Integer.parseInt(tmp) - 1), + false); } } } @@ -1401,8 +1599,7 @@ public class AnnotationFile if (sg != null) { String keyValue, key, value; - ColourSchemeI def = sg.cs; - sg.cs = null; + ColourSchemeI def = sg.getColourScheme(); while (st.hasMoreTokens()) { keyValue = st.nextToken(); @@ -1415,7 +1612,10 @@ public class AnnotationFile } else if (key.equalsIgnoreCase("colour")) { - sg.cs = ColourSchemeProperty.getColour(al, value); + // TODO need to notify colourscheme of view reference once it is + // available + sg.cs.setColourScheme( + ColourSchemeProperty.getColourScheme(null, al, value)); } else if (key.equalsIgnoreCase("pidThreshold")) { @@ -1425,8 +1625,7 @@ public class AnnotationFile else if (key.equalsIgnoreCase("consThreshold")) { sg.cs.setConservationInc(Integer.parseInt(value)); - Conservation c = new Conservation("Group", - ResidueProperties.propHash, 3, sg.getSequences(null), + Conservation c = new Conservation("Group", sg.getSequences(null), sg.getStartRes(), sg.getEndRes() + 1); c.calculate(); @@ -1437,7 +1636,7 @@ public class AnnotationFile } else if (key.equalsIgnoreCase("outlineColour")) { - sg.setOutlineColour(new UserColourScheme(value).findColour('A')); + sg.setOutlineColour(ColorUtils.parseColourString(value)); } else if (key.equalsIgnoreCase("displayBoxes")) { @@ -1457,11 +1656,11 @@ public class AnnotationFile } else if (key.equalsIgnoreCase("textCol1")) { - sg.textColour = new UserColourScheme(value).findColour('A'); + sg.textColour = ColorUtils.parseColourString(value); } else if (key.equalsIgnoreCase("textCol2")) { - sg.textColour2 = new UserColourScheme(value).findColour('A'); + sg.textColour2 = ColorUtils.parseColourString(value); } else if (key.equalsIgnoreCase("textColThreshold")) { @@ -1469,9 +1668,8 @@ public class AnnotationFile } else if (key.equalsIgnoreCase("idColour")) { - // consider warning if colour doesn't resolve to a real colour - sg.setIdColour((def = new UserColourScheme(value)) - .findColour('A')); + Color idColour = ColorUtils.parseColourString(value); + sg.setIdColour(idColour == null ? Color.black : idColour); } else if (key.equalsIgnoreCase("hide")) { @@ -1485,9 +1683,9 @@ public class AnnotationFile } sg.recalcConservation(); } - if (sg.cs == null) + if (sg.getColourScheme() == null) { - sg.cs = def; + sg.setColourScheme(def); } } } @@ -1498,8 +1696,8 @@ public class AnnotationFile AlignmentAnnotation aa, ala[] = al.getAlignmentAnnotation(); if (ala == null) { - System.err - .print("Warning - no annotation to set below for sequence associated annotation:"); + System.err.print( + "Warning - no annotation to set below for sequence associated annotation:"); } while (st.hasMoreTokens()) { @@ -1547,6 +1745,10 @@ public class AnnotationFile */ public String printCSVAnnotations(AlignmentAnnotation[] annotations) { + if (annotations == null) + { + return ""; + } StringBuffer sp = new StringBuffer(); for (int i = 0; i < annotations.length; i++) { @@ -1571,4 +1773,22 @@ public class AnnotationFile } return sp.toString(); } + + public String printAnnotationsForView(AlignViewportI viewport) + { + return printAnnotations( + viewport.isShowAnnotation() + ? viewport.getAlignment().getAlignmentAnnotation() + : null, + viewport.getAlignment().getGroups(), + viewport.getAlignment().getProperties(), + viewport.getAlignment().getHiddenColumns(), + viewport.getAlignment(), null); + } + + public String printAnnotationsForAlignment(AlignmentI al) + { + return printAnnotations(al.getAlignmentAnnotation(), al.getGroups(), + al.getProperties(), null, al, null); + } }