Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
Commands | 86 | 538 | 196 |
1 | /* | |
2 | * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) | |
3 | * Copyright (C) $$Year-Rel$$ The Jalview Authors | |
4 | * | |
5 | * This file is part of Jalview. | |
6 | * | |
7 | * Jalview is free software: you can redistribute it and/or | |
8 | * modify it under the terms of the GNU General Public License | |
9 | * as published by the Free Software Foundation, either version 3 | |
10 | * of the License, or (at your option) any later version. | |
11 | * | |
12 | * Jalview is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty | |
14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |
15 | * PURPOSE. See the GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with Jalview. If not, see <http://www.gnu.org/licenses/>. | |
19 | * The Jalview Authors are detailed in the 'AUTHORS' file. | |
20 | */ | |
21 | package jalview.bin; | |
22 | ||
23 | import java.awt.Color; | |
24 | import java.io.File; | |
25 | import java.io.FileNotFoundException; | |
26 | import java.io.IOException; | |
27 | import java.net.URISyntaxException; | |
28 | import java.util.ArrayList; | |
29 | import java.util.Arrays; | |
30 | import java.util.Collections; | |
31 | import java.util.HashMap; | |
32 | import java.util.Iterator; | |
33 | import java.util.List; | |
34 | import java.util.Locale; | |
35 | import java.util.Map; | |
36 | ||
37 | import javax.swing.SwingUtilities; | |
38 | ||
39 | import jalview.analysis.AlignmentUtils; | |
40 | import jalview.api.structures.JalviewStructureDisplayI; | |
41 | import jalview.bin.Jalview.ExitCode; | |
42 | import jalview.bin.argparser.Arg; | |
43 | import jalview.bin.argparser.ArgParser; | |
44 | import jalview.bin.argparser.ArgValue; | |
45 | import jalview.bin.argparser.ArgValuesMap; | |
46 | import jalview.bin.argparser.SubVals; | |
47 | import jalview.datamodel.AlignmentI; | |
48 | import jalview.datamodel.SequenceI; | |
49 | import jalview.datamodel.annotations.AlphaFoldAnnotationRowBuilder; | |
50 | import jalview.gui.AlignFrame; | |
51 | import jalview.gui.AlignmentPanel; | |
52 | import jalview.gui.AppJmol; | |
53 | import jalview.gui.Desktop; | |
54 | import jalview.gui.Preferences; | |
55 | import jalview.gui.StructureChooser; | |
56 | import jalview.gui.StructureViewer; | |
57 | import jalview.gui.StructureViewer.ViewerType; | |
58 | import jalview.io.AppletFormatAdapter; | |
59 | import jalview.io.BackupFiles; | |
60 | import jalview.io.BioJsHTMLOutput; | |
61 | import jalview.io.DataSourceType; | |
62 | import jalview.io.FileFormat; | |
63 | import jalview.io.FileFormatException; | |
64 | import jalview.io.FileFormatI; | |
65 | import jalview.io.FileFormats; | |
66 | import jalview.io.FileLoader; | |
67 | import jalview.io.HtmlSvgOutput; | |
68 | import jalview.io.IdentifyFile; | |
69 | import jalview.io.NewickFile; | |
70 | import jalview.io.exceptions.ImageOutputException; | |
71 | import jalview.schemes.ColourSchemeI; | |
72 | import jalview.schemes.ColourSchemeProperty; | |
73 | import jalview.structure.StructureCommandI; | |
74 | import jalview.structure.StructureImportSettings.TFType; | |
75 | import jalview.structure.StructureSelectionManager; | |
76 | import jalview.util.ColorUtils; | |
77 | import jalview.util.FileUtils; | |
78 | import jalview.util.HttpUtils; | |
79 | import jalview.util.ImageMaker; | |
80 | import jalview.util.ImageMaker.TYPE; | |
81 | import jalview.util.MessageManager; | |
82 | import jalview.util.Platform; | |
83 | import jalview.util.StringUtils; | |
84 | import jalview.util.imagemaker.BitmapImageSizing; | |
85 | ||
86 | public class Commands | |
87 | { | |
88 | Desktop desktop; | |
89 | ||
90 | private boolean headless; | |
91 | ||
92 | private ArgParser argParser; | |
93 | ||
94 | private Map<String, AlignFrame> afMap; | |
95 | ||
96 | private Map<String, List<StructureViewer>> svMap; | |
97 | ||
98 | private boolean commandArgsProvided = false; | |
99 | ||
100 | private boolean argsWereParsed = false; | |
101 | ||
102 | private List<String> errors = new ArrayList<>(); | |
103 | ||
104 | 130 | public Commands(ArgParser argparser, boolean headless) |
105 | { | |
106 | 130 | this(Desktop.instance, argparser, headless); |
107 | } | |
108 | ||
109 | 130 | public Commands(Desktop d, ArgParser argparser, boolean h) |
110 | { | |
111 | 130 | argParser = argparser; |
112 | 130 | headless = h; |
113 | 130 | desktop = d; |
114 | 130 | afMap = new HashMap<>(); |
115 | } | |
116 | ||
117 | 130 | protected boolean processArgs() |
118 | { | |
119 | 130 | if (argParser == null) |
120 | { | |
121 | 0 | return true; |
122 | } | |
123 | ||
124 | 130 | boolean theseArgsWereParsed = false; |
125 | ||
126 | 130 | if (argParser != null && argParser.getLinkedIds() != null) |
127 | { | |
128 | 130 | for (String id : argParser.getLinkedIds()) |
129 | { | |
130 | 155 | ArgValuesMap avm = argParser.getLinkedArgs(id); |
131 | 155 | theseArgsWereParsed = true; |
132 | 155 | boolean processLinkedOkay = processLinked(id); |
133 | 151 | theseArgsWereParsed &= processLinkedOkay; |
134 | ||
135 | 151 | processGroovyScript(id); |
136 | ||
137 | // wait around until alignFrame isn't busy | |
138 | 151 | AlignFrame af = afMap.get(id); |
139 | 652 | while (af != null && af.getViewport().isCalcInProgress()) |
140 | { | |
141 | 501 | try |
142 | { | |
143 | 501 | Thread.sleep(25); |
144 | } catch (Exception q) | |
145 | { | |
146 | } | |
147 | 501 | ; |
148 | } | |
149 | ||
150 | 151 | theseArgsWereParsed &= processImages(id); |
151 | ||
152 | 151 | if (processLinkedOkay) |
153 | { | |
154 | 151 | theseArgsWereParsed &= processOutput(id); |
155 | } | |
156 | ||
157 | // close ap | |
158 | 151 | if (avm.getBoolean(Arg.CLOSE)) |
159 | { | |
160 | 60 | af = afMap.get(id); |
161 | 60 | if (af != null) |
162 | { | |
163 | 60 | af.closeMenuItem_actionPerformed(true); |
164 | } | |
165 | } | |
166 | ||
167 | } | |
168 | ||
169 | } | |
170 | ||
171 | // report errors - if any | |
172 | 126 | String errorsRaised = errorsToString(); |
173 | 126 | if (errorsRaised.trim().length() > 0) |
174 | { | |
175 | 0 | Console.warn( |
176 | "The following errors and warnings occurred whilst processing files:\n" | |
177 | + errorsRaised); | |
178 | } | |
179 | // gui errors reported in Jalview | |
180 | ||
181 | 126 | if (argParser.getBoolean(Arg.QUIT)) |
182 | { | |
183 | 1 | Jalview.exit("Exiting due to " + Arg.QUIT.argString() + " argument.", |
184 | ExitCode.OK); | |
185 | 0 | return true; |
186 | } | |
187 | // carry on with jalview.bin.Jalview | |
188 | 125 | argsWereParsed = theseArgsWereParsed; |
189 | 125 | return argsWereParsed; |
190 | } | |
191 | ||
192 | 13 | public boolean commandArgsProvided() |
193 | { | |
194 | 13 | return commandArgsProvided; |
195 | } | |
196 | ||
197 | 137 | public boolean argsWereParsed() |
198 | { | |
199 | 137 | return argsWereParsed; |
200 | } | |
201 | ||
202 | 155 | protected boolean processLinked(String id) |
203 | { | |
204 | 155 | boolean theseArgsWereParsed = false; |
205 | 155 | ArgValuesMap avm = argParser.getLinkedArgs(id); |
206 | 155 | if (avm == null) |
207 | { | |
208 | 0 | return true; |
209 | } | |
210 | ||
211 | 155 | Boolean isError = Boolean.valueOf(false); |
212 | ||
213 | // set wrap, showSSAnnotations, showAnnotations and hideTFrows scope here so | |
214 | // it can be applied after structures are opened | |
215 | 155 | boolean wrap = false; |
216 | 155 | boolean showSSAnnotations = false; |
217 | 155 | boolean showAnnotations = false; |
218 | 155 | boolean hideTFrows = false; |
219 | 155 | AlignFrame af = null; |
220 | ||
221 | 155 | if (avm.containsArg(Arg.APPEND) || avm.containsArg(Arg.OPEN)) |
222 | { | |
223 | 155 | commandArgsProvided = true; |
224 | 155 | final long progress = System.currentTimeMillis(); |
225 | ||
226 | 155 | boolean first = true; |
227 | 155 | boolean progressBarSet = false; |
228 | // Combine the APPEND and OPEN files into one list, along with whether it | |
229 | // was APPEND or OPEN | |
230 | 155 | List<ArgValue> openAvList = new ArrayList<>(); |
231 | 155 | openAvList.addAll(avm.getArgValueList(Arg.OPEN)); |
232 | 155 | openAvList.addAll(avm.getArgValueList(Arg.APPEND)); |
233 | // sort avlist based on av.getArgIndex() | |
234 | 155 | Collections.sort(openAvList); |
235 | 155 | for (ArgValue av : openAvList) |
236 | { | |
237 | 176 | Arg a = av.getArg(); |
238 | 176 | SubVals sv = av.getSubVals(); |
239 | 176 | String openFile0 = av.getValue(); |
240 | 176 | String openFile = HttpUtils.equivalentJalviewUrl(openFile0); |
241 | 176 | if (openFile == null) |
242 | 0 | continue; |
243 | ||
244 | 176 | theseArgsWereParsed = true; |
245 | 176 | if (first) |
246 | { | |
247 | 155 | first = false; |
248 | 155 | if (!headless && desktop != null) |
249 | { | |
250 | 117 | SwingUtilities.invokeLater(new Runnable() |
251 | { | |
252 | 117 | @Override |
253 | public void run() | |
254 | { | |
255 | 117 | desktop.setProgressBar( |
256 | MessageManager.getString( | |
257 | "status.processing_commandline_args"), | |
258 | progress); | |
259 | ||
260 | } | |
261 | }); | |
262 | 117 | progressBarSet = true; |
263 | } | |
264 | } | |
265 | ||
266 | 176 | if (!Platform.isJS()) |
267 | /** | |
268 | * ignore in JavaScript -- can't just file existence - could load it? | |
269 | * | |
270 | * @j2sIgnore | |
271 | */ | |
272 | { | |
273 | 176 | if (!HttpUtils.isPlausibleUri(openFile)) |
274 | { | |
275 | 176 | if (!(new File(openFile)).exists()) |
276 | { | |
277 | 0 | addError("Can't find file '" + openFile + "'"); |
278 | 0 | isError = true; |
279 | 0 | continue; |
280 | } | |
281 | } | |
282 | } | |
283 | ||
284 | 176 | DataSourceType protocol = AppletFormatAdapter |
285 | .checkProtocol(openFile); | |
286 | ||
287 | 176 | FileFormatI format = null; |
288 | 176 | try |
289 | { | |
290 | 176 | format = new IdentifyFile().identify(openFile, protocol); |
291 | } catch (FileNotFoundException e0) | |
292 | { | |
293 | 0 | addError((protocol == DataSourceType.URL ? "File at URL" : "File") |
294 | + " '" + openFile + "' not found"); | |
295 | 0 | isError = true; |
296 | 0 | continue; |
297 | } catch (FileFormatException e1) | |
298 | { | |
299 | 0 | addError("Unknown file format for '" + openFile + "'"); |
300 | 0 | isError = true; |
301 | 0 | continue; |
302 | } | |
303 | ||
304 | 176 | af = afMap.get(id); |
305 | // When to open a new AlignFrame | |
306 | 176 | if (af == null || "true".equals(av.getSubVal("new")) |
307 | || a == Arg.OPEN || format == FileFormat.Jalview) | |
308 | { | |
309 | 156 | if (a == Arg.OPEN) |
310 | { | |
311 | 133 | Jalview.testoutput(argParser, Arg.OPEN, "examples/uniref50.fa", |
312 | openFile); | |
313 | } | |
314 | ||
315 | 156 | Console.debug( |
316 | "Opening '" + openFile + "' in new alignment frame"); | |
317 | 156 | FileLoader fileLoader = new FileLoader(!headless); |
318 | 156 | boolean xception = false; |
319 | 156 | try |
320 | { | |
321 | 156 | af = fileLoader.LoadFileWaitTillLoaded(openFile, protocol, |
322 | format); | |
323 | 152 | if (!openFile.equals(openFile0)) |
324 | { | |
325 | 0 | af.setTitle(openFile0); |
326 | } | |
327 | } catch (Throwable thr) | |
328 | { | |
329 | 0 | xception = true; |
330 | 0 | addError("Couldn't open '" + openFile + "' as " + format + " " |
331 | + thr.getLocalizedMessage() | |
332 | + " (Enable debug for full stack trace)"); | |
333 | 0 | isError = true; |
334 | 0 | Console.debug("Exception when opening '" + openFile + "'", thr); |
335 | } finally | |
336 | { | |
337 | 152 | if (af == null && !xception) |
338 | { | |
339 | 0 | addInfo("Ignoring '" + openFile |
340 | + "' - no alignment data found."); | |
341 | 0 | continue; |
342 | } | |
343 | } | |
344 | ||
345 | // colour alignment | |
346 | 152 | String colour = null; |
347 | 152 | if (avm.containsArg(Arg.COLOUR) |
348 | || !(format == FileFormat.Jalview)) | |
349 | { | |
350 | 152 | colour = avm.getFromSubValArgOrPref(av, Arg.COLOUR, sv, null, |
351 | "DEFAULT_COLOUR_PROT", null); | |
352 | } | |
353 | 152 | if (colour != null) |
354 | { | |
355 | 13 | this.colourAlignFrame(af, colour); |
356 | } | |
357 | ||
358 | // Change alignment frame title | |
359 | 152 | String title = avm.getFromSubValArgOrPref(av, Arg.TITLE, sv, null, |
360 | null, null); | |
361 | 152 | if (title != null) |
362 | { | |
363 | 0 | af.setTitle(title); |
364 | 0 | Jalview.testoutput(argParser, Arg.TITLE, "test title", title); |
365 | } | |
366 | ||
367 | // Add features | |
368 | 152 | String featuresfile = avm.getValueFromSubValOrArg(av, |
369 | Arg.FEATURES, sv); | |
370 | 152 | if (featuresfile != null) |
371 | { | |
372 | 1 | af.parseFeaturesFile(featuresfile, |
373 | AppletFormatAdapter.checkProtocol(featuresfile)); | |
374 | 1 | Jalview.testoutput(argParser, Arg.FEATURES, |
375 | "examples/testdata/plantfdx.features", featuresfile); | |
376 | } | |
377 | ||
378 | // Add annotations from file | |
379 | 152 | String annotationsfile = avm.getValueFromSubValOrArg(av, |
380 | Arg.ANNOTATIONS, sv); | |
381 | 152 | if (annotationsfile != null) |
382 | { | |
383 | 1 | af.loadJalviewDataFile(annotationsfile, null, null, null); |
384 | 1 | Jalview.testoutput(argParser, Arg.ANNOTATIONS, |
385 | "examples/testdata/plantfdx.annotations", | |
386 | annotationsfile); | |
387 | } | |
388 | ||
389 | // Set or clear the sortbytree flag | |
390 | 152 | boolean sortbytree = avm.getBoolFromSubValOrArg(Arg.SORTBYTREE, |
391 | sv); | |
392 | 152 | if (sortbytree) |
393 | { | |
394 | 1 | af.getViewport().setSortByTree(true); |
395 | 1 | Jalview.testoutput(argParser, Arg.SORTBYTREE); |
396 | } | |
397 | ||
398 | // Load tree from file | |
399 | 152 | String treefile = avm.getValueFromSubValOrArg(av, Arg.TREE, sv); |
400 | 152 | if (treefile != null) |
401 | { | |
402 | 1 | try |
403 | { | |
404 | 1 | NewickFile nf = new NewickFile(treefile, |
405 | AppletFormatAdapter.checkProtocol(treefile)); | |
406 | 1 | af.getViewport().setCurrentTree( |
407 | af.showNewickTree(nf, treefile).getTree()); | |
408 | 1 | Jalview.testoutput(argParser, Arg.TREE, |
409 | "examples/testdata/uniref50_test_tree", treefile); | |
410 | } catch (IOException e) | |
411 | { | |
412 | 0 | addError("Couldn't add tree " + treefile, e); |
413 | 0 | isError = true; |
414 | } | |
415 | } | |
416 | ||
417 | // Show secondary structure annotations? | |
418 | 152 | showSSAnnotations = avm.getFromSubValArgOrPref( |
419 | Arg.SHOWSSANNOTATIONS, av.getSubVals(), null, | |
420 | "STRUCT_FROM_PDB", true); | |
421 | // Show sequence annotations? | |
422 | 152 | showAnnotations = avm.getFromSubValArgOrPref(Arg.SHOWANNOTATIONS, |
423 | av.getSubVals(), null, "SHOW_ANNOTATIONS", true); | |
424 | // hide the Temperature Factor row? | |
425 | 152 | hideTFrows = (avm.getBoolean(Arg.NOTEMPFAC)); |
426 | ||
427 | // showSSAnnotations, showAnnotations, hideTFrows used after opening | |
428 | // structure | |
429 | ||
430 | // wrap alignment? do this last for formatting reasons | |
431 | 152 | wrap = avm.getFromSubValArgOrPref(Arg.WRAP, sv, null, |
432 | "WRAP_ALIGNMENT", false); | |
433 | // af.setWrapFormat(wrap) is applied after structures are opened for | |
434 | // annotation reasons | |
435 | ||
436 | // store the AlignFrame for this id | |
437 | 152 | afMap.put(id, af); |
438 | ||
439 | // is it its own structure file? | |
440 | 152 | if (format.isStructureFile()) |
441 | { | |
442 | 2 | StructureSelectionManager ssm = StructureSelectionManager |
443 | .getStructureSelectionManager(Desktop.instance); | |
444 | 2 | SequenceI seq = af.alignPanel.getAlignment().getSequenceAt(0); |
445 | 2 | ssm.computeMapping(false, new SequenceI[] { seq }, null, |
446 | openFile, DataSourceType.FILE, null, null, null, false); | |
447 | } | |
448 | } | |
449 | else | |
450 | { | |
451 | 20 | Console.debug( |
452 | "Opening '" + openFile + "' in existing alignment frame"); | |
453 | ||
454 | 20 | DataSourceType dst = HttpUtils.startsWithHttpOrHttps(openFile) |
455 | ? DataSourceType.URL | |
456 | : DataSourceType.FILE; | |
457 | ||
458 | 20 | FileLoader fileLoader = new FileLoader(!headless); |
459 | 20 | fileLoader.LoadFile(af.getCurrentView(), openFile, dst, null, |
460 | false); | |
461 | } | |
462 | ||
463 | 172 | Console.debug("Command " + Arg.APPEND + " executed successfully!"); |
464 | ||
465 | } | |
466 | 151 | if (first) // first=true means nothing opened |
467 | { | |
468 | 0 | if (headless) |
469 | { | |
470 | 0 | Jalview.exit("Could not open any files in headless mode", |
471 | ExitCode.NO_FILES); | |
472 | } | |
473 | else | |
474 | { | |
475 | 0 | Console.info("No more files to open"); |
476 | } | |
477 | } | |
478 | 151 | if (progressBarSet && desktop != null) |
479 | 113 | desktop.setProgressBar(null, progress); |
480 | ||
481 | } | |
482 | ||
483 | // open the structure (from same PDB file or given PDBfile) | |
484 | 151 | if (!avm.getBoolean(Arg.NOSTRUCTURE)) |
485 | { | |
486 | 151 | if (af == null) |
487 | { | |
488 | 0 | af = afMap.get(id); |
489 | } | |
490 | 151 | if (avm.containsArg(Arg.STRUCTURE)) |
491 | { | |
492 | 28 | commandArgsProvided = true; |
493 | 28 | for (ArgValue structureAv : avm.getArgValueList(Arg.STRUCTURE)) |
494 | { | |
495 | 42 | argParser.setStructureFilename(null); |
496 | 42 | String val = structureAv.getValue(); |
497 | 42 | SubVals subVals = structureAv.getSubVals(); |
498 | 42 | int argIndex = structureAv.getArgIndex(); |
499 | 42 | SequenceI seq = getSpecifiedSequence(af, avm, structureAv); |
500 | 42 | if (seq == null) |
501 | { | |
502 | // Could not find sequence from subId, let's assume the first | |
503 | // sequence in the alignframe | |
504 | 26 | AlignmentI al = af.getCurrentView().getAlignment(); |
505 | 26 | seq = al.getSequenceAt(0); |
506 | } | |
507 | ||
508 | 42 | if (seq == null) |
509 | { | |
510 | 0 | addWarn("Could not find sequence for argument " |
511 | + Arg.STRUCTURE.argString() + "=" + val); | |
512 | 0 | continue; |
513 | } | |
514 | 42 | String structureFilename = null; |
515 | 42 | File structureFile = null; |
516 | 42 | if (subVals.getContent() != null |
517 | && subVals.getContent().length() != 0) | |
518 | { | |
519 | 42 | structureFilename = subVals.getContent(); |
520 | 42 | Console.debug("Using structure file (from argument) '" |
521 | + structureFilename + "'"); | |
522 | 42 | structureFile = new File(structureFilename); |
523 | } | |
524 | /* THIS DOESN'T WORK */ | |
525 | 0 | else if (seq.getAllPDBEntries() != null |
526 | && seq.getAllPDBEntries().size() > 0) | |
527 | { | |
528 | 0 | structureFile = new File( |
529 | seq.getAllPDBEntries().elementAt(0).getFile()); | |
530 | 0 | if (structureFile != null) |
531 | { | |
532 | 0 | Console.debug("Using structure file (from sequence) '" |
533 | + structureFile.getAbsolutePath() + "'"); | |
534 | } | |
535 | 0 | structureFilename = structureFile.getAbsolutePath(); |
536 | } | |
537 | ||
538 | 42 | if (structureFilename == null || structureFile == null) |
539 | { | |
540 | 0 | addWarn("Not provided structure file with '" + val + "'"); |
541 | 0 | continue; |
542 | } | |
543 | ||
544 | 42 | if (!structureFile.exists()) |
545 | { | |
546 | 0 | addWarn("Structure file '" + structureFile.getAbsoluteFile() |
547 | + "' not found."); | |
548 | 0 | continue; |
549 | } | |
550 | ||
551 | 42 | Console.debug("Using structure file " |
552 | + structureFile.getAbsolutePath()); | |
553 | ||
554 | 42 | argParser.setStructureFilename(structureFilename); |
555 | ||
556 | // open structure view | |
557 | 42 | AlignmentPanel ap = af.alignPanel; |
558 | 42 | if (headless) |
559 | { | |
560 | 10 | Cache.setProperty(Preferences.STRUCTURE_DISPLAY, |
561 | StructureViewer.ViewerType.JMOL.toString()); | |
562 | } | |
563 | ||
564 | 42 | String structureFilepath = structureFile.getAbsolutePath(); |
565 | ||
566 | // get PAEMATRIX file and label from subvals or Arg.PAEMATRIX | |
567 | 42 | String paeFilepath = avm.getFromSubValArgOrPrefWithSubstitutions( |
568 | argParser, Arg.PAEMATRIX, ArgValuesMap.Position.AFTER, | |
569 | structureAv, subVals, null, null, null); | |
570 | 42 | if (paeFilepath != null) |
571 | { | |
572 | 26 | File paeFile = new File(paeFilepath); |
573 | ||
574 | 26 | try |
575 | { | |
576 | 26 | paeFilepath = paeFile.getCanonicalPath(); |
577 | } catch (IOException e) | |
578 | { | |
579 | 0 | paeFilepath = paeFile.getAbsolutePath(); |
580 | 0 | addWarn("Problem with the PAE file path: '" |
581 | + paeFile.getPath() + "'"); | |
582 | } | |
583 | } | |
584 | ||
585 | // showing annotations from structure file or not | |
586 | 42 | boolean ssFromStructure = avm.getFromSubValArgOrPref( |
587 | Arg.SHOWSSANNOTATIONS, subVals, null, "STRUCT_FROM_PDB", | |
588 | true); | |
589 | ||
590 | // get TEMPFAC type from subvals or Arg.TEMPFAC in case user Adds | |
591 | // reference annotations | |
592 | 42 | String tftString = avm.getFromSubValArgOrPrefWithSubstitutions( |
593 | argParser, Arg.TEMPFAC, ArgValuesMap.Position.AFTER, | |
594 | structureAv, subVals, null, null, null); | |
595 | 42 | boolean notempfac = avm.getFromSubValArgOrPref(Arg.NOTEMPFAC, |
596 | subVals, null, "ADD_TEMPFACT_ANN", false, true); | |
597 | 42 | TFType tft = notempfac ? null : TFType.DEFAULT; |
598 | 42 | if (tftString != null && !notempfac) |
599 | { | |
600 | // get kind of temperature factor annotation | |
601 | 12 | try |
602 | { | |
603 | 12 | tft = TFType.valueOf(tftString.toUpperCase(Locale.ROOT)); |
604 | 12 | Console.debug("Obtained Temperature Factor type of '" + tft |
605 | + "' for structure '" + structureFilepath + "'"); | |
606 | } catch (IllegalArgumentException e) | |
607 | { | |
608 | // Just an error message! | |
609 | 0 | StringBuilder sb = new StringBuilder().append("Cannot set ") |
610 | .append(Arg.TEMPFAC.argString()).append(" to '") | |
611 | .append(tft) | |
612 | .append("', ignoring. Valid values are: "); | |
613 | 0 | Iterator<TFType> it = Arrays.stream(TFType.values()) |
614 | .iterator(); | |
615 | 0 | while (it.hasNext()) |
616 | { | |
617 | 0 | sb.append(it.next().toString().toLowerCase(Locale.ROOT)); |
618 | 0 | if (it.hasNext()) |
619 | 0 | sb.append(", "); |
620 | } | |
621 | 0 | addWarn(sb.toString()); |
622 | } | |
623 | } | |
624 | ||
625 | 42 | String sViewerName = avm.getFromSubValArgOrPref( |
626 | Arg.STRUCTUREVIEWER, ArgValuesMap.Position.AFTER, | |
627 | structureAv, subVals, null, null, "jmol"); | |
628 | 42 | ViewerType viewerType = ViewerType.getFromString(sViewerName); |
629 | ||
630 | // TODO use ssFromStructure | |
631 | 42 | StructureViewer structureViewer = StructureChooser |
632 | .openStructureFileForSequence(null, null, ap, seq, false, | |
633 | structureFilepath, tft, paeFilepath, false, | |
634 | ssFromStructure, false, viewerType); | |
635 | ||
636 | 42 | if (structureViewer == null) |
637 | { | |
638 | 9 | if (!StringUtils.equalsIgnoreCase(sViewerName, "none")) |
639 | { | |
640 | 0 | addError("Failed to import and open structure view for file '" |
641 | + structureFile + "'."); | |
642 | } | |
643 | 9 | continue; |
644 | } | |
645 | 33 | try |
646 | { | |
647 | 33 | long tries = 1000; |
648 | 307 | while (structureViewer.isBusy() && tries > 0) |
649 | { | |
650 | 274 | Thread.sleep(25); |
651 | 274 | if (structureViewer.isBusy()) |
652 | { | |
653 | 241 | tries--; |
654 | 241 | Console.debug( |
655 | "Waiting for viewer for " + structureFilepath); | |
656 | } | |
657 | } | |
658 | 33 | if (tries == 0 && structureViewer.isBusy()) |
659 | { | |
660 | 0 | addWarn("Gave up waiting for structure viewer to load file '" |
661 | + structureFile | |
662 | + "'. Something may have gone wrong."); | |
663 | } | |
664 | } catch (Exception x) | |
665 | { | |
666 | 0 | addError("Exception whilst waiting for structure viewer " |
667 | + structureFilepath, x); | |
668 | 0 | isError = true; |
669 | } | |
670 | ||
671 | // add StructureViewer to svMap list | |
672 | 33 | if (svMap == null) |
673 | { | |
674 | 23 | svMap = new HashMap<>(); |
675 | } | |
676 | 33 | if (svMap.get(id) == null) |
677 | { | |
678 | 27 | svMap.put(id, new ArrayList<>()); |
679 | } | |
680 | 33 | svMap.get(id).add(structureViewer); |
681 | ||
682 | 33 | Console.debug( |
683 | "Successfully opened viewer for " + structureFilepath); | |
684 | ||
685 | 33 | if (avm.containsArg(Arg.STRUCTUREIMAGE)) |
686 | { | |
687 | 10 | for (ArgValue structureImageArgValue : avm |
688 | .getArgValueListFromSubValOrArg(structureAv, | |
689 | Arg.STRUCTUREIMAGE, subVals)) | |
690 | { | |
691 | 10 | String structureImageFilename = argParser.makeSubstitutions( |
692 | structureImageArgValue.getValue(), id, true); | |
693 | 10 | if (structureViewer != null && structureImageFilename != null) |
694 | { | |
695 | 10 | SubVals structureImageSubVals = null; |
696 | 10 | structureImageSubVals = structureImageArgValue.getSubVals(); |
697 | 10 | File structureImageFile = new File(structureImageFilename); |
698 | 10 | String width = avm.getValueFromSubValOrArg( |
699 | structureImageArgValue, Arg.WIDTH, | |
700 | structureImageSubVals); | |
701 | 10 | String height = avm.getValueFromSubValOrArg( |
702 | structureImageArgValue, Arg.HEIGHT, | |
703 | structureImageSubVals); | |
704 | 10 | String scale = avm.getValueFromSubValOrArg( |
705 | structureImageArgValue, Arg.SCALE, | |
706 | structureImageSubVals); | |
707 | 10 | String renderer = avm.getValueFromSubValOrArg( |
708 | structureImageArgValue, Arg.TEXTRENDERER, | |
709 | structureImageSubVals); | |
710 | 10 | String typeS = avm.getValueFromSubValOrArg( |
711 | structureImageArgValue, Arg.TYPE, | |
712 | structureImageSubVals); | |
713 | 10 | if (typeS == null || typeS.length() == 0) |
714 | { | |
715 | 10 | typeS = FileUtils.getExtension(structureImageFile); |
716 | } | |
717 | 10 | TYPE imageType; |
718 | 10 | try |
719 | { | |
720 | 10 | imageType = Enum.valueOf(TYPE.class, |
721 | typeS.toUpperCase(Locale.ROOT)); | |
722 | } catch (IllegalArgumentException e) | |
723 | { | |
724 | 0 | addWarn("Do not know image format '" + typeS |
725 | + "', using PNG"); | |
726 | 0 | imageType = TYPE.PNG; |
727 | } | |
728 | 10 | BitmapImageSizing userBis = ImageMaker |
729 | .parseScaleWidthHeightStrings(scale, width, height); | |
730 | ||
731 | ///// | |
732 | // DON'T TRY TO EXPORT IF VIEWER IS UNSUPPORTED | |
733 | 10 | if (viewerType != ViewerType.JMOL) |
734 | { | |
735 | 0 | addWarn("Cannot export image for structure viewer " |
736 | + viewerType.name() + " yet"); | |
737 | 0 | continue; |
738 | } | |
739 | ||
740 | ///// | |
741 | // Apply the temporary colourscheme to the linked alignment | |
742 | // TODO: enhance for multiple linked alignments. | |
743 | ||
744 | 10 | String imageColour = avm.getValueFromSubValOrArg( |
745 | structureImageArgValue, Arg.IMAGECOLOUR, | |
746 | structureImageSubVals); | |
747 | 10 | ColourSchemeI originalColourScheme = this |
748 | .getColourScheme(af); | |
749 | 10 | this.colourAlignFrame(af, imageColour); |
750 | ||
751 | ///// | |
752 | // custom image background colour | |
753 | ||
754 | 10 | String bgcolourstring = avm.getValueFromSubValOrArg( |
755 | structureImageArgValue, Arg.BGCOLOUR, | |
756 | structureImageSubVals); | |
757 | 10 | Color bgcolour = null; |
758 | 10 | if (bgcolourstring != null && bgcolourstring.length() > 0) |
759 | { | |
760 | 0 | bgcolour = ColorUtils.parseColourString(bgcolourstring); |
761 | 0 | if (bgcolour == null) |
762 | { | |
763 | 0 | Console.warn( |
764 | "Background colour string '" + bgcolourstring | |
765 | + "' not recognised -- using default"); | |
766 | } | |
767 | } | |
768 | ||
769 | 10 | JalviewStructureDisplayI sview = structureViewer |
770 | .getJalviewStructureDisplay(); | |
771 | ||
772 | 10 | File sessionToRestore = null; |
773 | ||
774 | 10 | List<StructureCommandI> extraCommands = new ArrayList<>(); |
775 | ||
776 | 10 | if (extraCommands.size() > 0 || bgcolour != null) |
777 | { | |
778 | 0 | try |
779 | { | |
780 | 0 | sessionToRestore = sview.saveSession(); |
781 | } catch (Throwable t) | |
782 | { | |
783 | 0 | Console.warn( |
784 | "Unable to save temporary session file before custom structure view export operation."); | |
785 | } | |
786 | } | |
787 | ||
788 | //// | |
789 | // Do temporary ops | |
790 | ||
791 | 10 | if (bgcolour != null) |
792 | { | |
793 | 0 | sview.getBinding().setBackgroundColour(bgcolour); |
794 | } | |
795 | ||
796 | 10 | sview.getBinding().executeCommands(extraCommands, false, |
797 | "Executing Custom Commands"); | |
798 | ||
799 | // and export the view as an image | |
800 | 10 | boolean success = this.checksBeforeWritingToFile(avm, |
801 | subVals, false, structureImageFilename, | |
802 | "structure image", isError); | |
803 | ||
804 | 10 | if (!success) |
805 | { | |
806 | 0 | continue; |
807 | } | |
808 | 10 | Console.debug("Rendering image to " + structureImageFile); |
809 | // | |
810 | // TODO - extend StructureViewer / Binding with makePDBImage so | |
811 | // we can do this with every viewer | |
812 | // | |
813 | ||
814 | 10 | try |
815 | { | |
816 | // We don't expect class cast exception | |
817 | 10 | AppJmol jmol = (AppJmol) sview; |
818 | 10 | jmol.makePDBImage(structureImageFile, imageType, renderer, |
819 | userBis); | |
820 | 10 | Console.info("Exported structure image to " |
821 | + structureImageFile); | |
822 | ||
823 | // RESTORE SESSION AFTER EXPORT IF NEED BE | |
824 | 10 | if (sessionToRestore != null) |
825 | { | |
826 | 0 | Console.debug( |
827 | "Restoring session from " + sessionToRestore); | |
828 | ||
829 | 0 | sview.getBinding().restoreSession( |
830 | sessionToRestore.getAbsolutePath()); | |
831 | ||
832 | } | |
833 | } catch (ImageOutputException ioexec) | |
834 | { | |
835 | 0 | addError( |
836 | "Unexpected error when restoring structure viewer session after custom view operations."); | |
837 | 0 | isError = true; |
838 | 0 | continue; |
839 | } finally | |
840 | { | |
841 | 10 | try |
842 | { | |
843 | 10 | this.colourAlignFrame(af, originalColourScheme); |
844 | } catch (Exception t) | |
845 | { | |
846 | 0 | addError( |
847 | "Unexpected error when restoring colourscheme to alignment after temporary change for export.", | |
848 | t); | |
849 | } | |
850 | } | |
851 | } | |
852 | } | |
853 | } | |
854 | 33 | argParser.setStructureFilename(null); |
855 | } | |
856 | } | |
857 | } | |
858 | ||
859 | 151 | if (af == null) |
860 | { | |
861 | 0 | af = afMap.get(id); |
862 | } | |
863 | // many of jalview's format/layout methods are only thread safe on the | |
864 | // swingworker thread. | |
865 | // all these methods should be on the alignViewController so it can | |
866 | // coordinate such details | |
867 | 151 | if (headless) |
868 | { | |
869 | 38 | showOrHideAnnotations(af, showSSAnnotations, showAnnotations, |
870 | hideTFrows); | |
871 | } | |
872 | else | |
873 | { | |
874 | 113 | try |
875 | { | |
876 | 113 | AlignFrame _af = af; |
877 | 113 | final boolean _showSSAnnotations = showSSAnnotations; |
878 | 113 | final boolean _showAnnotations = showAnnotations; |
879 | 113 | final boolean _hideTFrows = hideTFrows; |
880 | 113 | SwingUtilities.invokeAndWait(() -> { |
881 | 113 | showOrHideAnnotations(_af, _showSSAnnotations, _showAnnotations, |
882 | _hideTFrows); | |
883 | } | |
884 | ||
885 | ); | |
886 | } catch (Exception x) | |
887 | { | |
888 | 0 | Console.warn( |
889 | "Unexpected exception adjusting annotation row visibility.", | |
890 | x); | |
891 | } | |
892 | } | |
893 | ||
894 | 151 | if (wrap) |
895 | { | |
896 | 0 | if (af == null) |
897 | { | |
898 | 0 | af = afMap.get(id); |
899 | } | |
900 | 0 | if (af != null) |
901 | { | |
902 | 0 | af.setWrapFormat(wrap, true); |
903 | } | |
904 | } | |
905 | ||
906 | /* | |
907 | boolean doShading = avm.getBoolean(Arg.TEMPFAC_SHADING); | |
908 | if (doShading) | |
909 | { | |
910 | AlignFrame af = afMap.get(id); | |
911 | for (AlignmentAnnotation aa : af.alignPanel.getAlignment() | |
912 | .findAnnotation(PDBChain.class.getName().toString())) | |
913 | { | |
914 | AnnotationColourGradient acg = new AnnotationColourGradient(aa, | |
915 | af.alignPanel.av.getGlobalColourScheme(), 0); | |
916 | acg.setSeqAssociated(true); | |
917 | af.changeColour(acg); | |
918 | Console.info("Changed colour " + acg.toString()); | |
919 | } | |
920 | } | |
921 | */ | |
922 | ||
923 | 151 | return theseArgsWereParsed && !isError; |
924 | } | |
925 | ||
926 | 151 | private static void showOrHideAnnotations(AlignFrame af, |
927 | boolean showSSAnnotations, boolean showAnnotations, | |
928 | boolean hideTFrows) | |
929 | { | |
930 | 151 | af.setAnnotationsVisibility(showSSAnnotations, true, false); |
931 | 151 | af.setAnnotationsVisibility(showAnnotations, false, true); |
932 | ||
933 | // show temperature factor annotations? | |
934 | 151 | if (hideTFrows) |
935 | { | |
936 | // do this better (annotation types?) | |
937 | 0 | List<String> hideThese = new ArrayList<>(); |
938 | 0 | hideThese.add("Temperature Factor"); |
939 | 0 | hideThese.add(AlphaFoldAnnotationRowBuilder.LABEL); |
940 | 0 | AlignmentUtils.showOrHideSequenceAnnotations( |
941 | af.getCurrentView().getAlignment(), hideThese, null, false, | |
942 | false); | |
943 | } | |
944 | } | |
945 | ||
946 | 151 | protected void processGroovyScript(String id) |
947 | { | |
948 | 151 | ArgValuesMap avm = argParser.getLinkedArgs(id); |
949 | 151 | AlignFrame af = afMap.get(id); |
950 | ||
951 | 151 | if (avm != null && !avm.containsArg(Arg.GROOVY)) |
952 | { | |
953 | // nothing to do | |
954 | 151 | return; |
955 | } | |
956 | ||
957 | 0 | if (af == null) |
958 | { | |
959 | 0 | addWarn("Groovy script does not have an alignment window. Proceeding with caution!"); |
960 | } | |
961 | ||
962 | 0 | if (avm.containsArg(Arg.GROOVY)) |
963 | { | |
964 | 0 | for (ArgValue groovyAv : avm.getArgValueList(Arg.GROOVY)) |
965 | { | |
966 | 0 | String groovyscript = groovyAv.getValue(); |
967 | 0 | if (groovyscript != null) |
968 | { | |
969 | // Execute the groovy script after we've done all the rendering stuff | |
970 | // and before any images or figures are generated. | |
971 | 0 | Console.info("Executing script " + groovyscript); |
972 | 0 | Jalview.getInstance().executeGroovyScript(groovyscript, af); |
973 | } | |
974 | } | |
975 | } | |
976 | } | |
977 | ||
978 | 151 | protected boolean processImages(String id) |
979 | { | |
980 | 151 | ArgValuesMap avm = argParser.getLinkedArgs(id); |
981 | 151 | AlignFrame af = afMap.get(id); |
982 | ||
983 | 151 | if (avm != null && !avm.containsArg(Arg.IMAGE)) |
984 | { | |
985 | // nothing to do | |
986 | 121 | return true; |
987 | } | |
988 | ||
989 | 30 | if (af == null) |
990 | { | |
991 | 0 | addWarn("Do not have an alignment window to create image from (id=" |
992 | + id + "). Not proceeding."); | |
993 | 0 | return false; |
994 | } | |
995 | ||
996 | 30 | Boolean isError = Boolean.valueOf(false); |
997 | 30 | if (avm.containsArg(Arg.IMAGE)) |
998 | { | |
999 | 30 | for (ArgValue imageAv : avm.getArgValueList(Arg.IMAGE)) |
1000 | { | |
1001 | 30 | String val = imageAv.getValue(); |
1002 | 30 | SubVals imageSubVals = imageAv.getSubVals(); |
1003 | 30 | String fileName = imageSubVals.getContent(); |
1004 | 30 | File file = new File(fileName); |
1005 | 30 | String name = af.getName(); |
1006 | 30 | String renderer = avm.getValueFromSubValOrArg(imageAv, |
1007 | Arg.TEXTRENDERER, imageSubVals); | |
1008 | 30 | if (renderer == null) |
1009 | 30 | renderer = "text"; |
1010 | 30 | String type = "png"; // default |
1011 | ||
1012 | 30 | String scale = avm.getValueFromSubValOrArg(imageAv, Arg.SCALE, |
1013 | imageSubVals); | |
1014 | 30 | String width = avm.getValueFromSubValOrArg(imageAv, Arg.WIDTH, |
1015 | imageSubVals); | |
1016 | 30 | String height = avm.getValueFromSubValOrArg(imageAv, Arg.HEIGHT, |
1017 | imageSubVals); | |
1018 | 30 | BitmapImageSizing userBis = ImageMaker |
1019 | .parseScaleWidthHeightStrings(scale, width, height); | |
1020 | ||
1021 | 30 | type = avm.getValueFromSubValOrArg(imageAv, Arg.TYPE, imageSubVals); |
1022 | 30 | if (type == null && fileName != null) |
1023 | { | |
1024 | 30 | for (String ext : new String[] { "svg", "png", "html", "eps" }) |
1025 | { | |
1026 | 120 | if (fileName.toLowerCase(Locale.ROOT).endsWith("." + ext)) |
1027 | { | |
1028 | 30 | type = ext; |
1029 | } | |
1030 | } | |
1031 | } | |
1032 | // for moment we disable JSON export | |
1033 | 30 | Cache.setPropsAreReadOnly(true); |
1034 | 30 | Cache.setProperty("EXPORT_EMBBED_BIOJSON", "false"); |
1035 | ||
1036 | 30 | String imageColour = avm.getValueFromSubValOrArg(imageAv, |
1037 | Arg.IMAGECOLOUR, imageSubVals); | |
1038 | 30 | ColourSchemeI originalColourScheme = this.getColourScheme(af); |
1039 | 30 | this.colourAlignFrame(af, imageColour); |
1040 | ||
1041 | 30 | Console.info("Writing " + file); |
1042 | ||
1043 | 30 | boolean success = checksBeforeWritingToFile(avm, imageSubVals, |
1044 | false, fileName, "image", isError); | |
1045 | 30 | if (!success) |
1046 | { | |
1047 | 0 | continue; |
1048 | } | |
1049 | ||
1050 | 30 | try |
1051 | { | |
1052 | 30 | switch (type) |
1053 | { | |
1054 | ||
1055 | 1 | case "svg": |
1056 | 1 | Console.debug("Outputting type '" + type + "' to " + fileName); |
1057 | 1 | af.createSVG(file, renderer); |
1058 | 1 | break; |
1059 | ||
1060 | 23 | case "png": |
1061 | 23 | Console.debug("Outputting type '" + type + "' to " + fileName); |
1062 | 23 | af.createPNG(file, null, userBis); |
1063 | 23 | break; |
1064 | ||
1065 | 1 | case "html": |
1066 | 1 | Console.debug("Outputting type '" + type + "' to " + fileName); |
1067 | 1 | HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel); |
1068 | 1 | htmlSVG.exportHTML(fileName, renderer); |
1069 | 1 | break; |
1070 | ||
1071 | 0 | case "biojs": |
1072 | 0 | Console.debug( |
1073 | "Outputting BioJS MSA Viwer HTML file: " + fileName); | |
1074 | 0 | try |
1075 | { | |
1076 | 0 | BioJsHTMLOutput.refreshVersionInfo( |
1077 | BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY); | |
1078 | } catch (URISyntaxException e) | |
1079 | { | |
1080 | 0 | e.printStackTrace(); |
1081 | } | |
1082 | 0 | BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel); |
1083 | 0 | bjs.exportHTML(fileName); |
1084 | 0 | break; |
1085 | ||
1086 | 5 | case "eps": |
1087 | 5 | Console.debug("Outputting EPS file: " + fileName); |
1088 | 5 | af.createEPS(file, renderer); |
1089 | 5 | break; |
1090 | ||
1091 | 0 | case "imagemap": |
1092 | 0 | Console.debug("Outputting ImageMap file: " + fileName); |
1093 | 0 | af.createImageMap(file, name); |
1094 | 0 | break; |
1095 | ||
1096 | 0 | default: |
1097 | 0 | addWarn(Arg.IMAGE.argString() + " type '" + type |
1098 | + "' not known. Ignoring"); | |
1099 | 0 | break; |
1100 | } | |
1101 | } catch (Exception ioex) | |
1102 | { | |
1103 | 0 | addError("Unexpected error during export to '" + fileName + "'", |
1104 | ioex); | |
1105 | 0 | isError = true; |
1106 | } | |
1107 | ||
1108 | 30 | this.colourAlignFrame(af, originalColourScheme); |
1109 | } | |
1110 | } | |
1111 | 30 | return !isError; |
1112 | } | |
1113 | ||
1114 | 151 | protected boolean processOutput(String id) |
1115 | { | |
1116 | 151 | ArgValuesMap avm = argParser.getLinkedArgs(id); |
1117 | 151 | AlignFrame af = afMap.get(id); |
1118 | ||
1119 | 151 | if (avm != null && !avm.containsArg(Arg.OUTPUT)) |
1120 | { | |
1121 | // nothing to do | |
1122 | 77 | return true; |
1123 | } | |
1124 | ||
1125 | 74 | if (af == null) |
1126 | { | |
1127 | 0 | addWarn("Do not have an alignment window (id=" + id |
1128 | + "). Not proceeding."); | |
1129 | 0 | return false; |
1130 | } | |
1131 | ||
1132 | 74 | Boolean isError = Boolean.valueOf(false); |
1133 | ||
1134 | 74 | if (avm.containsArg(Arg.OUTPUT)) |
1135 | { | |
1136 | 74 | for (ArgValue av : avm.getArgValueList(Arg.OUTPUT)) |
1137 | { | |
1138 | 74 | String val = av.getValue(); |
1139 | 74 | SubVals subVals = av.getSubVals(); |
1140 | 74 | String fileName = subVals.getContent(); |
1141 | 74 | boolean stdout = ArgParser.STDOUTFILENAME.equals(fileName); |
1142 | 74 | File file = new File(fileName); |
1143 | ||
1144 | 74 | String name = af.getName(); |
1145 | 74 | String format = avm.getValueFromSubValOrArg(av, Arg.FORMAT, |
1146 | subVals); | |
1147 | 74 | FileFormats ffs = FileFormats.getInstance(); |
1148 | 74 | List<String> validFormats = ffs.getWritableFormats(false); |
1149 | ||
1150 | 74 | FileFormatI ff = null; |
1151 | 74 | if (format == null && fileName != null) |
1152 | { | |
1153 | 71 | FORMAT: for (String fname : validFormats) |
1154 | { | |
1155 | 365 | FileFormatI tff = ffs.forName(fname); |
1156 | 365 | String[] extensions = tff.getExtensions().split(","); |
1157 | 365 | for (String ext : extensions) |
1158 | { | |
1159 | 655 | if (fileName.toLowerCase(Locale.ROOT).endsWith("." + ext)) |
1160 | { | |
1161 | 62 | ff = tff; |
1162 | 62 | format = ff.getName(); |
1163 | 62 | break FORMAT; |
1164 | } | |
1165 | } | |
1166 | } | |
1167 | } | |
1168 | 74 | if (ff == null && format != null) |
1169 | { | |
1170 | 3 | ff = ffs.forName(format); |
1171 | } | |
1172 | 74 | if (ff == null) |
1173 | { | |
1174 | 9 | if (stdout) |
1175 | { | |
1176 | 9 | ff = FileFormat.Fasta; |
1177 | } | |
1178 | else | |
1179 | { | |
1180 | 0 | StringBuilder validSB = new StringBuilder(); |
1181 | 0 | for (String f : validFormats) |
1182 | { | |
1183 | 0 | if (validSB.length() > 0) |
1184 | 0 | validSB.append(", "); |
1185 | 0 | validSB.append(f); |
1186 | 0 | FileFormatI tff = ffs.forName(f); |
1187 | 0 | validSB.append(" ("); |
1188 | 0 | validSB.append(tff.getExtensions()); |
1189 | 0 | validSB.append(")"); |
1190 | } | |
1191 | ||
1192 | 0 | addError("No valid format specified for " |
1193 | + Arg.OUTPUT.argString() + ". Valid formats are " | |
1194 | + validSB.toString() + "."); | |
1195 | 0 | continue; |
1196 | } | |
1197 | } | |
1198 | ||
1199 | 74 | boolean success = checksBeforeWritingToFile(avm, subVals, true, |
1200 | fileName, ff.getName(), isError); | |
1201 | 74 | if (!success) |
1202 | { | |
1203 | 0 | continue; |
1204 | } | |
1205 | ||
1206 | 74 | boolean backups = avm.getFromSubValArgOrPref(Arg.BACKUPS, subVals, |
1207 | 74 | null, Platform.isHeadless() ? null : BackupFiles.ENABLED, |
1208 | !Platform.isHeadless()); | |
1209 | ||
1210 | 74 | Console.info("Writing " + fileName); |
1211 | ||
1212 | 74 | af.saveAlignment(fileName, ff, stdout, backups); |
1213 | 74 | if (af.isSaveAlignmentSuccessful()) |
1214 | { | |
1215 | 74 | Console.debug("Written alignment '" + name + "' in " |
1216 | + ff.getName() + " format to '" + file + "'"); | |
1217 | } | |
1218 | else | |
1219 | { | |
1220 | 0 | addError("Error writing file '" + file + "' in " + ff.getName() |
1221 | + " format!"); | |
1222 | 0 | isError = true; |
1223 | 0 | continue; |
1224 | } | |
1225 | ||
1226 | } | |
1227 | } | |
1228 | 74 | return !isError; |
1229 | } | |
1230 | ||
1231 | 42 | private SequenceI getSpecifiedSequence(AlignFrame af, ArgValuesMap avm, |
1232 | ArgValue av) | |
1233 | { | |
1234 | 42 | SubVals subVals = av.getSubVals(); |
1235 | 42 | ArgValue idAv = avm.getClosestNextArgValueOfArg(av, Arg.SEQID, true); |
1236 | 42 | SequenceI seq = null; |
1237 | 42 | if (subVals == null && idAv == null) |
1238 | 0 | return null; |
1239 | 42 | if (af == null || af.getCurrentView() == null) |
1240 | { | |
1241 | 0 | return null; |
1242 | } | |
1243 | 42 | AlignmentI al = af.getCurrentView().getAlignment(); |
1244 | 42 | if (al == null) |
1245 | { | |
1246 | 0 | return null; |
1247 | } | |
1248 | 42 | if (subVals != null) |
1249 | { | |
1250 | 42 | if (subVals.has(Arg.SEQID.getName())) |
1251 | { | |
1252 | 8 | seq = al.findName(subVals.get(Arg.SEQID.getName())); |
1253 | } | |
1254 | 34 | else if (-1 < subVals.getIndex() |
1255 | && subVals.getIndex() < al.getSequences().size()) | |
1256 | { | |
1257 | 0 | seq = al.getSequenceAt(subVals.getIndex()); |
1258 | } | |
1259 | } | |
1260 | 42 | if (seq == null && idAv != null) |
1261 | { | |
1262 | 12 | seq = al.findName(idAv.getValue()); |
1263 | } | |
1264 | 42 | return seq; |
1265 | } | |
1266 | ||
1267 | 0 | public AlignFrame[] getAlignFrames() |
1268 | { | |
1269 | 0 | AlignFrame[] afs = null; |
1270 | 0 | if (afMap != null) |
1271 | { | |
1272 | 0 | afs = (AlignFrame[]) afMap.values().toArray(); |
1273 | } | |
1274 | ||
1275 | 0 | return afs; |
1276 | } | |
1277 | ||
1278 | 0 | public List<StructureViewer> getStructureViewers() |
1279 | { | |
1280 | 0 | List<StructureViewer> svs = null; |
1281 | 0 | if (svMap != null) |
1282 | { | |
1283 | 0 | for (List<StructureViewer> svList : svMap.values()) |
1284 | { | |
1285 | 0 | if (svs == null) |
1286 | { | |
1287 | 0 | svs = new ArrayList<>(); |
1288 | } | |
1289 | 0 | svs.addAll(svList); |
1290 | } | |
1291 | } | |
1292 | 0 | return svs; |
1293 | } | |
1294 | ||
1295 | 53 | private void colourAlignFrame(AlignFrame af, String colour) |
1296 | { | |
1297 | // use string "none" to remove colour scheme | |
1298 | 53 | if (colour != null && "" != colour) |
1299 | { | |
1300 | 13 | ColourSchemeI cs = ColourSchemeProperty.getColourScheme( |
1301 | af.getViewport(), af.getViewport().getAlignment(), colour); | |
1302 | 13 | if (cs == null && !StringUtils.equalsIgnoreCase(colour, "none")) |
1303 | { | |
1304 | 0 | addWarn("Couldn't parse '" + colour + "' as a colourscheme."); |
1305 | } | |
1306 | else | |
1307 | { | |
1308 | 13 | Jalview.testoutput(argParser, Arg.COLOUR, "zappo", colour); |
1309 | 13 | colourAlignFrame(af, cs); |
1310 | } | |
1311 | } | |
1312 | } | |
1313 | ||
1314 | 53 | private void colourAlignFrame(AlignFrame af, ColourSchemeI cs) |
1315 | { | |
1316 | 53 | try |
1317 | { | |
1318 | 53 | SwingUtilities.invokeAndWait(new Runnable() |
1319 | { | |
1320 | 53 | @Override |
1321 | public void run() | |
1322 | { | |
1323 | // Note that cs == null removes colour scheme from af | |
1324 | 53 | af.changeColour(cs); |
1325 | } | |
1326 | }); | |
1327 | } catch (Exception x) | |
1328 | { | |
1329 | 0 | Console.trace("Interrupted whilst waiting for colorAlignFrame action", |
1330 | x); | |
1331 | ||
1332 | } | |
1333 | } | |
1334 | ||
1335 | 40 | private ColourSchemeI getColourScheme(AlignFrame af) |
1336 | { | |
1337 | 40 | return af.getViewport().getGlobalColourScheme(); |
1338 | } | |
1339 | ||
1340 | 0 | private void addInfo(String errorMessage) |
1341 | { | |
1342 | 0 | Console.info(errorMessage); |
1343 | 0 | errors.add(errorMessage); |
1344 | } | |
1345 | ||
1346 | 0 | private void addWarn(String errorMessage) |
1347 | { | |
1348 | 0 | Console.warn(errorMessage); |
1349 | 0 | errors.add(errorMessage); |
1350 | } | |
1351 | ||
1352 | 0 | private void addError(String errorMessage) |
1353 | { | |
1354 | 0 | addError(errorMessage, null); |
1355 | } | |
1356 | ||
1357 | 0 | private void addError(String errorMessage, Exception e) |
1358 | { | |
1359 | 0 | Console.error(errorMessage, e); |
1360 | 0 | errors.add(errorMessage); |
1361 | } | |
1362 | ||
1363 | 114 | private boolean checksBeforeWritingToFile(ArgValuesMap avm, |
1364 | SubVals subVal, boolean includeBackups, String filename, | |
1365 | String adjective, Boolean isError) | |
1366 | { | |
1367 | 114 | File file = new File(filename); |
1368 | ||
1369 | 114 | boolean overwrite = avm.getFromSubValArgOrPref(Arg.OVERWRITE, subVal, |
1370 | null, "OVERWRITE_OUTPUT", false); | |
1371 | 114 | boolean stdout = false; |
1372 | 114 | boolean backups = false; |
1373 | 114 | if (includeBackups) |
1374 | { | |
1375 | 74 | stdout = ArgParser.STDOUTFILENAME.equals(filename); |
1376 | // backups. Use the Arg.BACKUPS or subval "backups" setting first, | |
1377 | // otherwise if headless assume false, if not headless use the user | |
1378 | // preference with default true. | |
1379 | 74 | backups = avm.getFromSubValArgOrPref(Arg.BACKUPS, subVal, null, |
1380 | 74 | Platform.isHeadless() ? null : BackupFiles.ENABLED, |
1381 | !Platform.isHeadless()); | |
1382 | } | |
1383 | ||
1384 | 114 | if (file.exists() && !(overwrite || backups || stdout)) |
1385 | { | |
1386 | 0 | addWarn("Won't overwrite file '" + filename + "' without " |
1387 | + Arg.OVERWRITE.argString() | |
1388 | 0 | + (includeBackups ? " or " + Arg.BACKUPS.argString() : "") |
1389 | + " set"); | |
1390 | 0 | return false; |
1391 | } | |
1392 | ||
1393 | 114 | boolean mkdirs = avm.getFromSubValArgOrPref(Arg.MKDIRS, subVal, null, |
1394 | "MKDIRS_OUTPUT", false); | |
1395 | ||
1396 | 114 | if (!FileUtils.checkParentDir(file, mkdirs)) |
1397 | { | |
1398 | 0 | addError("Directory '" |
1399 | + FileUtils.getParentDir(file).getAbsolutePath() | |
1400 | + "' does not exist for " + adjective + " file '" + filename | |
1401 | + "'." | |
1402 | 0 | + (mkdirs ? "" : " Try using " + Arg.MKDIRS.argString())); |
1403 | 0 | isError = true; |
1404 | 0 | return false; |
1405 | } | |
1406 | ||
1407 | 114 | return true; |
1408 | } | |
1409 | ||
1410 | 98 | public List<String> getErrors() |
1411 | { | |
1412 | 98 | return errors; |
1413 | } | |
1414 | ||
1415 | 126 | public String errorsToString() |
1416 | { | |
1417 | 126 | StringBuilder sb = new StringBuilder(); |
1418 | 126 | for (String error : errors) |
1419 | { | |
1420 | 0 | if (sb.length() > 0) |
1421 | 0 | sb.append("\n"); |
1422 | 0 | sb.append("- " + error); |
1423 | } | |
1424 | 126 | return sb.toString(); |
1425 | } | |
1426 | } |