3 import java.awt.EventQueue;
4 //import java.applet.AppletContext;
5 import java.io.IOException;
7 import java.util.ArrayList;
8 import java.util.Hashtable;
10 import java.util.StringTokenizer;
11 import java.util.Vector;
13 import jalview.bin.ArgsParser;
14 import jalview.bin.Jalview;
15 import jalview.bin.JalviewJSApi;
16 import jalview.datamodel.Alignment;
17 import jalview.datamodel.AlignmentI;
18 import jalview.datamodel.AlignmentOrder;
19 import jalview.datamodel.ColumnSelection;
20 import jalview.datamodel.HiddenColumns;
21 import jalview.datamodel.PDBEntry;
22 import jalview.datamodel.Sequence;
23 import jalview.datamodel.SequenceGroup;
24 import jalview.datamodel.SequenceI;
25 import jalview.gui.AlignFrame;
26 import jalview.gui.AlignViewport;
27 import jalview.gui.AlignmentPanel;
28 import jalview.gui.CalculationChooser;
29 import jalview.gui.Desktop;
30 import jalview.gui.StructureViewer;
31 import jalview.io.AnnotationFile;
32 import jalview.io.AppletFormatAdapter;
33 import jalview.io.DataSourceType;
34 import jalview.io.FeaturesFile;
35 import jalview.io.FileFormat;
36 import jalview.io.FileFormatI;
37 import jalview.io.FileFormats;
38 import jalview.io.IdentifyFile;
39 import jalview.io.JPredFile;
40 import jalview.io.JnetAnnotationMaker;
41 import jalview.io.NewickFile;
42 import jalview.renderer.seqfeatures.FeatureRenderer;
43 import jalview.structure.SelectionListener;
44 import jalview.structure.SelectionSource;
45 import jalview.structure.StructureSelectionManager;
46 import jalview.structure.VamsasSource;
47 import jalview.util.HttpUtils;
48 import jalview.util.MessageManager;
49 import jalview.util.Platform;
51 //import netscape.javascript.JSObject;
54 * Basically the JalviewLite application, but without JalviewLite
59 public class JalviewJSApp implements JalviewJSApi
61 private ArgsParser aparser;
63 private boolean debug;
65 private String[] ret = new String[1];
67 private String separator = "\u00AC"; // JalviewLite note: the default used to
68 // be '|', but many sequence IDS include
72 public JalviewJSApp(ArgsParser aparser)
74 this.aparser = aparser;
75 Platform.setAppClass(this);
79 public void load(AlignFrame af)
81 String sep = (String) getAppletParameter("separator", true);
90 throw new Error(MessageManager
91 .getString("error.invalid_separator_parameter"));
105 // These are methods that are in JalviewLite that various classes call
106 // but are not in JalviewLiteJsApi. Or, even if they are, other classes
108 // them to JalviewLite directly. Some may not be necessary, but they have
110 // be at least mentioned here, or the classes calling them should
112 // JalviewLite itself.
114 // private boolean alignPDBStructures; // From JalviewLite; not implemented
118 public String getParameter(String name)
120 return (String) getAppletParameter(name, true);
124 public Object getAppletParameter(String name, boolean asString)
126 return aparser.getAppletValue(name, null, asString);
130 * Get the applet-like code base even though this is an application.
134 public URL getCodeBase()
136 return Platform.getCodeBase();
140 * Get the applet-like document base even though this is an application.
144 public URL getDocumentBase()
146 return Platform.getDocumentBase();
150 public Object getFrameForSource(VamsasSource source)
155 if (source instanceof jalview.gui.AlignViewport
156 && source == (af = Jalview.getCurrentAlignFrame())
159 // should be valid if it just generated an event!
162 // TODO: ensure that if '_af' is specified along with a handler
163 // function, then only events from that alignFrame are sent to that
170 public FeatureRenderer getNewFeatureRenderer(AlignViewportI vp)
172 return new jalview.gui.FeatureRenderer((AlignmentPanel) vp);
176 public Object[] getSelectionForListener(SequenceGroup seqsel,
177 ColumnSelection colsel, HiddenColumns hidden,
178 SelectionSource source, Object alignFrame)
180 return getSelectionForListener(null, seqsel, colsel, hidden, source,
190 public boolean loadScoreFile(String sScoreFile) throws IOException
192 return loadScoreFile(null, sScoreFile);
195 public boolean loadScoreFile(AlignFrame af, String sScoreFile) throws IOException
197 (af == null ? Jalview.getCurrentAlignFrame() : af).loadJalviewDataFile(sScoreFile, null, null, null);
201 public void loadTree(AlignFrame af, NewickFile nf, String treeFile) throws IOException
204 af = Jalview.getCurrentAlignFrame();
206 .setCurrentTree(af.showNewickTree(nf, treeFile).getTree());
210 public void newFeatureSettings()
213 "Jalview applet interface newFeatureSettings not implemented");
218 // public void setAlignPdbStructures(boolean defaultParameter)
220 // alignPDBStructures = true;
225 public void newStructureView(PDBEntry pdb, SequenceI[] seqs,
226 String[] chains, DataSourceType protocol)
228 newStructureView(null, pdb, seqs, chains, protocol);
232 public void newStructureView(AlignFrame af, PDBEntry pdb,
233 SequenceI[] seqs, String[] chains, DataSourceType protocol)
235 StructureViewer.launchStructureViewer(
236 (af == null ? Jalview.getCurrentAlignFrame() : af).alignPanel,
247 public boolean parseFeaturesFile(String filename, DataSourceType protocol)
249 return parseFeaturesFile(null, filename, protocol);
253 * @j2sAlias parseFeatureFile
260 public boolean parseFeaturesFile(AlignFrame af, String filename, DataSourceType protocol)
262 return (af == null ? Jalview.getCurrentAlignFrame() : af).parseFeaturesFile(filename, protocol);
266 * annotations, jpredfile, jnetfile
271 public void updateForAnnotations()
273 updateForAnnotations(null);
276 public void updateForAnnotations(AlignFrame af)
278 (af == null ? Jalview.getCurrentAlignFrame() : af).updateForAnnotations();
282 public boolean addPdbFile(AlignFrame alf, String sequenceId,
283 String pdbEntryString, String pdbFile)
287 alf = Jalview.getCurrentAlignFrame();
289 SequenceI toaddpdb = alf.getViewport().getAlignment()
290 .findName(sequenceId);
291 boolean needtoadd = false;
292 if (toaddpdb != null)
294 Vector<PDBEntry> pdbe = toaddpdb.getAllPDBEntries();
295 PDBEntry pdbentry = null;
296 if (pdbe != null && pdbe.size() > 0)
298 for (int pe = 0, peSize = pdbe.size(); pe < peSize; pe++)
300 pdbentry = pdbe.elementAt(pe);
301 if (!pdbentry.getId().equals(pdbEntryString)
302 && !pdbentry.getFile().equals(pdbFile))
312 if (pdbentry == null)
314 pdbentry = new PDBEntry();
315 pdbentry.setId(pdbEntryString);
316 pdbentry.setFile(pdbFile);
317 needtoadd = true; // add this new entry to sequence.
319 // resolve data source
320 // TODO: this code should be a refactored to an io package
321 DataSourceType protocol = AppletFormatAdapter.resolveProtocol(pdbFile,
323 if (protocol == null)
329 pdbentry.setProperty("protocol", protocol);
330 toaddpdb.addPDBId(pdbentry);
331 alf.alignPanel.getStructureSelectionManager()
332 .registerPDBEntry(pdbentry);
339 public String arrayToSeparatorList(String[] array)
341 return arrayToSeparatorList(array, separator);
345 * concatenate the list with separator
349 * @return concatenated string
351 public static String arrayToSeparatorList(String[] list, String separator)
353 // TODO use StringUtils version
354 StringBuffer v = new StringBuffer();
355 if (list != null && list.length > 0)
357 for (int i = 0, iSize = list.length; i < iSize; i++)
371 // .println("Returning '" + separator + "' separated List:\n");
372 // System.err.println(v);
378 // System.err.println(
379 // "Returning empty '" + separator + "' separated List\n");
381 return "" + separator;
385 public String getAlignment(String format)
387 return getAlignmentFrom(null, format, null);
391 * suffix string "true"/"false" (default true)
392 * passed to AlnFile class controls whether /START-END is added to
396 public String getAlignment(String format, String suffix)
398 return getAlignmentFrom(Jalview.getCurrentAlignFrame(), format, suffix);
402 public String getAlignmentFrom(AlignFrame alf, String format)
404 return getAlignmentFrom(alf, format, null);
408 public String getAlignmentFrom(AlignFrame alf, String format,
415 alf = Jalview.getCurrentAlignFrame();
417 boolean seqlimits = (suffix == null
418 || suffix.equalsIgnoreCase("true"));
420 FileFormatI theFormat = FileFormats.getInstance().forName(format);
421 String reply = new AppletFormatAdapter().formatSequences(theFormat,
422 alf.getViewport().getAlignment(), seqlimits);
424 } catch (IllegalArgumentException ex)
426 ex.printStackTrace();
427 return "Error retrieving alignment, possibly invalid format specifier: "
433 public String getAlignmentOrder()
435 return getAlignmentFrom(Jalview.getCurrentAlignFrame(), null);
439 public String getAlignmentOrderFrom(AlignFrame alf)
441 return getAlignmentFrom(alf, null);
445 public String getAlignmentOrderFrom(AlignFrame alf, String sep)
449 alf = Jalview.getCurrentAlignFrame();
451 AlignmentI alorder = alf.getViewport().getAlignment();
452 String[] order = new String[alorder.getHeight()];
453 for (int i = 0; i < order.length; i++)
455 order[i] = alorder.getSequenceAt(i).getName();
457 return arrayToSeparatorList(order, sep);
461 public String getAnnotation()
463 return getAnnotationFrom(null);
467 public String getAnnotationFrom(AlignFrame alf)
471 alf = Jalview.getCurrentAlignFrame();
473 String annotation = new AnnotationFile()
474 .printAnnotationsForView(alf.getViewport());
479 public String getFeatureGroups()
481 return getFeatureGroupsOn(null);
485 public String getFeatureGroupsOfState(boolean visible)
487 return getFeatureGroupsOfStateOn(null, visible);
491 public String getFeatureGroupsOfStateOn(AlignFrame alf, boolean visible)
495 alf = Jalview.getCurrentAlignFrame();
497 return arrayToSeparatorList(alf.getFeatureGroupsOfState(visible));
501 public String getFeatureGroupsOn(AlignFrame alf)
505 alf = Jalview.getCurrentAlignFrame();
507 return arrayToSeparatorList(alf.getFeatureGroups());
511 public String getFeatures(String format)
513 return getFeaturesFrom(null, format);
517 * JavaScript interface to print the alignment frame
521 * "jalview" or "gff" with or without ";includeComplement" or
522 * ";includeNonpositional"; default with no ";" is
523 * ";includeNonpositional"
527 public String getFeaturesFrom(AlignFrame alf, String format)
531 alf = Jalview.getCurrentAlignFrame();
534 FeaturesFile formatter = new FeaturesFile();
535 format = format.toLowerCase();
536 if (format.indexOf(";") < 0)
537 format += ";includenonpositional";
538 boolean nonpos = format.indexOf(";includenonpositional") > 0;
539 boolean compl = format.indexOf(";includecomplement") >= 0;
540 if (format.startsWith("jalview"))
542 features = formatter.printJalviewFormat(
543 alf.getViewport().getAlignment().getSequencesArray(),
544 alf.alignPanel.getFeatureRenderer(), nonpos, compl);
548 features = formatter.printGffFormat(
549 alf.getViewport().getAlignment().getSequencesArray(),
550 alf.alignPanel.getFeatureRenderer(), nonpos, compl);
553 if (features == null)
562 * read sequence1...sequenceN as a raw alignment
567 public String getPastedSequence(JalviewJSApp jalviewApp)
569 StringBuffer data = new StringBuffer("PASTE");
572 while ((file = (String) getAppletParameter("sequence" + i,
575 data.append(file.toString() + "\n");
578 if (data.length() > 5)
580 file = data.toString();
587 * @see jalview.appletgui.js.JalviewLiteJsApi#getSelectedSequences()
590 public SequenceI[] getSelectedSequences()
592 return getSelectedSequencesFrom(Jalview.getCurrentAlignFrame());
597 * @see jalview.appletgui.js.JalviewLiteJsApi#getSelectedSequences(java.lang.String)
600 public SequenceI[] getSelectedSequences(String sep)
602 return getSelectedSequencesFrom(Jalview.getCurrentAlignFrame(), sep);
606 public String getSelectedSequencesAsAlignment(String format,
609 return getSelectedSequencesAsAlignmentFrom(null, format, suffix);
613 public String getSelectedSequencesAsAlignmentFrom(AlignFrame alf,
614 String format, String suffix)
619 alf = Jalview.getCurrentAlignFrame();
622 boolean seqlimits = (suffix == null || suffix.equalsIgnoreCase("true"));
625 AlignViewport vp = alf.getViewport();
626 FileFormatI theFormat = FileFormats.getInstance().forName(format);
627 if (vp.getSelectionGroup() != null)
629 // JBPNote: getSelectionAsNewSequence behaviour has changed - this
630 // method now returns a full copy of sequence data
631 // TODO consider using getSequenceSelection instead here
632 String reply = new AppletFormatAdapter().formatSequences(theFormat,
633 new Alignment(vp.getSelectionAsNewSequence()), seqlimits);
636 } catch (IllegalArgumentException ex)
638 ex.printStackTrace();
639 return "Error retrieving alignment, possibly invalid format specifier: "
647 * @see jalview.appletgui.js.JalviewLiteJsApi#getSelectedSequencesFrom(jalview.appletgui
651 public SequenceI[] getSelectedSequencesFrom(AlignFrame alf)
653 return getSelectedSequencesFrom(alf, null);
657 public SequenceI[] getSelectedSequencesFrom(AlignFrame alf, String sep)
661 alf = Jalview.getCurrentAlignFrame();
663 AlignViewport v = alf.getViewport();
664 if (v.getSelectionGroup() != null)
666 return v.getSelectionGroup()
667 .getSequencesInOrder(v.getAlignment());
673 public Object[] getSelectionForListener(AlignFrame alf,
674 SequenceGroup seqsel, ColumnSelection colsel,
675 HiddenColumns hidden, SelectionSource source, Object alignFrame)
679 alf = Jalview.getCurrentAlignFrame();
681 // System.err.println("Testing selection event relay to
682 // jsfunction:"+_listener);
684 AlignFrame src = (AlignFrame) alignFrame;
687 if (source instanceof AlignViewport && alf.getViewport() == source)
689 // should be valid if it just generated an event!
694 String[] seqs = new String[] {};
695 String[] cols = new String[] {};
696 int strt = 0, end = (src == null) ? -1
697 : src.alignPanel.av.getAlignment().getWidth();
698 if (seqsel != null && seqsel.getSize() > 0)
700 seqs = new String[seqsel.getSize()];
701 for (int i = 0; i < seqs.length; i++)
703 seqs[i] = seqsel.getSequenceAt(i).getName();
705 if (strt < seqsel.getStartRes())
707 strt = seqsel.getStartRes();
709 if (end == -1 || end > seqsel.getEndRes())
711 end = seqsel.getEndRes();
714 if (colsel != null && !colsel.isEmpty())
718 end = colsel.getMax() + 1;
720 cols = new String[colsel.getSelected().size()];
721 for (int i = 0; i < cols.length; i++)
723 cols[i] = "" + (1 + colsel.getSelected().get(i).intValue());
728 if (seqsel != null && seqsel.getSize() > 0)
730 // send a valid range, otherwise we send the empty selection
731 cols = new String[2];
732 cols[0] = "" + (1 + strt) + "-" + (1 + end);
735 return new Object[] { src, setid, arrayToSeparatorList(seqs),
736 arrayToSeparatorList(cols) };
740 public String getSeparator()
747 * @see jalview.appletgui.js.JalviewLiteJsApi#getSelectedSequencesFrom(jalview.appletgui
748 * .AlignFrame, java.lang.String)
751 public void highlight(String sequenceId, String position,
752 String alignedPosition)
754 highlightIn(null, sequenceId, position, alignedPosition);
758 public void highlightIn(AlignFrame alf, final String sequenceId,
759 final String position, final String alignedPosition)
763 alf = Jalview.getCurrentAlignFrame();
765 // TODO: could try to highlight in all alignments if alf==null
766 jalview.analysis.SequenceIdMatcher matcher = new jalview.analysis.SequenceIdMatcher(
767 alf.getViewport().getAlignment().getSequencesArray());
768 final SequenceI sq = matcher.findIdMatch(sequenceId);
774 apos = Integer.valueOf(position).intValue();
776 } catch (NumberFormatException ex)
780 final int pos = apos;
781 // use vamsas listener to broadcast to all listeners in scope
782 if (alignedPosition != null && (alignedPosition.trim().length() == 0
783 || alignedPosition.toLowerCase().indexOf("false") > -1))
785 java.awt.EventQueue.invokeLater(new Runnable()
790 StructureSelectionManager
791 .getStructureSelectionManager(Desktop.getInstance())
792 .mouseOverVamsasSequence(sq, sq.findIndex(pos), null);
798 java.awt.EventQueue.invokeLater(new Runnable()
803 StructureSelectionManager
804 .getStructureSelectionManager(Desktop.getInstance())
805 .mouseOverVamsasSequence(sq, pos, null);
812 public AlignFrame loadAlignment(String text, int width, int height,
815 AlignmentI al = null;
819 FileFormatI format = new IdentifyFile().identify(text,
820 DataSourceType.PASTE);
821 al = new AppletFormatAdapter().readFile(text, DataSourceType.PASTE,
823 if (al.getHeight() > 0)
825 return new AlignFrame(al, width, height, title);
827 } catch (IOException ex)
829 ex.printStackTrace();
834 // public void setMouseoverListener(String listener)
836 // appLoader.setMouseoverListener(listener);
840 // public void setMouseoverListener(AlignFrame af, String listener)
846 public AlignFrame loadAlignment(String text, String title)
848 return loadAlignment(text, AlignFrame.DEFAULT_WIDTH,
849 AlignFrame.DEFAULT_HEIGHT, title);
853 public void loadAnnotation(String annotation)
855 loadAnnotationFrom(null, annotation);
859 public void loadAnnotationFrom(AlignFrame alf, String annotation)
863 alf = Jalview.getCurrentAlignFrame();
865 if (new AnnotationFile().annotateAlignmentView(alf.getViewport(),
866 annotation, DataSourceType.PASTE))
868 alf.alignPanel.fontChanged();
869 alf.alignPanel.setScrollValues(0, 0);
873 alf.parseFeaturesFile(annotation, DataSourceType.PASTE);
878 * Load annotations if specified by parameter. Returns true if loaded, else
885 protected boolean loadAnnotations(AlignFrame af)
887 boolean result = false;
888 String param = (String) getAppletParameter("annotations", true);
892 DataSourceType protocol = resolveFileProtocol(ret);
894 if (new AnnotationFile().annotateAlignmentView(af.getViewport(), param,
897 updateForAnnotations();
903 .println("Annotations were not added from annotation file '"
913 * Load features file and view settings as specified by parameters. Returns
914 * true if features were loaded, else false.
920 protected boolean loadFeatures(AlignFrame af)
922 boolean result = false;
923 // ///////////////////////////
924 // modify display of features
925 // we do this before any features have been loaded, ensuring any hidden
926 // groups are hidden when features first displayed
928 // hide specific groups
930 String param = (String) getAppletParameter("hidefeaturegroups", true);
933 setFeatureGroupState(af, separatorListToArray(param, separator), false);
934 // setFeatureGroupStateOn(newAlignFrame, param, false);
936 // show specific groups
937 param = (String) getAppletParameter("showfeaturegroups", true);
940 setFeatureGroupState(af, separatorListToArray(param, separator), true);
941 // setFeatureGroupStateOn(newAlignFrame, param, true);
943 // and now load features
944 param = (String) getAppletParameter("features", true);
948 DataSourceType protocol = resolveFileProtocol(ret);
950 result = parseFeaturesFile(af, ret[0], protocol);
953 param = (String) getAppletParameter("showFeatureSettings", true);
954 if (param != null && param.equalsIgnoreCase("true"))
956 newFeatureSettings();
962 public void loadFeatures(String features, boolean autoenabledisplay)
964 loadFeaturesFrom(null, features, autoenabledisplay);
968 public boolean loadFeaturesFrom(AlignFrame alf, String features,
969 boolean autoenabledisplay)
973 alf = Jalview.getCurrentAlignFrame();
975 boolean ret = alf.parseFeaturesFile(features, DataSourceType.PASTE);
980 if (autoenabledisplay)
982 alf.getViewport().setShowSequenceFeatures(true);
983 // this next was for a checkbox in JalviewLite
984 // ((AlignFrame) alf).getViewport().sequenceFeatures.setState(true);
990 * Load in a Jnetfile if specified by parameter. Returns true if loaded, else
996 protected boolean loadJnetFile(AlignFrame af)
998 boolean result = false;
999 String param = (String) getAppletParameter("jnetfile", true);
1002 // jnet became jpred around 2016
1003 param = (String) getAppletParameter("jpredfile", true);
1010 DataSourceType protocol = resolveFileProtocol(ret);
1011 JPredFile predictions = new JPredFile(ret[0], protocol);
1012 JnetAnnotationMaker.add_annotation(predictions,
1013 af.getViewport().getAlignment(), 0, false);
1014 // false == do not add sequence profile from concise output
1015 af.getViewport().getAlignment().setupJPredAlignment();
1016 updateForAnnotations();
1018 } catch (Exception ex)
1020 ex.printStackTrace();
1027 * Load PDBFiles if any specified by parameter(s). Returns true if loaded,
1030 * @param loaderFrame
1033 protected boolean loadPdbFiles(AlignFrame af)
1035 boolean result = false;
1037 * <param name="alignpdbfiles" value="false/true"/> Undocumented for 2.6 -
1038 * related to JAL-434
1041 // not supported (as for JalviewLite)
1042 // boolean doAlign = false;//"true".equalsIgnoreCase("" +
1043 // getAppletParameter("alignpdbfiles", false));
1044 // setAlignPdbStructures(doAlign);
1046 * <param name="PDBfile" value="1gaq.txt PDB|1GAQ|1GAQ|A PDB|1GAQ|1GAQ|B
1049 * <param name="PDBfile2" value="1gaq.txt A=SEQA B=SEQB C=SEQB">
1051 * <param name="PDBfile3" value="1q0o Q45135_9MICO">
1054 // Accumulate pdbs here if they are heading for the same view (if
1055 // alignPdbStructures is true)
1056 // ArrayList<Object[]> pdbs = new ArrayList<>();
1057 // create a lazy matcher if we're asked to
1058 boolean relaxed = "true".equalsIgnoreCase(
1059 "" + getAppletParameter("relaxedidmatch", false));
1060 jalview.analysis.SequenceIdMatcher matcher = relaxed
1061 ? new jalview.analysis.SequenceIdMatcher(
1062 af.getViewport().getAlignment().getSequencesArray())
1065 int pdbFileCount = 0;
1069 if (pdbFileCount > 0)
1071 param = (String) getAppletParameter("PDBFILE" + pdbFileCount, true);
1075 param = (String) getAppletParameter("PDBFILE", true);
1080 PDBEntry pdb = new PDBEntry();
1083 SequenceI[] seqs = null;
1084 String[] chains = null;
1086 StringTokenizer st = new StringTokenizer(param, " ");
1088 if (st.countTokens() < 2)
1090 String sequence = (String) getAppletParameter("PDBSEQ", true);
1091 if (sequence != null)
1093 seqs = new SequenceI[] { matcher == null
1094 ? (Sequence) af.getViewport().getAlignment()
1096 : matcher.findIdMatch(sequence) };
1102 param = st.nextToken();
1103 List<SequenceI> tmp = new ArrayList<>();
1104 List<String> tmp2 = new ArrayList<>();
1106 while (st.hasMoreTokens())
1108 seqstring = st.nextToken();
1109 StringTokenizer st2 = new StringTokenizer(seqstring, "=");
1110 if (st2.countTokens() > 1)
1112 // This is the chain
1113 tmp2.add(st2.nextToken());
1114 seqstring = st2.nextToken();
1116 tmp.add(matcher == null
1117 ? (Sequence) af.getViewport().getAlignment()
1118 .findName(seqstring)
1119 : matcher.findIdMatch(seqstring));
1122 seqs = tmp.toArray(new SequenceI[tmp.size()]);
1123 if (tmp2.size() == tmp.size())
1125 chains = tmp2.toArray(new String[tmp2.size()]);
1130 DataSourceType protocol = resolveFileProtocol(ret);
1131 // TODO check JAL-357 for files in a jar (CLASSLOADER)
1132 pdb.setFile(ret[0]);
1136 for (int i = 0; i < seqs.length; i++)
1138 if (seqs[i] != null)
1140 ((Sequence) seqs[i]).addPDBId(pdb);
1141 StructureSelectionManager
1142 .getStructureSelectionManager(
1143 (StructureSelectionManagerProvider) this)
1144 .registerPDBEntry(pdb);
1150 // this may not really be a problem but we give a warning
1153 "Warning: Possible input parsing error: Null sequence for attachment of PDB (sequence "
1161 // pdbs.add(new Object[] { pdb, seqs, chains, protocol });
1165 newStructureView(af, pdb, seqs, chains, protocol);
1171 } while (param != null || pdbFileCount < 10);
1173 // if (doAlign && pdbs.size() > 0)
1175 // SequenceI[][] seqs = new SequenceI[pdbs.size()][];
1176 // PDBEntry[] pdb = new PDBEntry[pdbs.size()];
1177 // String[][] chains = new String[pdbs.size()][];
1178 // String[] protocols = new String[pdbs.size()];
1179 // for (int pdbsi = 0, pdbsiSize = pdbs
1180 // .size(); pdbsi < pdbsiSize; pdbsi++)
1182 // Object[] o = pdbs.get(pdbsi);
1183 // pdb[pdbsi] = (PDBEntry) o[0];
1184 // seqs[pdbsi] = (SequenceI[]) o[1];
1185 // chains[pdbsi] = (String[]) o[2];
1186 // protocols[pdbsi] = (String) o[3];
1188 //// alignedStructureView(pdb, seqs, chains, protocols);
1195 * Load a score file if specified by parameter. Returns true if file was
1196 * loaded, else false.
1198 * @param loaderFrame
1200 protected boolean loadScoreFile()
1202 boolean result = false;
1203 String sScoreFile = (String) getAppletParameter("scoreFile", true);
1204 if (sScoreFile != null && !"".equals(sScoreFile))
1211 "Attempting to load T-COFFEE score file from the scoreFile parameter");
1213 result = loadScoreFile(sScoreFile);
1217 "Failed to parse T-COFFEE parameter as a valid score file ('"
1218 + sScoreFile + "')");
1220 } catch (Exception e)
1222 System.err.printf("Cannot read score file: '%s'. Cause: %s \n",
1223 sScoreFile, e.getMessage());
1230 * Load a tree for the alignment if specified by parameter. Returns true if a
1231 * tree was loaded, else false.
1235 protected boolean loadTree(AlignFrame af)
1237 boolean result = false;
1238 String treeFile = (String) getAppletParameter("tree", true);
1239 if (treeFile == null)
1241 treeFile = (String) getAppletParameter("treefile", true);
1244 if (treeFile != null)
1249 NewickFile fin = new NewickFile(treeFile, resolveFileProtocol(ret));
1252 if (fin.getTree() != null)
1254 loadTree(af, fin, ret[0]);
1258 System.out.println("Successfully imported tree.");
1266 "Tree parameter did not resolve to a valid tree.");
1269 } catch (Exception ex)
1271 ex.printStackTrace();
1278 * public static method for JalviewJS API to open a PCAPanel without
1279 * necessarily using a dialog.
1283 * @return the PCAPanel, or the string "label.you_need_at_least_n_sequences"
1284 * if number of sequences selected is inappropriate
1287 public Object openPcaPanel(AlignFrame af, String modelName)
1291 af = Jalview.getCurrentAlignFrame();
1293 return CalculationChooser.openPcaPanel(af, modelName, null);
1297 * Open a new Tree panel on the desktop statically. Params are standard (not
1298 * set by Groovy). No dialog is opened.
1303 * @return null, or the string "label.you_need_at_least_n_sequences" if number
1304 * of sequences selected is inappropriate
1307 public Object openTreePanel(AlignFrame af, String treeType,
1312 af = Jalview.getCurrentAlignFrame();
1314 return CalculationChooser.openTreePanel(af, treeType, modelName, null);
1318 public String orderAlignmentBy(AlignFrame alf, String order,
1319 String undoName, String sep)
1321 if (sep == null || sep.length() == 0)
1325 String[] ids = separatorListToArray(order, sep);
1326 SequenceI[] sqs = null;
1327 if (ids != null && ids.length > 0)
1331 alf = Jalview.getCurrentAlignFrame();
1333 jalview.analysis.SequenceIdMatcher matcher = new jalview.analysis.SequenceIdMatcher(
1334 alf.getViewport().getAlignment().getSequencesArray());
1336 sqs = new SequenceI[ids.length];
1337 for (int i = 0; i < ids.length; i++)
1339 if (ids[i].trim().length() == 0)
1343 SequenceI sq = matcher.findIdMatch(ids[i]);
1351 SequenceI[] sqq = new SequenceI[s];
1352 System.arraycopy(sqs, 0, sqq, 0, s);
1365 final AlignmentOrder aorder = new AlignmentOrder(sqs);
1367 if (undoName != null && undoName.trim().length() == 0)
1371 final String _undoName = undoName;
1372 // TODO: deal with synchronization here: cannot raise any events until after
1373 // this has returned.
1374 return alf.sortBy(aorder, _undoName) ? "true" : "";
1378 public String orderBy(String order, String undoName)
1380 return orderBy(order, undoName, null);
1384 public String orderBy(String order, String undoName, String sep)
1386 return orderAlignmentBy(Jalview.getCurrentAlignFrame(), order, undoName,
1391 * Allow an outside entity to initiate the second half of argument parsing
1395 * @return null is good
1398 public Object parseArguments(String[] args)
1403 Jalview.getInstance().parseArguments(new ArgsParser(args), false);
1405 } catch (Throwable t)
1412 public void removeSelectionListener(AlignFrame af, String listener)
1415 List<SelectionListener> listeners = Desktop
1416 .getStructureSelectionManager().getListeners();
1417 for (int i = listeners.size(); --i >= 0;)
1419 SelectionListener l = listeners.get(i);
1420 if (l instanceof JsSelectionListener
1421 && ((JsSelectionListener) l).isFor(af, listener))
1423 listeners.remove(i);
1430 public void scrollViewToColumnIn(final AlignFrame alf,
1431 final String leftHandColumn)
1433 java.awt.EventQueue.invokeLater(new Runnable()
1441 (alf == null ? Jalview.getCurrentAlignFrame() : alf)
1443 Integer.valueOf(leftHandColumn).intValue());
1445 } catch (Exception ex)
1448 "Couldn't parse integer arguments (leftHandColumn='"
1449 + leftHandColumn + "')");
1450 ex.printStackTrace();
1458 public void scrollViewToIn(final AlignFrame alf, final String topRow,
1459 final String leftHandColumn)
1462 java.awt.EventQueue.invokeLater(new Runnable()
1469 (alf == null ? Jalview.getCurrentAlignFrame() : alf).scrollTo(
1470 Integer.valueOf(topRow).intValue(),
1471 Integer.valueOf(leftHandColumn).intValue());
1473 } catch (Exception ex)
1475 System.err.println("Couldn't parse integer arguments (topRow='"
1476 + topRow + "' and leftHandColumn='" + leftHandColumn
1478 ex.printStackTrace();
1485 public void scrollViewToRowIn(final AlignFrame alf, final String topRow)
1489 java.awt.EventQueue.invokeLater(new Runnable()
1496 (alf == null ? Jalview.getCurrentAlignFrame() : alf)
1497 .scrollToRow(Integer.valueOf(topRow).intValue());
1499 } catch (Exception ex)
1501 System.err.println("Couldn't parse integer arguments (topRow='"
1503 ex.printStackTrace();
1511 public void select(String sequenceIds, String columns)
1513 selectIn(Jalview.getCurrentAlignFrame(), sequenceIds, columns, null);
1517 public void select(String sequenceIds, String columns, String sep)
1519 selectIn(null, sequenceIds, columns, sep);
1523 // public AlignFrame newView()
1525 // return newViewFrom(null, null);
1529 // public AlignFrame newView(String name)
1531 // return newViewFrom(null, name);
1535 // public AlignFrame newViewFrom(AlignFrame alf)
1537 // return newViewFrom(alf, null);
1541 // public AlignFrame newViewFrom(AlignFrame alf, String name)
1545 // alf = Jalview.getCurrentAlignFrame();
1547 // return appLoader.newViewFrom(alf, name);
1551 public void selectIn(AlignFrame alf, String sequenceIds, String columns)
1553 selectIn(alf, sequenceIds, columns, null);
1557 public void selectIn(AlignFrame af, String sequenceIds, String columns,
1560 AlignFrame alf = (af == null ? Jalview.getCurrentAlignFrame() : af);
1562 if (sep == null || sep.length() == 0)
1570 System.err.println("Selecting region using separator string '"
1575 String[] ids = separatorListToArray(sequenceIds, sep);
1576 String[] cols = separatorListToArray(columns, sep);
1577 final SequenceGroup sel = new SequenceGroup();
1578 final ColumnSelection csel = new ColumnSelection();
1579 AlignmentI al = alf.getViewport().getAlignment();
1580 jalview.analysis.SequenceIdMatcher matcher = new jalview.analysis.SequenceIdMatcher(
1581 alf.getViewport().getAlignment().getSequencesArray());
1582 int start = 0, end = al.getWidth(), alw = al.getWidth();
1583 boolean seqsfound = true;
1584 if (ids != null && ids.length > 0)
1587 for (int i = 0; i < ids.length; i++)
1589 if (ids[i].trim().length() == 0)
1593 SequenceI sq = matcher.findIdMatch(ids[i]);
1597 sel.addSequence(sq, false);
1601 boolean inseqpos = false;
1602 if (cols != null && cols.length > 0)
1604 boolean seset = false;
1605 for (int i = 0; i < cols.length; i++)
1607 String cl = cols[i].trim();
1608 if (cl.length() == 0)
1613 if ((p = cl.indexOf("-")) > -1)
1615 int from = -1, to = -1;
1618 from = Integer.valueOf(cl.substring(0, p)).intValue();
1620 } catch (NumberFormatException ex)
1623 "ERROR: Couldn't parse first integer in range element column selection string '"
1624 + cl + "' - format is 'from-to'");
1629 to = Integer.valueOf(cl.substring(p + 1)).intValue();
1631 } catch (NumberFormatException ex)
1634 "ERROR: Couldn't parse second integer in range element column selection string '"
1635 + cl + "' - format is 'from-to'");
1638 if (from >= 0 && to >= 0)
1655 // comment to prevent range extension
1665 for (int r = from; r <= to; r++)
1667 if (r >= 0 && r < alw)
1674 System.err.println("Range '" + cl + "' deparsed as [" + from
1680 System.err.println("ERROR: Invalid Range '" + cl
1681 + "' deparsed as [" + from + "," + to + "]");
1689 r = Integer.valueOf(cl).intValue();
1691 } catch (NumberFormatException ex)
1693 if (cl.toLowerCase().equals("sequence"))
1695 // we are in the dataset sequence's coordinate frame.
1701 "ERROR: Couldn't parse integer from point selection element of column selection string '"
1706 if (r >= 0 && r <= alw)
1716 // comment to prevent range extension
1729 System.err.println("Point selection '" + cl
1730 + "' deparsed as [" + r + "]");
1735 System.err.println("ERROR: Invalid Point selection '" + cl
1736 + "' deparsed as [" + r + "]");
1743 // we only propagate the selection when it was the null selection, or the
1744 // given sequences were found in the alignment.
1745 if (inseqpos && sel.getSize() > 0)
1747 // assume first sequence provides reference frame ?
1748 SequenceI rs = sel.getSequenceAt(0);
1749 start = rs.findIndex(start);
1750 end = rs.findIndex(end);
1751 List<Integer> cs = new ArrayList<>(csel.getSelected());
1753 for (Integer selectedCol : cs)
1755 csel.addElement(rs.findIndex(selectedCol));
1758 sel.setStartRes(start);
1760 EventQueue.invokeLater(new Runnable()
1765 alf.select(sel, csel,
1766 alf.getCurrentView().getAlignment().getHiddenColumns());
1772 // public AlignFrame newViewFrom(AlignFrame alf, String name)
1774 // return (AlignFrame) alf.newView(name, true);
1778 public String[] separatorListToArray(String list)
1780 return separatorListToArray(list, separator);
1784 public void setFeatureGroupState(String[] groups, boolean state)
1786 setFeatureGroupState(null, groups, state);
1790 public void setFeatureGroupState(String groups, boolean state)
1791 { // JalviewLite API
1792 setFeatureGroupStateOn(null, groups, state);
1796 public void setFeatureGroupStateOn(final AlignFrame alf,
1797 final String groups, boolean state)
1799 setFeatureGroupState(alf, separatorListToArray(groups, separator), state);
1800 // java.awt.EventQueue.invokeLater(new Runnable()
1803 // public void run()
1805 // (alf == null ? Jalview.getCurrentAlignFrame() : alf)
1806 // .setFeatureGroupState(
1807 // separatorListToArray(groups, separator), state);
1812 public void setFeatureGroupState(AlignFrame af, String[] groups, boolean state) {
1813 (af == null ? Jalview.getCurrentAlignFrame() : af).setFeatureGroupState(groups, state);
1818 public void setSelectionListener(AlignFrame af, String listener)
1820 Desktop.getStructureSelectionManager()
1821 .addSelectionListener(new JsSelectionListener(af, listener));
1825 public void setSelectionListener(String listener)
1827 Desktop.getStructureSelectionManager()
1828 .addSelectionListener(new JsSelectionListener(null, listener));
1832 public void setSeparator(String separator)
1834 this.separator = separator;
1838 public void showOverview()
1840 Jalview.getCurrentAlignFrame().overviewMenuItem_actionPerformed(null);
1844 * Allowing for a JavaScript function here.
1846 public void callInitCallback()
1848 Object initjscallback = getAppletParameter("oninit", false);
1849 if (initjscallback != null)
1853 doSendCallback(initjscallback, new Object[0]);
1854 } catch (Exception e)
1856 System.err.println("Exception when executing _oninit callback '"
1857 + initjscallback + "'.");
1858 e.printStackTrace();
1864 * Pass the provided array prepended with Jalview.this
1866 * Appropriated from org.jmol.appletjs.Jmol
1869 * a window function or "alert"
1871 * @return String return from the callback method.
1873 public String doSendCallback(Object callback, Object[] data)
1875 Jalview me = Jalview.getInstance();
1877 if (me != null && callback != null)
1884 * if (callback == "alert") { alert(data[0]); return ""; } var
1885 * o; if (typeof callback == "function") { o = callback; } else
1886 * { if (!callback)return; var tokens = callback.split("."); o
1887 * = window[tokens[0]]; for (var i = 1; i < tokens.length; i++)
1888 * o = o[tokens[i]]; } var a = [me]; for (var i = 0; i <
1889 * data.length; i++) a.push(data[i] ? data[i].booleanValue &&
1890 * (data[i] = data[i].booleanValue()) : data[i]); return
1891 * o.apply(null,a) } catch (e) { System.out.println(callback +
1892 * " failed " + e); }
1898 private DataSourceType resolveFileProtocol(String[] retPath)
1900 String path = retPath[0];
1904 if (path.startsWith("PASTE"))
1906 retPath[0] = path.substring(5);
1907 return DataSourceType.PASTE;
1913 if (path.indexOf("://") >= 0)
1915 return DataSourceType.URL;
1919 * try relative to document root
1921 URL documentBase = getDocumentBase();
1922 String withDocBase = resolveUrlForLocalOrAbsolute(path, documentBase);
1923 if (HttpUtils.isValidUrl(withDocBase))
1927 // System.err.println("Prepended document base '" + documentBase
1928 // + "' to make: '" + withDocBase + "'");
1930 retPath[0] = withDocBase;
1931 return DataSourceType.URL;
1935 * try relative to codebase (if different to document base)
1937 URL codeBase = getCodeBase();
1938 String withCodeBase = resolveUrlForLocalOrAbsolute(path, codeBase);
1939 if (!withCodeBase.equals(withDocBase)
1940 && HttpUtils.isValidUrl(withCodeBase))
1944 // System.err.println("Prepended codebase '" + codeBase
1945 // + "' to make: '" + withCodeBase + "'");
1947 retPath[0] = withCodeBase;
1948 return DataSourceType.URL;
1952 * try locating by classloader; try this last so files in the directory
1953 * are resolved using document base
1955 if (inArchive(getClass(), path))
1957 return DataSourceType.CLASSLOADER;
1963 * Discovers whether the given file is in the Applet Archive
1969 private static boolean inArchive(Class<?> c, String f)
1971 // This might throw a security exception in certain browsers
1972 // Netscape Communicator for instance.
1975 boolean rtn = (c.getResourceAsStream("/" + f) != null);
1977 } catch (Exception ex)
1979 System.out.println("Exception checking resources: " + f + " " + ex);
1985 * form a complete URL given a path to a resource and a reference location on
1989 * - an absolute path on the same server as localref or a document
1990 * located relative to localref
1992 * - a URL on the same server as url
1993 * @return a complete URL for the resource located by url
1995 public static String resolveUrlForLocalOrAbsolute(String targetPath,
1998 String resolvedPath = "";
1999 if (targetPath.startsWith("/"))
2001 String codebase = localref.toString();
2002 String localfile = localref.getFile();
2003 resolvedPath = codebase.substring(0,
2004 codebase.length() - localfile.length()) + targetPath;
2005 return resolvedPath;
2009 * get URL path and strip off any trailing file e.g.
2010 * www.jalview.org/examples/index.html#applets?a=b is trimmed to
2011 * www.jalview.org/examples/
2013 String urlPath = localref.toString();
2014 String directoryPath = urlPath;
2015 int lastSeparator = directoryPath.lastIndexOf("/");
2016 if (lastSeparator > 0)
2018 directoryPath = directoryPath.substring(0, lastSeparator + 1);
2021 if (targetPath.startsWith("/"))
2024 * construct absolute URL to a file on the server - this is not allowed?
2026 // String localfile = localref.getFile();
2027 // resolvedPath = urlPath.substring(0,
2028 // urlPath.length() - localfile.length())
2030 resolvedPath = directoryPath + targetPath.substring(1);
2034 resolvedPath = directoryPath + targetPath;
2038 // System.err.println(
2039 // "resolveUrlForLocalOrAbsolute returning " + resolvedPath);
2041 return resolvedPath;
2045 * parse the string into a list
2049 * @return elements separated by separator
2051 public static String[] separatorListToArray(String list, String separator)
2053 // TODO use StringUtils version (slightly different...)
2054 int seplen = separator.length();
2055 if (list == null || list.equals("") || list.equals(separator))
2059 Vector<String> jv = new Vector<>();
2061 while ((pos = list.indexOf(separator, cp)) > cp)
2063 jv.addElement(list.substring(cp, pos));
2066 if (cp < list.length())
2068 String c = list.substring(cp);
2069 if (!c.equals(separator))
2076 String[] v = new String[jv.size()];
2077 for (int i = 0; i < v.length; i++)
2079 v[i] = jv.elementAt(i);
2081 jv.removeAllElements();
2087 public class JsSelectionListener
2088 implements jalview.structure.SelectionListener
2095 public JsSelectionListener(AlignFrame af, String listener)
2098 _listener = listener;
2102 public void selection(SequenceGroup seqsel, ColumnSelection colsel,
2103 HiddenColumns hidden, SelectionSource source)
2105 // System.err.println("Testing selection event relay to
2106 // jsfunction:"+_listener);
2108 AlignFrame src = _af;
2111 if (source instanceof AlignViewport
2112 && Jalview.getCurrentAlignFrame().getViewport() == source)
2114 src = Jalview.getCurrentAlignFrame();
2119 String[] seqs = new String[] {};
2120 String[] cols = new String[] {};
2121 int strt = 0, end = (src == null) ? -1
2122 : src.alignPanel.av.getAlignment().getWidth();
2123 if (seqsel != null && seqsel.getSize() > 0)
2125 seqs = new String[seqsel.getSize()];
2126 for (int i = 0; i < seqs.length; i++)
2128 seqs[i] = seqsel.getSequenceAt(i).getName();
2130 if (strt < seqsel.getStartRes())
2132 strt = seqsel.getStartRes();
2134 if (end == -1 || end > seqsel.getEndRes())
2136 end = seqsel.getEndRes();
2139 if (colsel != null && !colsel.isEmpty())
2143 end = colsel.getMax() + 1;
2145 cols = new String[colsel.getSelected().size()];
2146 for (int i = 0; i < cols.length; i++)
2148 cols[i] = "" + (1 + colsel.getSelected().get(i).intValue());
2153 if (seqsel != null && seqsel.getSize() > 0)
2155 // send a valid range, otherwise we send the empty selection
2156 cols = new String[2];
2157 cols[0] = "" + (1 + strt) + "-" + (1 + end);
2163 doSendCallback(_listener,
2165 { src, setid, arrayToSeparatorList(seqs),
2166 arrayToSeparatorList(cols) });
2169 public boolean isFor(AlignFrame af, String listener)
2171 return _af == af && _listener.contentEquals(listener);
2177 public AlignViewportI getViewport()
2179 return Jalview.getCurrentAlignFrame().getViewport();