Merge branch 'master' of https://source.jalview.org/git/jalviewjs.git
[jalviewjs.git] / site / j2s / jalview / io / FeaturesFile.js
index f1f497c..c83bf08 100644 (file)
-Clazz.declarePackage ("jalview.io");\r
-Clazz.load (["jalview.io.AlignFile", "java.lang.Enum", "$.Exception"], "jalview.io.FeaturesFile", ["jalview.analysis.SequenceIdMatcher", "jalview.datamodel.AlignedCodonFrame", "$.SequenceDummy", "$.SequenceFeature", "jalview.jsdev.GenericFileAdapter", "jalview.schemes.GraduatedColor", "$.UserColourScheme", "jalview.util.Format", "$.MapList", "$.ParseHtmlBodyAndLinks", "java.awt.Color", "java.lang.Float", "$.StringBuffer", "java.util.ArrayList", "$.Arrays", "$.HashMap", "$.Hashtable", "$.StringTokenizer", "$.Vector"], function () {\r
-c$ = Clazz.decorateAsClass (function () {\r
-this.doGffSource = true;\r
-this.gffversion = 0;\r
-if (!Clazz.isClassDefined ("jalview.io.FeaturesFile.InvalidGFF3FieldException")) {\r
-jalview.io.FeaturesFile.$FeaturesFile$InvalidGFF3FieldException$ ();\r
-}\r
-this.lastmatchedAl = null;\r
-this.matcher = null;\r
-Clazz.instantialize (this, arguments);\r
-}, jalview.io, "FeaturesFile", jalview.io.AlignFile);\r
-Clazz.makeConstructor (c$, \r
-function () {\r
-Clazz.superConstructor (this, jalview.io.FeaturesFile, []);\r
-});\r
-Clazz.defineMethod (c$, "parse", \r
-function (align, colours, removeHTML) {\r
-return this.parse (align, colours, null, removeHTML, false);\r
-}, "jalview.datamodel.AlignmentI,java.util.Hashtable,~B");\r
-Clazz.defineMethod (c$, "parse", \r
-function (align, colours, removeHTML, relaxedIdMatching) {\r
-return this.parse (align, colours, null, removeHTML, relaxedIdMatching);\r
-}, "jalview.datamodel.AlignmentI,java.util.Map,~B,~B");\r
-Clazz.defineMethod (c$, "parse", \r
-function (align, colours, featureLink, removeHTML) {\r
-return this.parse (align, colours, featureLink, removeHTML, false);\r
-}, "jalview.datamodel.AlignmentI,java.util.Map,java.util.Map,~B");\r
-Clazz.defineMethod (c$, "parse", \r
-function (align, colours, featureLink, removeHTML, relaxedIdmatching) {\r
-var line = null;\r
-try {\r
-var seq = null;\r
-var newseqs =  new java.util.ArrayList ();\r
-var type;\r
-var desc;\r
-var token = null;\r
-var index;\r
-var start;\r
-var end;\r
-var score;\r
-var st;\r
-var sf;\r
-var featureGroup = null;\r
-var groupLink = null;\r
-var typeLink =  new java.util.Hashtable ();\r
-var GFFFile = true;\r
-var gffProps =  new java.util.HashMap ();\r
-while ((line = this.nextLine ()) != null) {\r
-if (line.startsWith ("#")) {\r
-if (line.startsWith ("##")) {\r
-this.processGffPragma (line, gffProps, align, newseqs);\r
-line = "";\r
-}continue;\r
-}st =  new java.util.StringTokenizer (line, "\t");\r
-if (st.countTokens () == 1) {\r
-if (line.trim ().equalsIgnoreCase ("GFF")) {\r
-GFFFile = true;\r
-continue;\r
-}}if (st.countTokens () > 1 && st.countTokens () < 4) {\r
-GFFFile = false;\r
-type = st.nextToken ();\r
-if (type.equalsIgnoreCase ("startgroup")) {\r
-featureGroup = st.nextToken ();\r
-if (st.hasMoreElements ()) {\r
-groupLink = st.nextToken ();\r
-featureLink.put (featureGroup, groupLink);\r
-}} else if (type.equalsIgnoreCase ("endgroup")) {\r
-st.nextToken ();\r
-featureGroup = null;\r
-groupLink = null;\r
-} else {\r
-var colour = null;\r
-var colscheme = st.nextToken ();\r
-if (colscheme.indexOf ("|") > -1 || colscheme.trim ().equalsIgnoreCase ("label")) {\r
-var gcol =  new java.util.StringTokenizer (colscheme, "|", true);\r
-var threshtype = -1;\r
-var min = 1.4E-45;\r
-var max = 3.4028235E38;\r
-var threshval = NaN;\r
-var labelCol = false;\r
-var mincol = gcol.nextToken ();\r
-if (mincol === "|") {\r
-System.err.println ("Expected either 'label' or a colour specification in the line: " + line);\r
-continue;\r
-}var maxcol = null;\r
-if (mincol.toLowerCase ().indexOf ("label") == 0) {\r
-labelCol = true;\r
-mincol = (gcol.hasMoreTokens () ? gcol.nextToken () : null);\r
-mincol = (gcol.hasMoreTokens () ? gcol.nextToken () : null);\r
-}var abso = null;\r
-var minval;\r
-var maxval;\r
-if (mincol != null) {\r
-if (mincol.equals ("|")) {\r
-mincol = "";\r
-} else {\r
-gcol.nextToken ();\r
-}maxcol = gcol.nextToken ();\r
-if (maxcol.equals ("|")) {\r
-maxcol = "";\r
-} else {\r
-gcol.nextToken ();\r
-}abso = gcol.nextToken ();\r
-gcol.nextToken ();\r
-if (abso.toLowerCase ().indexOf ("abso") != 0) {\r
-minval = abso;\r
-abso = null;\r
-} else {\r
-minval = gcol.nextToken ();\r
-gcol.nextToken ();\r
-}maxval = gcol.nextToken ();\r
-if (gcol.hasMoreTokens ()) {\r
-gcol.nextToken ();\r
-}try {\r
-if (minval.length > 0) {\r
-min =  new Float (minval).floatValue ();\r
-}} catch (e) {\r
-if (Clazz.exceptionOf (e, Exception)) {\r
-System.err.println ("Couldn't parse the minimum value for graduated colour for type (" + colscheme + ") - did you misspell 'auto' for the optional automatic colour switch ?");\r
-e.printStackTrace ();\r
-} else {\r
-throw e;\r
-}\r
-}\r
-try {\r
-if (maxval.length > 0) {\r
-max =  new Float (maxval).floatValue ();\r
-}} catch (e) {\r
-if (Clazz.exceptionOf (e, Exception)) {\r
-System.err.println ("Couldn't parse the maximum value for graduated colour for type (" + colscheme + ")");\r
-e.printStackTrace ();\r
-} else {\r
-throw e;\r
-}\r
-}\r
-} else {\r
-mincol = "FFFFFF";\r
-maxcol = "000000";\r
-}try {\r
-colour =  new jalview.schemes.GraduatedColor ( new jalview.schemes.UserColourScheme (mincol).findColour ('A'),  new jalview.schemes.UserColourScheme (maxcol).findColour ('A'), min, max);\r
-} catch (e) {\r
-if (Clazz.exceptionOf (e, Exception)) {\r
-System.err.println ("Couldn't parse the graduated colour scheme (" + colscheme + ")");\r
-e.printStackTrace ();\r
-} else {\r
-throw e;\r
-}\r
-}\r
-if (colour != null) {\r
-(colour).setColourByLabel (labelCol);\r
-(colour).setAutoScaled (abso == null);\r
-var ttype = null;\r
-var tval = null;\r
-if (gcol.hasMoreTokens ()) {\r
-ttype = gcol.nextToken ();\r
-if (ttype.toLowerCase ().startsWith ("below")) {\r
-(colour).setThreshType (0);\r
-} else if (ttype.toLowerCase ().startsWith ("above")) {\r
-(colour).setThreshType (1);\r
-} else {\r
-(colour).setThreshType (-1);\r
-if (!ttype.toLowerCase ().startsWith ("no")) {\r
-System.err.println ("Ignoring unrecognised threshold type : " + ttype);\r
-}}}if ((colour).getThreshType () != -1) {\r
-try {\r
-gcol.nextToken ();\r
-tval = gcol.nextToken ();\r
-(colour).setThresh ( new Float (tval).floatValue ());\r
-} catch (e) {\r
-if (Clazz.exceptionOf (e, Exception)) {\r
-System.err.println ("Couldn't parse threshold value as a float: (" + tval + ")");\r
-e.printStackTrace ();\r
-} else {\r
-throw e;\r
-}\r
-}\r
-}if (gcol.hasMoreTokens ()) {\r
-System.err.println ("Ignoring additional tokens in parameters in graduated colour specification\n");\r
-while (gcol.hasMoreTokens ()) {\r
-System.err.println ("|" + gcol.nextToken ());\r
-}\r
-System.err.println ("\n");\r
-}}} else {\r
-var ucs =  new jalview.schemes.UserColourScheme (colscheme);\r
-colour = ucs.findColour ('A');\r
-}if (colour != null) {\r
-colours.put (type, colour);\r
-}if (st.hasMoreElements ()) {\r
-var link = st.nextToken ();\r
-typeLink.put (type, link);\r
-if (featureLink == null) {\r
-featureLink =  new java.util.Hashtable ();\r
-}featureLink.put (type, link);\r
-}}continue;\r
-}var seqId = "";\r
-while (st.hasMoreElements ()) {\r
-if (GFFFile) {\r
-seqId = token = st.nextToken ();\r
-seq = this.findName (align, seqId, relaxedIdmatching, newseqs);\r
-if (seq != null) {\r
-desc = st.nextToken ();\r
-var group = null;\r
-if (this.doGffSource && desc.indexOf (' ') == -1) {\r
-group =  String.instantialize (desc);\r
-}type = st.nextToken ();\r
-try {\r
-var stt = st.nextToken ();\r
-if (stt.length == 0 || stt.equals ("-")) {\r
-start = 0;\r
-} else {\r
-start = Integer.parseInt (stt);\r
-}} catch (ex) {\r
-if (Clazz.exceptionOf (ex, NumberFormatException)) {\r
-start = 0;\r
-} else {\r
-throw ex;\r
-}\r
-}\r
-try {\r
-var stt = st.nextToken ();\r
-if (stt.length == 0 || stt.equals ("-")) {\r
-end = 0;\r
-} else {\r
-end = Integer.parseInt (stt);\r
-}} catch (ex) {\r
-if (Clazz.exceptionOf (ex, NumberFormatException)) {\r
-end = 0;\r
-} else {\r
-throw ex;\r
-}\r
-}\r
-if (end == 0) {\r
-start = 0;\r
-}try {\r
-score =  new Float (st.nextToken ()).floatValue ();\r
-} catch (ex) {\r
-if (Clazz.exceptionOf (ex, NumberFormatException)) {\r
-score = 0;\r
-} else {\r
-throw ex;\r
-}\r
-}\r
-sf =  new jalview.datamodel.SequenceFeature (type, desc, start, end, score, group);\r
-try {\r
-sf.setValue ("STRAND", st.nextToken ());\r
-sf.setValue ("FRAME", st.nextToken ());\r
-} catch (ex) {\r
-if (Clazz.exceptionOf (ex, Exception)) {\r
-} else {\r
-throw ex;\r
-}\r
-}\r
-if (st.hasMoreTokens ()) {\r
-var attributes =  new StringBuffer ();\r
-var sep = false;\r
-while (st.hasMoreTokens ()) {\r
-attributes.append ((sep ? "\t" : "") + st.nextElement ());\r
-sep = true;\r
-}\r
-sf.setValue ("ATTRIBUTES", attributes.toString ());\r
-}if (this.processOrAddSeqFeature (align, newseqs, seq, sf, GFFFile, relaxedIdmatching)) {\r
-while ((seq = align.findName (seq, seqId, true)) != null) {\r
-seq.addSequenceFeature ( new jalview.datamodel.SequenceFeature (sf));\r
-}\r
-}break;\r
-}}if (GFFFile && seq == null) {\r
-desc = token;\r
-} else {\r
-desc = st.nextToken ();\r
-}if (!st.hasMoreTokens ()) {\r
-System.err.println ("DEBUG: Run out of tokens when trying to identify the destination for the feature.. giving up.");\r
-return false;\r
-}token = st.nextToken ();\r
-if (!token.equals ("ID_NOT_SPECIFIED")) {\r
-seq = this.findName (align, seqId = token, relaxedIdmatching, null);\r
-st.nextToken ();\r
-} else {\r
-seqId = null;\r
-try {\r
-index = Integer.parseInt (st.nextToken ());\r
-seq = align.getSequenceAt (index);\r
-} catch (ex) {\r
-if (Clazz.exceptionOf (ex, NumberFormatException)) {\r
-seq = null;\r
-} else {\r
-throw ex;\r
-}\r
-}\r
-}if (seq == null) {\r
-System.out.println ("Sequence not found: " + line);\r
-break;\r
-}start = Integer.parseInt (st.nextToken ());\r
-end = Integer.parseInt (st.nextToken ());\r
-type = st.nextToken ();\r
-if (!colours.containsKey (type)) {\r
-var ucs =  new jalview.schemes.UserColourScheme (type);\r
-colours.put (type, ucs.findColour ('A'));\r
-}sf =  new jalview.datamodel.SequenceFeature (type, desc, "", start, end, featureGroup);\r
-if (st.hasMoreTokens ()) {\r
-try {\r
-score =  new Float (st.nextToken ()).floatValue ();\r
-} catch (ex) {\r
-if (Clazz.exceptionOf (ex, NumberFormatException)) {\r
-score = 0;\r
-} else {\r
-throw ex;\r
-}\r
-}\r
-sf.setScore (score);\r
-}if (groupLink != null && removeHTML) {\r
-sf.addLink (groupLink);\r
-sf.description += "%LINK%";\r
-}if (typeLink.containsKey (type) && removeHTML) {\r
-sf.addLink (typeLink.get (type).toString ());\r
-sf.description += "%LINK%";\r
-}this.parseDescriptionHTML (sf, removeHTML);\r
-seq.addSequenceFeature (sf);\r
-while (seqId != null && (seq = align.findName (seq, seqId, false)) != null) {\r
-seq.addSequenceFeature ( new jalview.datamodel.SequenceFeature (sf));\r
-}\r
-GFFFile = false;\r
-}\r
-}\r
-this.resetMatcher ();\r
-} catch (ex) {\r
-if (Clazz.exceptionOf (ex, Exception)) {\r
-this.warningMessage = ((this.warningMessage == null) ? "" : this.warningMessage) + "Parsing error at\n" + line;\r
-System.out.println ("Error parsing feature file: " + ex + "\n" + line);\r
-ex.printStackTrace (System.err);\r
-this.resetMatcher ();\r
-return false;\r
-} else {\r
-throw ex;\r
-}\r
-}\r
-return true;\r
-}, "jalview.datamodel.AlignmentI,java.util.Map,java.util.Map,~B,~B");\r
-Clazz.defineMethod (c$, "processGffPragma", \r
- function (line, gffProps, align, newseqs) {\r
-var spacepos = line.indexOf (' ');\r
-var pragma = spacepos == -1 ? line.substring (2).trim () : line.substring (2, spacepos);\r
-var gffpragma = jalview.io.FeaturesFile.GFFPRAGMA.get (pragma.toLowerCase ());\r
-if (gffpragma == null) {\r
-return;\r
-}switch (gffpragma) {\r
-case jalview.io.FeaturesFile.GffPragmas.gff_version:\r
-try {\r
-this.gffversion = Integer.parseInt (line.substring (spacepos + 1));\r
-} finally {\r
-}\r
-break;\r
-case jalview.io.FeaturesFile.GffPragmas.feature_ontology:\r
-break;\r
-case jalview.io.FeaturesFile.GffPragmas.attribute_ontology:\r
-break;\r
-case jalview.io.FeaturesFile.GffPragmas.source_ontology:\r
-break;\r
-case jalview.io.FeaturesFile.GffPragmas.species_build:\r
-break;\r
-case jalview.io.FeaturesFile.GffPragmas.hash:\r
-break;\r
-case jalview.io.FeaturesFile.GffPragmas.fasta:\r
-this.process_as_fasta (align, newseqs);\r
-break;\r
-default:\r
-System.err.println ("Ignoring unknown pragma:\n" + line);\r
-}\r
-}, "~S,java.util.Map,jalview.datamodel.AlignmentI,java.util.ArrayList");\r
-Clazz.defineMethod (c$, "process_as_fasta", \r
- function (align, newseqs) {\r
-try {\r
-this.mark ();\r
-} catch (q) {\r
-if (Clazz.exceptionOf (q, java.io.IOException)) {\r
-} else {\r
-throw q;\r
-}\r
-}\r
-var parser = jalview.jsdev.GenericFileAdapter.getFile ("FastaFile", []);\r
-var includedseqs = parser.getSeqs ();\r
-var smatcher =  new jalview.analysis.SequenceIdMatcher (newseqs);\r
-for (var p = 0, pSize = includedseqs.size (); p < pSize; p++) {\r
-var dummyseq = smatcher.findIdMatch (includedseqs.get (p));\r
-if (dummyseq != null) {\r
-var mseq = includedseqs.get (p);\r
-if (Clazz.instanceOf (dummyseq, jalview.datamodel.SequenceDummy)) {\r
-(dummyseq).become (mseq);\r
-includedseqs.set (p, dummyseq);\r
-}}}\r
-for (var seq, $seq = includedseqs.iterator (); $seq.hasNext () && ((seq = $seq.next ()) || true);) {\r
-align.addSequence (seq);\r
-}\r
-}, "jalview.datamodel.AlignmentI,java.util.List");\r
-Clazz.defineMethod (c$, "processOrAddSeqFeature", \r
-function (align, newseqs, seq, sf, gFFFile, relaxedIdMatching) {\r
-var attr = sf.getValue ("ATTRIBUTES");\r
-var add = true;\r
-if (gFFFile && attr != null) {\r
-var nattr = 8;\r
-for (var attset, $attset = 0, $$attset = attr.$plit ("\t"); $attset < $$attset.length && ((attset = $$attset[$attset]) || true); $attset++) {\r
-if (attset == null || attset.trim ().length == 0) {\r
-continue;\r
-}nattr++;\r
-var set =  new java.util.HashMap ();\r
-for (var pair, $pair = 0, $$pair = attset.trim ().$plit (";"); $pair < $$pair.length && ((pair = $$pair[$pair]) || true); $pair++) {\r
-pair = pair.trim ();\r
-if (pair.length == 0) {\r
-continue;\r
-}var eqpos = pair.indexOf ('=');\r
-var sppos = pair.indexOf (' ');\r
-var key = null;\r
-var value = null;\r
-if (sppos > -1 && (eqpos == -1 || sppos < eqpos)) {\r
-key = pair.substring (0, sppos);\r
-value = pair.substring (sppos + 1);\r
-} else {\r
-if (eqpos > -1 && (sppos == -1 || eqpos < sppos)) {\r
-key = pair.substring (0, eqpos);\r
-value = pair.substring (eqpos + 1);\r
-} else {\r
-key = pair;\r
-}}if (key != null) {\r
-var vals = set.get (key);\r
-if (vals == null) {\r
-vals =  new java.util.ArrayList ();\r
-set.put (key, vals);\r
-}if (value != null) {\r
-vals.add (value.trim ());\r
-}}}\r
-try {\r
-add = new Boolean (add & this.processGffKey (set, nattr, seq, sf, align, newseqs, relaxedIdMatching)).valueOf ();\r
-} catch (ivfe) {\r
-if (Clazz.exceptionOf (ivfe, jalview.io.FeaturesFile.InvalidGFF3FieldException)) {\r
-System.err.println (ivfe);\r
-} else {\r
-throw ivfe;\r
-}\r
-}\r
-}\r
-}if (add) {\r
-seq.addSequenceFeature (sf);\r
-}return add;\r
-}, "jalview.datamodel.AlignmentI,java.util.List,jalview.datamodel.SequenceI,jalview.datamodel.SequenceFeature,~B,~B");\r
-Clazz.defineMethod (c$, "processGffKey", \r
-function (set, nattr, seq, sf, align, newseqs, relaxedIdMatching) {\r
-var attr;\r
-if (sf.getType ().equals ("similarity")) {\r
-var strand = sf.getStrand ();\r
-var querySeq = this.findNames (align, newseqs, relaxedIdMatching, set.get (attr = "Query"));\r
-if (querySeq == null || querySeq.size () != 1) {\r
-throw Clazz.innerTypeInstance (jalview.io.FeaturesFile.InvalidGFF3FieldException, this, null, attr, set, "Expecting exactly one sequence in Query field (got " + set.get (attr) + ")");\r
-}if (set.containsKey (attr = "Align")) {\r
-var alco =  new jalview.datamodel.AlignedCodonFrame ();\r
-var codonmapping = this.constructCodonMappingFromAlign (set, attr, strand);\r
-alco.addMap (seq, querySeq.get (0), codonmapping);\r
-align.addCodonFrame (alco);\r
-return false;\r
-}}return true;\r
-}, "java.util.Map,~N,jalview.datamodel.SequenceI,jalview.datamodel.SequenceFeature,jalview.datamodel.AlignmentI,java.util.List,~B");\r
-Clazz.defineMethod (c$, "constructCodonMappingFromAlign", \r
- function (set, attr, strand) {\r
-if (strand == 0) {\r
-throw Clazz.innerTypeInstance (jalview.io.FeaturesFile.InvalidGFF3FieldException, this, null, attr, set, "Invalid strand for a codon mapping (cannot be 0)");\r
-}var fromrange =  new java.util.ArrayList ();\r
-var torange =  new java.util.ArrayList ();\r
-var lastppos = 0;\r
-var lastpframe = 0;\r
-for (var range, $range = set.get (attr).iterator (); $range.hasNext () && ((range = $range.next ()) || true);) {\r
-var ints =  new java.util.ArrayList ();\r
-var st =  new java.util.StringTokenizer (range, " ");\r
-while (st.hasMoreTokens ()) {\r
-var num = st.nextToken ();\r
-try {\r
-ints.add ( new Integer (num));\r
-} catch (nfe) {\r
-if (Clazz.exceptionOf (nfe, NumberFormatException)) {\r
-throw Clazz.innerTypeInstance (jalview.io.FeaturesFile.InvalidGFF3FieldException, this, null, attr, set, "Invalid number in field " + num);\r
-} else {\r
-throw nfe;\r
-}\r
-}\r
-}\r
-if (ints.size () != 3) {\r
-throw Clazz.innerTypeInstance (jalview.io.FeaturesFile.InvalidGFF3FieldException, this, null, attr, set, "Invalid number of fields for this attribute (" + ints.size () + ")");\r
-}fromrange.add ( new Integer (ints.get (0).intValue ()));\r
-fromrange.add ( new Integer (ints.get (0).intValue () + strand * ints.get (2).intValue ()));\r
-if (ints.get (1).equals (new Integer (lastppos)) && lastpframe > 0) {\r
-lastppos += (ints.get (2)).intValue () / 3;\r
-lastpframe = (ints.get (2)).intValue () % 3;\r
-torange.set (torange.size () - 1,  new Integer (lastppos));\r
-} else {\r
-torange.add (ints.get (1));\r
-lastppos = (ints.get (1)).intValue () + (ints.get (2)).intValue () / 3;\r
-lastpframe = (ints.get (2)).intValue () % 3;\r
-torange.add ( new Integer (lastppos));\r
-}}\r
-if (fromrange.size () % 2 == 1) {\r
-throw Clazz.innerTypeInstance (jalview.io.FeaturesFile.InvalidGFF3FieldException, this, null, attr, set, "Couldn't parse the DNA alignment range correctly");\r
-}if (torange.size () % 2 == 1) {\r
-throw Clazz.innerTypeInstance (jalview.io.FeaturesFile.InvalidGFF3FieldException, this, null, attr, set, "Couldn't parse the protein alignment range correctly");\r
-}var frommap =  Clazz.newIntArray (fromrange.size (), 0);\r
-var tomap =  Clazz.newIntArray (torange.size (), 0);\r
-var p = 0;\r
-for (var ip, $ip = fromrange.iterator (); $ip.hasNext () && ((ip = $ip.next ()) || true);) {\r
-frommap[p++] = ip.intValue ();\r
-}\r
-p = 0;\r
-for (var ip, $ip = torange.iterator (); $ip.hasNext () && ((ip = $ip.next ()) || true);) {\r
-tomap[p++] = ip.intValue ();\r
-}\r
-return  new jalview.util.MapList (frommap, tomap, 3, 1);\r
-}, "java.util.Map,~S,~N");\r
-Clazz.defineMethod (c$, "findNames", \r
- function (align, newseqs, relaxedIdMatching, list) {\r
-var found =  new java.util.ArrayList ();\r
-for (var seqId, $seqId = list.iterator (); $seqId.hasNext () && ((seqId = $seqId.next ()) || true);) {\r
-var seq = this.findName (align, seqId, relaxedIdMatching, newseqs);\r
-if (seq != null) {\r
-found.add (seq);\r
-}}\r
-return found;\r
-}, "jalview.datamodel.AlignmentI,java.util.List,~B,java.util.List");\r
-Clazz.defineMethod (c$, "resetMatcher", \r
- function () {\r
-this.lastmatchedAl = null;\r
-this.matcher = null;\r
-});\r
-Clazz.defineMethod (c$, "findName", \r
- function (align, seqId, relaxedIdMatching, newseqs) {\r
-var match = null;\r
-if (relaxedIdMatching) {\r
-if (this.lastmatchedAl !== align) {\r
-this.matcher =  new jalview.analysis.SequenceIdMatcher ((this.lastmatchedAl = align).getSequencesArray ());\r
-if (newseqs != null) {\r
-this.matcher.addAll (newseqs);\r
-}}match = this.matcher.findIdMatch (seqId);\r
-} else {\r
-match = align.findName (seqId, true);\r
-if (match == null && newseqs != null) {\r
-for (var m, $m = newseqs.iterator (); $m.hasNext () && ((m = $m.next ()) || true);) {\r
-if (seqId.equals (m.getName ())) {\r
-return m;\r
-}}\r
-}}if (match == null && newseqs != null) {\r
-match =  new jalview.datamodel.SequenceDummy (seqId);\r
-if (relaxedIdMatching) {\r
-this.matcher.addAll (java.util.Arrays.asList ( Clazz.newArray (-1, [match])));\r
-}newseqs.add (match);\r
-}return match;\r
-}, "jalview.datamodel.AlignmentI,~S,~B,java.util.List");\r
-Clazz.defineMethod (c$, "parseDescriptionHTML", \r
-function (sf, removeHTML) {\r
-if (sf.getDescription () == null) {\r
-return;\r
-}var parsed =  new jalview.util.ParseHtmlBodyAndLinks (sf.getDescription (), removeHTML, this.newline);\r
-sf.description = (removeHTML) ? parsed.getNonHtmlContent () : sf.description;\r
-for (var link, $link = parsed.getLinks ().iterator (); $link.hasNext () && ((link = $link.next ()) || true);) {\r
-sf.addLink (link);\r
-}\r
-}, "jalview.datamodel.SequenceFeature,~B");\r
-Clazz.defineMethod (c$, "printJalviewFormat", \r
-function (seqs, visible) {\r
-return this.printJalviewFormat (seqs, visible, true, true);\r
-}, "~A,java.util.Map");\r
-Clazz.defineMethod (c$, "printJalviewFormat", \r
-function (seqs, visible, visOnly, nonpos) {\r
-var out =  new StringBuffer ();\r
-var next;\r
-var featuresGen = false;\r
-if (visOnly && !nonpos && (visible == null || visible.size () < 1)) {\r
-return "No Features Visible";\r
-}if (visible != null && visOnly) {\r
-var en = visible.keySet ().iterator ();\r
-var type;\r
-var color;\r
-while (en.hasNext ()) {\r
-type = en.next ().toString ();\r
-if (Clazz.instanceOf (visible.get (type), jalview.schemes.GraduatedColor)) {\r
-var gc = visible.get (type);\r
-color = (gc.isColourByLabel () ? "label|" : "") + jalview.util.Format.getHexString (gc.getMinColor ()) + "|" + jalview.util.Format.getHexString (gc.getMaxColor ()) + (gc.isAutoScale () ? "|" : "|abso|") + gc.getMin () + "|" + gc.getMax () + "|";\r
-if (gc.getThreshType () != -1) {\r
-if (gc.getThreshType () == 0) {\r
-color += "below";\r
-} else {\r
-if (gc.getThreshType () != 1) {\r
-System.err.println ("WARNING: Unsupported threshold type (" + gc.getThreshType () + ") : Assuming 'above'");\r
-}color += "above";\r
-}color += "|" + gc.getThresh ();\r
-} else {\r
-color += "none";\r
-}} else if (Clazz.instanceOf (visible.get (type), java.awt.Color)) {\r
-color = jalview.util.Format.getHexString (visible.get (type));\r
-} else {\r
-color = jalview.util.Format.getHexString ( new java.awt.Color (Integer.parseInt (visible.get (type).toString ())));\r
-}out.append (type);\r
-out.append ("\t");\r
-out.append (color);\r
-out.append (this.newline);\r
-}\r
-}var groups =  new java.util.Vector ();\r
-var groupIndex = 0;\r
-var isnonpos = false;\r
-for (var i = 0; i < seqs.length; i++) {\r
-next = seqs[i].getSequenceFeatures ();\r
-if (next != null) {\r
-for (var j = 0; j < next.length; j++) {\r
-isnonpos = next[j].begin == 0 && next[j].end == 0;\r
-if ((!nonpos && isnonpos) || (!isnonpos && visOnly && !visible.containsKey (next[j].type))) {\r
-continue;\r
-}if (next[j].featureGroup != null && !groups.contains (next[j].featureGroup)) {\r
-groups.addElement (next[j].featureGroup);\r
-}}\r
-}}\r
-var group = null;\r
-do {\r
-if (groups.size () > 0 && groupIndex < groups.size ()) {\r
-group = groups.elementAt (groupIndex).toString ();\r
-out.append (this.newline);\r
-out.append ("STARTGROUP\t");\r
-out.append (group);\r
-out.append (this.newline);\r
-} else {\r
-group = null;\r
-}for (var i = 0; i < seqs.length; i++) {\r
-next = seqs[i].getSequenceFeatures ();\r
-if (next != null) {\r
-for (var j = 0; j < next.length; j++) {\r
-isnonpos = next[j].begin == 0 && next[j].end == 0;\r
-if ((!nonpos && isnonpos) || (!isnonpos && visOnly && !visible.containsKey (next[j].type))) {\r
-continue;\r
-}if (group != null && (next[j].featureGroup == null || !next[j].featureGroup.equals (group))) {\r
-continue;\r
-}if (group == null && next[j].featureGroup != null) {\r
-continue;\r
-}featuresGen = true;\r
-if (next[j].description == null || next[j].description.equals ("")) {\r
-out.append (next[j].type + "\t");\r
-} else {\r
-if (next[j].links != null && next[j].getDescription ().indexOf ("<html>") == -1) {\r
-out.append ("<html>");\r
-}out.append (next[j].description + " ");\r
-if (next[j].links != null) {\r
-for (var l = 0; l < next[j].links.size (); l++) {\r
-var label = next[j].links.elementAt (l).toString ();\r
-var href = label.substring (label.indexOf ("|") + 1);\r
-label = label.substring (0, label.indexOf ("|"));\r
-if (next[j].description.indexOf (href) == -1) {\r
-out.append ("<a href=\"" + href + "\">" + label + "</a>");\r
-}}\r
-if (next[j].getDescription ().indexOf ("</html>") == -1) {\r
-out.append ("</html>");\r
-}}out.append ("\t");\r
-}out.append (seqs[i].getName ());\r
-out.append ("\t-1\t");\r
-out.append ("" + next[j].begin);\r
-out.append ("\t");\r
-out.append ("" + next[j].end);\r
-out.append ("\t");\r
-out.append (next[j].type);\r
-if (!Float.isNaN (next[j].score)) {\r
-out.append ("\t");\r
-out.append (next[j].score);\r
-}out.append (this.newline);\r
-}\r
-}}\r
-if (group != null) {\r
-out.append ("ENDGROUP\t");\r
-out.append (group);\r
-out.append (this.newline);\r
-groupIndex++;\r
-} else {\r
-break;\r
-}} while (groupIndex < groups.size () + 1);\r
-if (!featuresGen) {\r
-return "No Features Visible";\r
-}return out.toString ();\r
-}, "~A,java.util.Map,~B,~B");\r
-Clazz.defineMethod (c$, "printGFFFormat", \r
-function (seqs, visible) {\r
-return this.printGFFFormat (seqs, visible, true, true);\r
-}, "~A,java.util.Map");\r
-Clazz.defineMethod (c$, "printGFFFormat", \r
-function (seqs, visible, visOnly, nonpos) {\r
-var out =  new StringBuffer ();\r
-var next;\r
-var source;\r
-var isnonpos;\r
-for (var i = 0; i < seqs.length; i++) {\r
-if (seqs[i].getSequenceFeatures () != null) {\r
-next = seqs[i].getSequenceFeatures ();\r
-for (var j = 0; j < next.length; j++) {\r
-isnonpos = next[j].begin == 0 && next[j].end == 0;\r
-if ((!nonpos && isnonpos) || (!isnonpos && visOnly && !visible.containsKey (next[j].type))) {\r
-continue;\r
-}source = next[j].featureGroup;\r
-if (source == null) {\r
-source = next[j].getDescription ();\r
-}out.append (seqs[i].getName ());\r
-out.append ("\t");\r
-out.append (source);\r
-out.append ("\t");\r
-out.append (next[j].type);\r
-out.append ("\t");\r
-out.append ("" + next[j].begin);\r
-out.append ("\t");\r
-out.append ("" + next[j].end);\r
-out.append ("\t");\r
-out.append (next[j].score);\r
-out.append ("\t");\r
-if (next[j].getValue ("STRAND") != null) {\r
-out.append (next[j].getValue ("STRAND"));\r
-out.append ("\t");\r
-} else {\r
-out.append (".\t");\r
-}if (next[j].getValue ("FRAME") != null) {\r
-out.append (next[j].getValue ("FRAME"));\r
-} else {\r
-out.append (".");\r
-}if (next[j].getValue ("ATTRIBUTES") != null) {\r
-out.append (next[j].getValue ("ATTRIBUTES"));\r
-}out.append (this.newline);\r
-}\r
-}}\r
-return out.toString ();\r
-}, "~A,java.util.Map,~B,~B");\r
-Clazz.defineMethod (c$, "parse", \r
-function () {\r
-});\r
-Clazz.overrideMethod (c$, "print", \r
-function () {\r
-return "USE printGFFFormat() or printJalviewFormat()";\r
-});\r
-c$.$FeaturesFile$InvalidGFF3FieldException$ = function () {\r
-Clazz.pu$h(self.c$);\r
-c$ = Clazz.decorateAsClass (function () {\r
-Clazz.prepareCallback (this, arguments);\r
-this.field = null;\r
-this.value = null;\r
-Clazz.instantialize (this, arguments);\r
-}, jalview.io.FeaturesFile, "InvalidGFF3FieldException", Exception);\r
-Clazz.makeConstructor (c$, \r
-function (a, b, c) {\r
-Clazz.superConstructor (this, jalview.io.FeaturesFile.InvalidGFF3FieldException, [c + " (Field was " + a + " and value was " + b.get (a).toString ()]);\r
-this.field = a;\r
-this.value = b.get (a).toString ();\r
-}, "~S,java.util.Map,~S");\r
-c$ = Clazz.p0p ();\r
-};\r
-Clazz.pu$h(self.c$);\r
-c$ = Clazz.declareType (jalview.io.FeaturesFile, "GffPragmas", Enum);\r
-Clazz.defineEnumConstant (c$, "gff_version", 0, []);\r
-Clazz.defineEnumConstant (c$, "sequence_region", 1, []);\r
-Clazz.defineEnumConstant (c$, "feature_ontology", 2, []);\r
-Clazz.defineEnumConstant (c$, "attribute_ontology", 3, []);\r
-Clazz.defineEnumConstant (c$, "source_ontology", 4, []);\r
-Clazz.defineEnumConstant (c$, "species_build", 5, []);\r
-Clazz.defineEnumConstant (c$, "fasta", 6, []);\r
-Clazz.defineEnumConstant (c$, "hash", 7, []);\r
-c$ = Clazz.p0p ();\r
-Clazz.defineStatics (c$,\r
-"GFFPRAGMA", null);\r
-{\r
-jalview.io.FeaturesFile.GFFPRAGMA =  new java.util.HashMap ();\r
-jalview.io.FeaturesFile.GFFPRAGMA.put ("sequence-region", jalview.io.FeaturesFile.GffPragmas.sequence_region);\r
-jalview.io.FeaturesFile.GFFPRAGMA.put ("feature-ontology", jalview.io.FeaturesFile.GffPragmas.feature_ontology);\r
-jalview.io.FeaturesFile.GFFPRAGMA.put ("#", jalview.io.FeaturesFile.GffPragmas.hash);\r
-jalview.io.FeaturesFile.GFFPRAGMA.put ("fasta", jalview.io.FeaturesFile.GffPragmas.fasta);\r
-jalview.io.FeaturesFile.GFFPRAGMA.put ("species-build", jalview.io.FeaturesFile.GffPragmas.species_build);\r
-jalview.io.FeaturesFile.GFFPRAGMA.put ("source-ontology", jalview.io.FeaturesFile.GffPragmas.source_ontology);\r
-jalview.io.FeaturesFile.GFFPRAGMA.put ("attribute-ontology", jalview.io.FeaturesFile.GffPragmas.attribute_ontology);\r
-}});\r
+Clazz.declarePackage ("jalview.io");
+Clazz.load (["jalview.io.AlignFile", "java.lang.Enum", "$.Exception"], "jalview.io.FeaturesFile", ["jalview.analysis.SequenceIdMatcher", "jalview.datamodel.AlignedCodonFrame", "$.SequenceDummy", "$.SequenceFeature", "jalview.jsdev.GenericFileAdapter", "jalview.schemes.GraduatedColor", "$.UserColourScheme", "jalview.util.Format", "$.MapList", "$.ParseHtmlBodyAndLinks", "java.awt.Color", "java.lang.Float", "$.StringBuffer", "java.util.ArrayList", "$.Arrays", "$.HashMap", "$.Hashtable", "$.StringTokenizer", "$.Vector"], function () {
+c$ = Clazz.decorateAsClass (function () {
+this.doGffSource = true;
+this.gffversion = 0;
+if (!Clazz.isClassDefined ("jalview.io.FeaturesFile.InvalidGFF3FieldException")) {
+jalview.io.FeaturesFile.$FeaturesFile$InvalidGFF3FieldException$ ();
+}
+this.lastmatchedAl = null;
+this.matcher = null;
+Clazz.instantialize (this, arguments);
+}, jalview.io, "FeaturesFile", jalview.io.AlignFile);
+Clazz.makeConstructor (c$, 
+function () {
+Clazz.superConstructor (this, jalview.io.FeaturesFile, []);
+});
+Clazz.defineMethod (c$, "parse", 
+function (align, colours, removeHTML) {
+return this.parse (align, colours, null, removeHTML, false);
+}, "jalview.datamodel.AlignmentI,java.util.Hashtable,~B");
+Clazz.defineMethod (c$, "parse", 
+function (align, colours, removeHTML, relaxedIdMatching) {
+return this.parse (align, colours, null, removeHTML, relaxedIdMatching);
+}, "jalview.datamodel.AlignmentI,java.util.Map,~B,~B");
+Clazz.defineMethod (c$, "parse", 
+function (align, colours, featureLink, removeHTML) {
+return this.parse (align, colours, featureLink, removeHTML, false);
+}, "jalview.datamodel.AlignmentI,java.util.Map,java.util.Map,~B");
+Clazz.defineMethod (c$, "parse", 
+function (align, colours, featureLink, removeHTML, relaxedIdmatching) {
+var line = null;
+try {
+var seq = null;
+var newseqs =  new java.util.ArrayList ();
+var type;
+var desc;
+var token = null;
+var index;
+var start;
+var end;
+var score;
+var st;
+var sf;
+var featureGroup = null;
+var groupLink = null;
+var typeLink =  new java.util.Hashtable ();
+var GFFFile = true;
+var gffProps =  new java.util.HashMap ();
+while ((line = this.nextLine ()) != null) {
+if (line.startsWith ("#")) {
+if (line.startsWith ("##")) {
+this.processGffPragma (line, gffProps, align, newseqs);
+line = "";
+}continue;
+}st =  new java.util.StringTokenizer (line, "\t");
+if (st.countTokens () == 1) {
+if (line.trim ().equalsIgnoreCase ("GFF")) {
+GFFFile = true;
+continue;
+}}if (st.countTokens () > 1 && st.countTokens () < 4) {
+GFFFile = false;
+type = st.nextToken ();
+if (type.equalsIgnoreCase ("startgroup")) {
+featureGroup = st.nextToken ();
+if (st.hasMoreElements ()) {
+groupLink = st.nextToken ();
+featureLink.put (featureGroup, groupLink);
+}} else if (type.equalsIgnoreCase ("endgroup")) {
+st.nextToken ();
+featureGroup = null;
+groupLink = null;
+} else {
+var colour = null;
+var colscheme = st.nextToken ();
+if (colscheme.indexOf ("|") > -1 || colscheme.trim ().equalsIgnoreCase ("label")) {
+var gcol =  new java.util.StringTokenizer (colscheme, "|", true);
+var threshtype = -1;
+var min = 1.4E-45;
+var max = 3.4028235E38;
+var threshval = NaN;
+var labelCol = false;
+var mincol = gcol.nextToken ();
+if (mincol === "|") {
+System.err.println ("Expected either 'label' or a colour specification in the line: " + line);
+continue;
+}var maxcol = null;
+if (mincol.toLowerCase ().indexOf ("label") == 0) {
+labelCol = true;
+mincol = (gcol.hasMoreTokens () ? gcol.nextToken () : null);
+mincol = (gcol.hasMoreTokens () ? gcol.nextToken () : null);
+}var abso = null;
+var minval;
+var maxval;
+if (mincol != null) {
+if (mincol.equals ("|")) {
+mincol = "";
+} else {
+gcol.nextToken ();
+}maxcol = gcol.nextToken ();
+if (maxcol.equals ("|")) {
+maxcol = "";
+} else {
+gcol.nextToken ();
+}abso = gcol.nextToken ();
+gcol.nextToken ();
+if (abso.toLowerCase ().indexOf ("abso") != 0) {
+minval = abso;
+abso = null;
+} else {
+minval = gcol.nextToken ();
+gcol.nextToken ();
+}maxval = gcol.nextToken ();
+if (gcol.hasMoreTokens ()) {
+gcol.nextToken ();
+}try {
+if (minval.length > 0) {
+min =  new Float (minval).floatValue ();
+}} catch (e) {
+if (Clazz.exceptionOf (e, Exception)) {
+System.err.println ("Couldn't parse the minimum value for graduated colour for type (" + colscheme + ") - did you misspell 'auto' for the optional automatic colour switch ?");
+e.printStackTrace ();
+} else {
+throw e;
+}
+}
+try {
+if (maxval.length > 0) {
+max =  new Float (maxval).floatValue ();
+}} catch (e) {
+if (Clazz.exceptionOf (e, Exception)) {
+System.err.println ("Couldn't parse the maximum value for graduated colour for type (" + colscheme + ")");
+e.printStackTrace ();
+} else {
+throw e;
+}
+}
+} else {
+mincol = "FFFFFF";
+maxcol = "000000";
+}try {
+colour =  new jalview.schemes.GraduatedColor ( new jalview.schemes.UserColourScheme (mincol).findColour ('A'),  new jalview.schemes.UserColourScheme (maxcol).findColour ('A'), min, max);
+} catch (e) {
+if (Clazz.exceptionOf (e, Exception)) {
+System.err.println ("Couldn't parse the graduated colour scheme (" + colscheme + ")");
+e.printStackTrace ();
+} else {
+throw e;
+}
+}
+if (colour != null) {
+(colour).setColourByLabel (labelCol);
+(colour).setAutoScaled (abso == null);
+var ttype = null;
+var tval = null;
+if (gcol.hasMoreTokens ()) {
+ttype = gcol.nextToken ();
+if (ttype.toLowerCase ().startsWith ("below")) {
+(colour).setThreshType (0);
+} else if (ttype.toLowerCase ().startsWith ("above")) {
+(colour).setThreshType (1);
+} else {
+(colour).setThreshType (-1);
+if (!ttype.toLowerCase ().startsWith ("no")) {
+System.err.println ("Ignoring unrecognised threshold type : " + ttype);
+}}}if ((colour).getThreshType () != -1) {
+try {
+gcol.nextToken ();
+tval = gcol.nextToken ();
+(colour).setThresh ( new Float (tval).floatValue ());
+} catch (e) {
+if (Clazz.exceptionOf (e, Exception)) {
+System.err.println ("Couldn't parse threshold value as a float: (" + tval + ")");
+e.printStackTrace ();
+} else {
+throw e;
+}
+}
+}if (gcol.hasMoreTokens ()) {
+System.err.println ("Ignoring additional tokens in parameters in graduated colour specification\n");
+while (gcol.hasMoreTokens ()) {
+System.err.println ("|" + gcol.nextToken ());
+}
+System.err.println ("\n");
+}}} else {
+var ucs =  new jalview.schemes.UserColourScheme (colscheme);
+colour = ucs.findColour ('A');
+}if (colour != null) {
+colours.put (type, colour);
+}if (st.hasMoreElements ()) {
+var link = st.nextToken ();
+typeLink.put (type, link);
+if (featureLink == null) {
+featureLink =  new java.util.Hashtable ();
+}featureLink.put (type, link);
+}}continue;
+}var seqId = "";
+while (st.hasMoreElements ()) {
+if (GFFFile) {
+seqId = token = st.nextToken ();
+seq = this.findName (align, seqId, relaxedIdmatching, newseqs);
+if (seq != null) {
+desc = st.nextToken ();
+var group = null;
+if (this.doGffSource && desc.indexOf (' ') == -1) {
+group =  String.instantialize (desc);
+}type = st.nextToken ();
+try {
+var stt = st.nextToken ();
+if (stt.length == 0 || stt.equals ("-")) {
+start = 0;
+} else {
+start = Integer.parseInt (stt);
+}} catch (ex) {
+if (Clazz.exceptionOf (ex, NumberFormatException)) {
+start = 0;
+} else {
+throw ex;
+}
+}
+try {
+var stt = st.nextToken ();
+if (stt.length == 0 || stt.equals ("-")) {
+end = 0;
+} else {
+end = Integer.parseInt (stt);
+}} catch (ex) {
+if (Clazz.exceptionOf (ex, NumberFormatException)) {
+end = 0;
+} else {
+throw ex;
+}
+}
+if (end == 0) {
+start = 0;
+}try {
+score =  new Float (st.nextToken ()).floatValue ();
+} catch (ex) {
+if (Clazz.exceptionOf (ex, NumberFormatException)) {
+score = 0;
+} else {
+throw ex;
+}
+}
+sf =  new jalview.datamodel.SequenceFeature (type, desc, start, end, score, group);
+try {
+sf.setValue ("STRAND", st.nextToken ());
+sf.setValue ("FRAME", st.nextToken ());
+} catch (ex) {
+if (Clazz.exceptionOf (ex, Exception)) {
+} else {
+throw ex;
+}
+}
+if (st.hasMoreTokens ()) {
+var attributes =  new StringBuffer ();
+var sep = false;
+while (st.hasMoreTokens ()) {
+attributes.append ((sep ? "\t" : "") + st.nextElement ());
+sep = true;
+}
+sf.setValue ("ATTRIBUTES", attributes.toString ());
+}if (this.processOrAddSeqFeature (align, newseqs, seq, sf, GFFFile, relaxedIdmatching)) {
+while ((seq = align.findName (seq, seqId, true)) != null) {
+seq.addSequenceFeature ( new jalview.datamodel.SequenceFeature (sf));
+}
+}break;
+}}if (GFFFile && seq == null) {
+desc = token;
+} else {
+desc = st.nextToken ();
+}if (!st.hasMoreTokens ()) {
+System.err.println ("DEBUG: Run out of tokens when trying to identify the destination for the feature.. giving up.");
+return false;
+}token = st.nextToken ();
+if (!token.equals ("ID_NOT_SPECIFIED")) {
+seq = this.findName (align, seqId = token, relaxedIdmatching, null);
+st.nextToken ();
+} else {
+seqId = null;
+try {
+index = Integer.parseInt (st.nextToken ());
+seq = align.getSequenceAt (index);
+} catch (ex) {
+if (Clazz.exceptionOf (ex, NumberFormatException)) {
+seq = null;
+} else {
+throw ex;
+}
+}
+}if (seq == null) {
+System.out.println ("Sequence not found: " + line);
+break;
+}start = Integer.parseInt (st.nextToken ());
+end = Integer.parseInt (st.nextToken ());
+type = st.nextToken ();
+if (!colours.containsKey (type)) {
+var ucs =  new jalview.schemes.UserColourScheme (type);
+colours.put (type, ucs.findColour ('A'));
+}sf =  new jalview.datamodel.SequenceFeature (type, desc, "", start, end, featureGroup);
+if (st.hasMoreTokens ()) {
+try {
+score =  new Float (st.nextToken ()).floatValue ();
+} catch (ex) {
+if (Clazz.exceptionOf (ex, NumberFormatException)) {
+score = 0;
+} else {
+throw ex;
+}
+}
+sf.setScore (score);
+}if (groupLink != null && removeHTML) {
+sf.addLink (groupLink);
+sf.description += "%LINK%";
+}if (typeLink.containsKey (type) && removeHTML) {
+sf.addLink (typeLink.get (type).toString ());
+sf.description += "%LINK%";
+}this.parseDescriptionHTML (sf, removeHTML);
+seq.addSequenceFeature (sf);
+while (seqId != null && (seq = align.findName (seq, seqId, false)) != null) {
+seq.addSequenceFeature ( new jalview.datamodel.SequenceFeature (sf));
+}
+GFFFile = false;
+}
+}
+this.resetMatcher ();
+} catch (ex) {
+if (Clazz.exceptionOf (ex, Exception)) {
+this.warningMessage = ((this.warningMessage == null) ? "" : this.warningMessage) + "Parsing error at\n" + line;
+System.out.println ("Error parsing feature file: " + ex + "\n" + line);
+ex.printStackTrace (System.err);
+this.resetMatcher ();
+return false;
+} else {
+throw ex;
+}
+}
+return true;
+}, "jalview.datamodel.AlignmentI,java.util.Map,java.util.Map,~B,~B");
+Clazz.defineMethod (c$, "processGffPragma", 
+ function (line, gffProps, align, newseqs) {
+var spacepos = line.indexOf (' ');
+var pragma = spacepos == -1 ? line.substring (2).trim () : line.substring (2, spacepos);
+var gffpragma = jalview.io.FeaturesFile.GFFPRAGMA.get (pragma.toLowerCase ());
+if (gffpragma == null) {
+return;
+}switch (gffpragma) {
+case jalview.io.FeaturesFile.GffPragmas.gff_version:
+try {
+this.gffversion = Integer.parseInt (line.substring (spacepos + 1));
+} finally {
+}
+break;
+case jalview.io.FeaturesFile.GffPragmas.feature_ontology:
+break;
+case jalview.io.FeaturesFile.GffPragmas.attribute_ontology:
+break;
+case jalview.io.FeaturesFile.GffPragmas.source_ontology:
+break;
+case jalview.io.FeaturesFile.GffPragmas.species_build:
+break;
+case jalview.io.FeaturesFile.GffPragmas.hash:
+break;
+case jalview.io.FeaturesFile.GffPragmas.fasta:
+this.process_as_fasta (align, newseqs);
+break;
+default:
+System.err.println ("Ignoring unknown pragma:\n" + line);
+}
+}, "~S,java.util.Map,jalview.datamodel.AlignmentI,java.util.ArrayList");
+Clazz.defineMethod (c$, "process_as_fasta", 
+ function (align, newseqs) {
+try {
+this.mark ();
+} catch (q) {
+if (Clazz.exceptionOf (q, java.io.IOException)) {
+} else {
+throw q;
+}
+}
+var parser = jalview.jsdev.GenericFileAdapter.getFile ("FastaFile", []);
+var includedseqs = parser.getSeqs ();
+var smatcher =  new jalview.analysis.SequenceIdMatcher (newseqs);
+for (var p = 0, pSize = includedseqs.size (); p < pSize; p++) {
+var dummyseq = smatcher.findIdMatch (includedseqs.get (p));
+if (dummyseq != null) {
+var mseq = includedseqs.get (p);
+if (Clazz.instanceOf (dummyseq, jalview.datamodel.SequenceDummy)) {
+(dummyseq).become (mseq);
+includedseqs.set (p, dummyseq);
+}}}
+for (var seq, $seq = includedseqs.iterator (); $seq.hasNext () && ((seq = $seq.next ()) || true);) {
+align.addSequence (seq);
+}
+}, "jalview.datamodel.AlignmentI,java.util.List");
+Clazz.defineMethod (c$, "processOrAddSeqFeature", 
+function (align, newseqs, seq, sf, gFFFile, relaxedIdMatching) {
+var attr = sf.getValue ("ATTRIBUTES");
+var add = true;
+if (gFFFile && attr != null) {
+var nattr = 8;
+for (var attset, $attset = 0, $$attset = attr.$plit ("\t"); $attset < $$attset.length && ((attset = $$attset[$attset]) || true); $attset++) {
+if (attset == null || attset.trim ().length == 0) {
+continue;
+}nattr++;
+var set =  new java.util.HashMap ();
+for (var pair, $pair = 0, $$pair = attset.trim ().$plit (";"); $pair < $$pair.length && ((pair = $$pair[$pair]) || true); $pair++) {
+pair = pair.trim ();
+if (pair.length == 0) {
+continue;
+}var eqpos = pair.indexOf ('=');
+var sppos = pair.indexOf (' ');
+var key = null;
+var value = null;
+if (sppos > -1 && (eqpos == -1 || sppos < eqpos)) {
+key = pair.substring (0, sppos);
+value = pair.substring (sppos + 1);
+} else {
+if (eqpos > -1 && (sppos == -1 || eqpos < sppos)) {
+key = pair.substring (0, eqpos);
+value = pair.substring (eqpos + 1);
+} else {
+key = pair;
+}}if (key != null) {
+var vals = set.get (key);
+if (vals == null) {
+vals =  new java.util.ArrayList ();
+set.put (key, vals);
+}if (value != null) {
+vals.add (value.trim ());
+}}}
+try {
+add = new Boolean (add & this.processGffKey (set, nattr, seq, sf, align, newseqs, relaxedIdMatching)).valueOf ();
+} catch (ivfe) {
+if (Clazz.exceptionOf (ivfe, jalview.io.FeaturesFile.InvalidGFF3FieldException)) {
+System.err.println (ivfe);
+} else {
+throw ivfe;
+}
+}
+}
+}if (add) {
+seq.addSequenceFeature (sf);
+}return add;
+}, "jalview.datamodel.AlignmentI,java.util.List,jalview.datamodel.SequenceI,jalview.datamodel.SequenceFeature,~B,~B");
+Clazz.defineMethod (c$, "processGffKey", 
+function (set, nattr, seq, sf, align, newseqs, relaxedIdMatching) {
+var attr;
+if (sf.getType ().equals ("similarity")) {
+var strand = sf.getStrand ();
+var querySeq = this.findNames (align, newseqs, relaxedIdMatching, set.get (attr = "Query"));
+if (querySeq == null || querySeq.size () != 1) {
+throw Clazz.innerTypeInstance (jalview.io.FeaturesFile.InvalidGFF3FieldException, this, null, attr, set, "Expecting exactly one sequence in Query field (got " + set.get (attr) + ")");
+}if (set.containsKey (attr = "Align")) {
+var alco =  new jalview.datamodel.AlignedCodonFrame ();
+var codonmapping = this.constructCodonMappingFromAlign (set, attr, strand);
+alco.addMap (seq, querySeq.get (0), codonmapping);
+align.addCodonFrame (alco);
+return false;
+}}return true;
+}, "java.util.Map,~N,jalview.datamodel.SequenceI,jalview.datamodel.SequenceFeature,jalview.datamodel.AlignmentI,java.util.List,~B");
+Clazz.defineMethod (c$, "constructCodonMappingFromAlign", 
+ function (set, attr, strand) {
+if (strand == 0) {
+throw Clazz.innerTypeInstance (jalview.io.FeaturesFile.InvalidGFF3FieldException, this, null, attr, set, "Invalid strand for a codon mapping (cannot be 0)");
+}var fromrange =  new java.util.ArrayList ();
+var torange =  new java.util.ArrayList ();
+var lastppos = 0;
+var lastpframe = 0;
+for (var range, $range = set.get (attr).iterator (); $range.hasNext () && ((range = $range.next ()) || true);) {
+var ints =  new java.util.ArrayList ();
+var st =  new java.util.StringTokenizer (range, " ");
+while (st.hasMoreTokens ()) {
+var num = st.nextToken ();
+try {
+ints.add ( new Integer (num));
+} catch (nfe) {
+if (Clazz.exceptionOf (nfe, NumberFormatException)) {
+throw Clazz.innerTypeInstance (jalview.io.FeaturesFile.InvalidGFF3FieldException, this, null, attr, set, "Invalid number in field " + num);
+} else {
+throw nfe;
+}
+}
+}
+if (ints.size () != 3) {
+throw Clazz.innerTypeInstance (jalview.io.FeaturesFile.InvalidGFF3FieldException, this, null, attr, set, "Invalid number of fields for this attribute (" + ints.size () + ")");
+}fromrange.add ( new Integer (ints.get (0).intValue ()));
+fromrange.add ( new Integer (ints.get (0).intValue () + strand * ints.get (2).intValue ()));
+if (ints.get (1).equals (new Integer (lastppos)) && lastpframe > 0) {
+lastppos += (ints.get (2)).intValue () / 3;
+lastpframe = (ints.get (2)).intValue () % 3;
+torange.set (torange.size () - 1,  new Integer (lastppos));
+} else {
+torange.add (ints.get (1));
+lastppos = (ints.get (1)).intValue () + (ints.get (2)).intValue () / 3;
+lastpframe = (ints.get (2)).intValue () % 3;
+torange.add ( new Integer (lastppos));
+}}
+if (fromrange.size () % 2 == 1) {
+throw Clazz.innerTypeInstance (jalview.io.FeaturesFile.InvalidGFF3FieldException, this, null, attr, set, "Couldn't parse the DNA alignment range correctly");
+}if (torange.size () % 2 == 1) {
+throw Clazz.innerTypeInstance (jalview.io.FeaturesFile.InvalidGFF3FieldException, this, null, attr, set, "Couldn't parse the protein alignment range correctly");
+}var frommap =  Clazz.newIntArray (fromrange.size (), 0);
+var tomap =  Clazz.newIntArray (torange.size (), 0);
+var p = 0;
+for (var ip, $ip = fromrange.iterator (); $ip.hasNext () && ((ip = $ip.next ()) || true);) {
+frommap[p++] = ip.intValue ();
+}
+p = 0;
+for (var ip, $ip = torange.iterator (); $ip.hasNext () && ((ip = $ip.next ()) || true);) {
+tomap[p++] = ip.intValue ();
+}
+return  new jalview.util.MapList (frommap, tomap, 3, 1);
+}, "java.util.Map,~S,~N");
+Clazz.defineMethod (c$, "findNames", 
+ function (align, newseqs, relaxedIdMatching, list) {
+var found =  new java.util.ArrayList ();
+for (var seqId, $seqId = list.iterator (); $seqId.hasNext () && ((seqId = $seqId.next ()) || true);) {
+var seq = this.findName (align, seqId, relaxedIdMatching, newseqs);
+if (seq != null) {
+found.add (seq);
+}}
+return found;
+}, "jalview.datamodel.AlignmentI,java.util.List,~B,java.util.List");
+Clazz.defineMethod (c$, "resetMatcher", 
+ function () {
+this.lastmatchedAl = null;
+this.matcher = null;
+});
+Clazz.defineMethod (c$, "findName", 
+ function (align, seqId, relaxedIdMatching, newseqs) {
+var match = null;
+if (relaxedIdMatching) {
+if (this.lastmatchedAl !== align) {
+this.matcher =  new jalview.analysis.SequenceIdMatcher ((this.lastmatchedAl = align).getSequencesArray ());
+if (newseqs != null) {
+this.matcher.addAll (newseqs);
+}}match = this.matcher.findIdMatch (seqId);
+} else {
+match = align.findName (seqId, true);
+if (match == null && newseqs != null) {
+for (var m, $m = newseqs.iterator (); $m.hasNext () && ((m = $m.next ()) || true);) {
+if (seqId.equals (m.getName ())) {
+return m;
+}}
+}}if (match == null && newseqs != null) {
+match =  new jalview.datamodel.SequenceDummy (seqId);
+if (relaxedIdMatching) {
+this.matcher.addAll (java.util.Arrays.asList ( Clazz.newArray (-1, [match])));
+}newseqs.add (match);
+}return match;
+}, "jalview.datamodel.AlignmentI,~S,~B,java.util.List");
+Clazz.defineMethod (c$, "parseDescriptionHTML", 
+function (sf, removeHTML) {
+if (sf.getDescription () == null) {
+return;
+}var parsed =  new jalview.util.ParseHtmlBodyAndLinks (sf.getDescription (), removeHTML, this.newline);
+sf.description = (removeHTML) ? parsed.getNonHtmlContent () : sf.description;
+for (var link, $link = parsed.getLinks ().iterator (); $link.hasNext () && ((link = $link.next ()) || true);) {
+sf.addLink (link);
+}
+}, "jalview.datamodel.SequenceFeature,~B");
+Clazz.defineMethod (c$, "printJalviewFormat", 
+function (seqs, visible) {
+return this.printJalviewFormat (seqs, visible, true, true);
+}, "~A,java.util.Map");
+Clazz.defineMethod (c$, "printJalviewFormat", 
+function (seqs, visible, visOnly, nonpos) {
+var out =  new StringBuffer ();
+var next;
+var featuresGen = false;
+if (visOnly && !nonpos && (visible == null || visible.size () < 1)) {
+return "No Features Visible";
+}if (visible != null && visOnly) {
+var en = visible.keySet ().iterator ();
+var type;
+var color;
+while (en.hasNext ()) {
+type = en.next ().toString ();
+if (Clazz.instanceOf (visible.get (type), jalview.schemes.GraduatedColor)) {
+var gc = visible.get (type);
+color = (gc.isColourByLabel () ? "label|" : "") + jalview.util.Format.getHexString (gc.getMinColor ()) + "|" + jalview.util.Format.getHexString (gc.getMaxColor ()) + (gc.isAutoScale () ? "|" : "|abso|") + gc.getMin () + "|" + gc.getMax () + "|";
+if (gc.getThreshType () != -1) {
+if (gc.getThreshType () == 0) {
+color += "below";
+} else {
+if (gc.getThreshType () != 1) {
+System.err.println ("WARNING: Unsupported threshold type (" + gc.getThreshType () + ") : Assuming 'above'");
+}color += "above";
+}color += "|" + gc.getThresh ();
+} else {
+color += "none";
+}} else if (Clazz.instanceOf (visible.get (type), java.awt.Color)) {
+color = jalview.util.Format.getHexString (visible.get (type));
+} else {
+color = jalview.util.Format.getHexString ( new java.awt.Color (Integer.parseInt (visible.get (type).toString ())));
+}out.append (type);
+out.append ("\t");
+out.append (color);
+out.append (this.newline);
+}
+}var groups =  new java.util.Vector ();
+var groupIndex = 0;
+var isnonpos = false;
+for (var i = 0; i < seqs.length; i++) {
+next = seqs[i].getSequenceFeatures ();
+if (next != null) {
+for (var j = 0; j < next.length; j++) {
+isnonpos = next[j].begin == 0 && next[j].end == 0;
+if ((!nonpos && isnonpos) || (!isnonpos && visOnly && !visible.containsKey (next[j].type))) {
+continue;
+}if (next[j].featureGroup != null && !groups.contains (next[j].featureGroup)) {
+groups.addElement (next[j].featureGroup);
+}}
+}}
+var group = null;
+do {
+if (groups.size () > 0 && groupIndex < groups.size ()) {
+group = groups.elementAt (groupIndex).toString ();
+out.append (this.newline);
+out.append ("STARTGROUP\t");
+out.append (group);
+out.append (this.newline);
+} else {
+group = null;
+}for (var i = 0; i < seqs.length; i++) {
+next = seqs[i].getSequenceFeatures ();
+if (next != null) {
+for (var j = 0; j < next.length; j++) {
+isnonpos = next[j].begin == 0 && next[j].end == 0;
+if ((!nonpos && isnonpos) || (!isnonpos && visOnly && !visible.containsKey (next[j].type))) {
+continue;
+}if (group != null && (next[j].featureGroup == null || !next[j].featureGroup.equals (group))) {
+continue;
+}if (group == null && next[j].featureGroup != null) {
+continue;
+}featuresGen = true;
+if (next[j].description == null || next[j].description.equals ("")) {
+out.append (next[j].type + "\t");
+} else {
+if (next[j].links != null && next[j].getDescription ().indexOf ("<html>") == -1) {
+out.append ("<html>");
+}out.append (next[j].description + " ");
+if (next[j].links != null) {
+for (var l = 0; l < next[j].links.size (); l++) {
+var label = next[j].links.elementAt (l).toString ();
+var href = label.substring (label.indexOf ("|") + 1);
+label = label.substring (0, label.indexOf ("|"));
+if (next[j].description.indexOf (href) == -1) {
+out.append ("<a href=\"" + href + "\">" + label + "</a>");
+}}
+if (next[j].getDescription ().indexOf ("</html>") == -1) {
+out.append ("</html>");
+}}out.append ("\t");
+}out.append (seqs[i].getName ());
+out.append ("\t-1\t");
+out.append ("" + next[j].begin);
+out.append ("\t");
+out.append ("" + next[j].end);
+out.append ("\t");
+out.append (next[j].type);
+if (!Float.isNaN (next[j].score)) {
+out.append ("\t");
+out.append (next[j].score);
+}out.append (this.newline);
+}
+}}
+if (group != null) {
+out.append ("ENDGROUP\t");
+out.append (group);
+out.append (this.newline);
+groupIndex++;
+} else {
+break;
+}} while (groupIndex < groups.size () + 1);
+if (!featuresGen) {
+return "No Features Visible";
+}return out.toString ();
+}, "~A,java.util.Map,~B,~B");
+Clazz.defineMethod (c$, "printGFFFormat", 
+function (seqs, visible) {
+return this.printGFFFormat (seqs, visible, true, true);
+}, "~A,java.util.Map");
+Clazz.defineMethod (c$, "printGFFFormat", 
+function (seqs, visible, visOnly, nonpos) {
+var out =  new StringBuffer ();
+var next;
+var source;
+var isnonpos;
+for (var i = 0; i < seqs.length; i++) {
+if (seqs[i].getSequenceFeatures () != null) {
+next = seqs[i].getSequenceFeatures ();
+for (var j = 0; j < next.length; j++) {
+isnonpos = next[j].begin == 0 && next[j].end == 0;
+if ((!nonpos && isnonpos) || (!isnonpos && visOnly && !visible.containsKey (next[j].type))) {
+continue;
+}source = next[j].featureGroup;
+if (source == null) {
+source = next[j].getDescription ();
+}out.append (seqs[i].getName ());
+out.append ("\t");
+out.append (source);
+out.append ("\t");
+out.append (next[j].type);
+out.append ("\t");
+out.append ("" + next[j].begin);
+out.append ("\t");
+out.append ("" + next[j].end);
+out.append ("\t");
+out.append (next[j].score);
+out.append ("\t");
+if (next[j].getValue ("STRAND") != null) {
+out.append (next[j].getValue ("STRAND"));
+out.append ("\t");
+} else {
+out.append (".\t");
+}if (next[j].getValue ("FRAME") != null) {
+out.append (next[j].getValue ("FRAME"));
+} else {
+out.append (".");
+}if (next[j].getValue ("ATTRIBUTES") != null) {
+out.append (next[j].getValue ("ATTRIBUTES"));
+}out.append (this.newline);
+}
+}}
+return out.toString ();
+}, "~A,java.util.Map,~B,~B");
+Clazz.defineMethod (c$, "parse", 
+function () {
+});
+Clazz.overrideMethod (c$, "print", 
+function () {
+return "USE printGFFFormat() or printJalviewFormat()";
+});
+c$.$FeaturesFile$InvalidGFF3FieldException$ = function () {
+Clazz.pu$h(self.c$);
+c$ = Clazz.decorateAsClass (function () {
+Clazz.prepareCallback (this, arguments);
+this.field = null;
+this.value = null;
+Clazz.instantialize (this, arguments);
+}, jalview.io.FeaturesFile, "InvalidGFF3FieldException", Exception);
+Clazz.makeConstructor (c$, 
+function (a, b, c) {
+Clazz.superConstructor (this, jalview.io.FeaturesFile.InvalidGFF3FieldException, [c + " (Field was " + a + " and value was " + b.get (a).toString ()]);
+this.field = a;
+this.value = b.get (a).toString ();
+}, "~S,java.util.Map,~S");
+c$ = Clazz.p0p ();
+};
+Clazz.pu$h(self.c$);
+c$ = Clazz.declareType (jalview.io.FeaturesFile, "GffPragmas", Enum);
+Clazz.defineEnumConstant (c$, "gff_version", 0, []);
+Clazz.defineEnumConstant (c$, "sequence_region", 1, []);
+Clazz.defineEnumConstant (c$, "feature_ontology", 2, []);
+Clazz.defineEnumConstant (c$, "attribute_ontology", 3, []);
+Clazz.defineEnumConstant (c$, "source_ontology", 4, []);
+Clazz.defineEnumConstant (c$, "species_build", 5, []);
+Clazz.defineEnumConstant (c$, "fasta", 6, []);
+Clazz.defineEnumConstant (c$, "hash", 7, []);
+c$ = Clazz.p0p ();
+Clazz.defineStatics (c$,
+"GFFPRAGMA", null);
+{
+jalview.io.FeaturesFile.GFFPRAGMA =  new java.util.HashMap ();
+jalview.io.FeaturesFile.GFFPRAGMA.put ("sequence-region", jalview.io.FeaturesFile.GffPragmas.sequence_region);
+jalview.io.FeaturesFile.GFFPRAGMA.put ("feature-ontology", jalview.io.FeaturesFile.GffPragmas.feature_ontology);
+jalview.io.FeaturesFile.GFFPRAGMA.put ("#", jalview.io.FeaturesFile.GffPragmas.hash);
+jalview.io.FeaturesFile.GFFPRAGMA.put ("fasta", jalview.io.FeaturesFile.GffPragmas.fasta);
+jalview.io.FeaturesFile.GFFPRAGMA.put ("species-build", jalview.io.FeaturesFile.GffPragmas.species_build);
+jalview.io.FeaturesFile.GFFPRAGMA.put ("source-ontology", jalview.io.FeaturesFile.GffPragmas.source_ontology);
+jalview.io.FeaturesFile.GFFPRAGMA.put ("attribute-ontology", jalview.io.FeaturesFile.GffPragmas.attribute_ontology);
+}});