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;
BufferedReader in) throws Exception
{
nlinesread = 0;
- ArrayList<Object[]> combineAnnotation_calls = new ArrayList<>();
- ArrayList<Object[]> deferredAnnotation_calls = new ArrayList<>();
+ List<Object[]> combineAnnotation_calls = new ArrayList<>();
+ List<Object[]> deferredAnnotation_calls = new ArrayList<>();
boolean modified = false;
String groupRef = null;
- Hashtable groupRefRows = new Hashtable();
-
- Hashtable autoAnnots = new Hashtable();
+ Map<String, Vector<AlignmentAnnotation>> groupRefRows = new HashMap<>();
+
+ Set<String> 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"))
- {
- addGroup(al, st);
- modified = true;
- continue;
}
+ 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("PROPERTIES"))
+ {
+ addProperties(al, st);
+ modified = true;
+ continue;
+ }
- else if (token.equalsIgnoreCase("BELOW_ALIGNMENT"))
+ 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)
{
- setBelowAlignment(al, st);
- modified = true;
- continue;
+ al.setSeqrep(refSeq);
}
- else if (token.equalsIgnoreCase("ALIGNMENT"))
+ modified = true;
+ continue;
+ }
+ else if (token.equalsIgnoreCase("VIEW_HIDECOLS"))
+ {
+ if (st.hasMoreTokens())
{
- 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)
+ if (hidden == null)
{
- al.setSeqrep(refSeq);
+ hidden = new HiddenColumns();
}
- modified = true;
- continue;
+ parseHideCols(hidden, st.nextToken());
}
- else if (token.equalsIgnoreCase("VIEW_HIDECOLS"))
+ modified = true;
+ continue;
+ }
+ else if (token.equalsIgnoreCase("HIDE_INSERTIONS"))
+ {
+ SequenceI sr = refSeq == null ? al.getSeqrep() : refSeq;
+ if (sr == null)
{
- if (st.hasMoreTokens())
- {
- if (hidden == null)
- {
- hidden = new HiddenColumns();
- }
- parseHideCols(hidden, st.nextToken());
- }
- modified = true;
- continue;
+ sr = al.getSequenceAt(0);
}
- else if (token.equalsIgnoreCase("HIDE_INSERTIONS"))
+ if (sr != null)
{
- SequenceI sr = refSeq == null ? al.getSeqrep() : refSeq;
- if (sr == null)
+ if (hidden == null)
{
- sr = al.getSequenceAt(0);
+ System.err.println(
+ "Cannot process HIDE_INSERTIONS without an alignment view: Ignoring line: "
+ + line);
}
- if (sr != null)
+ else
{
- 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());
- }
+ // consider deferring this till after the file has been parsed ?
+ hidden.hideList(sr.getInsertions());
}
- modified = true;
- continue;
}
+ 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<String, SequenceGroup> groupRefLookup = new Hashtable<>();
- Enumeration en = groupRefRows.keys();
+ // and set modification flag
+ modified = true;
+ }
+ // Resolve the groupRefs
+ Hashtable<String, SequenceGroup> groupRefLookup = new Hashtable<>();
+ Iterator<String> 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<AlignmentAnnotation> 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)
- {
- 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
+ groupRefRows.get(groupRef).removeAllElements();
+ }
+ // process any deferred attribute settings for each context
+ for (Object[] _deferred_args : deferredAnnotation_calls)
+ {
+ 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 Object autoAnnotsKey(AlignmentAnnotation annotation,
+ private String autoAnnotsKey(AlignmentAnnotation annotation,
SequenceI refSeq, String groupRef)
{
return annotation.graph + "\t" + annotation.label + "\t"