1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 package ffx.ui;
39
40 import static ffx.utilities.FileUtils.copyInputStreamToTmpFile;
41 import static ffx.utilities.StringUtils.pdbForID;
42 import static java.lang.String.format;
43 import static java.lang.System.arraycopy;
44
45 import ffx.crystal.Crystal;
46 import ffx.crystal.ReplicatesCrystal;
47 import ffx.potential.MolecularAssembly;
48 import ffx.potential.bonded.Atom;
49 import ffx.potential.bonded.Bond;
50 import ffx.potential.bonded.MSNode;
51 import ffx.potential.bonded.MSRoot;
52 import ffx.potential.bonded.RendererCache;
53 import ffx.potential.bonded.RotamerLibrary;
54 import ffx.potential.parameters.ForceField;
55 import ffx.potential.parsers.ARCFileFilter;
56 import ffx.potential.parsers.FFXFileFilter;
57 import ffx.potential.parsers.ForceFieldFileFilter;
58 import ffx.potential.parsers.ForceFieldFilter;
59 import ffx.potential.parsers.INTFileFilter;
60 import ffx.potential.parsers.INTFilter;
61 import ffx.potential.parsers.InducedFileFilter;
62 import ffx.potential.parsers.InducedFilter;
63 import ffx.potential.parsers.KeyFileFilter;
64 import ffx.potential.parsers.KeyFilter;
65 import ffx.potential.parsers.MergeFilter;
66 import ffx.potential.parsers.PDBFileFilter;
67 import ffx.potential.parsers.PDBFilter;
68 import ffx.potential.parsers.SystemFilter;
69 import ffx.potential.parsers.XYZFileFilter;
70 import ffx.potential.parsers.XYZFilter;
71 import ffx.ui.properties.FFXLocale;
72 import ffx.utilities.Keyword;
73 import ffx.utilities.Resources;
74
75 import java.awt.BorderLayout;
76 import java.awt.Container;
77 import java.awt.Cursor;
78 import java.awt.Dimension;
79 import java.awt.Font;
80 import java.awt.Frame;
81 import java.awt.GraphicsConfiguration;
82 import java.awt.GraphicsEnvironment;
83 import java.awt.GridLayout;
84 import java.awt.Toolkit;
85 import java.awt.event.ActionEvent;
86 import java.awt.event.ActionListener;
87 import java.io.*;
88 import java.net.InetAddress;
89 import java.net.InetSocketAddress;
90 import java.net.MalformedURLException;
91 import java.net.URI;
92 import java.net.URISyntaxException;
93 import java.net.URL;
94 import java.time.Month;
95 import java.util.ArrayList;
96 import java.util.Arrays;
97 import java.util.Hashtable;
98 import java.util.List;
99 import java.util.logging.Level;
100 import java.util.logging.Logger;
101 import java.util.prefs.Preferences;
102 import javax.swing.BorderFactory;
103 import javax.swing.ImageIcon;
104 import javax.swing.JCheckBoxMenuItem;
105 import javax.swing.JDialog;
106 import javax.swing.JFileChooser;
107 import javax.swing.JFrame;
108 import javax.swing.JLabel;
109 import javax.swing.JOptionPane;
110 import javax.swing.JPanel;
111 import javax.swing.JScrollPane;
112 import javax.swing.JSplitPane;
113 import javax.swing.JTabbedPane;
114 import javax.swing.JTextArea;
115 import javax.swing.SwingUtilities;
116 import javax.swing.UIManager;
117 import javax.swing.UnsupportedLookAndFeelException;
118 import javax.swing.border.Border;
119 import javax.swing.border.EtchedBorder;
120 import javax.swing.event.ChangeEvent;
121 import javax.swing.event.ChangeListener;
122 import javax.swing.filechooser.FileSystemView;
123
124 import org.apache.commons.configuration2.CompositeConfiguration;
125 import org.apache.commons.io.FileUtils;
126 import org.apache.commons.io.FilenameUtils;
127 import org.apache.commons.lang3.SystemUtils;
128 import org.jogamp.java3d.GraphicsConfigTemplate3D;
129 import org.jogamp.java3d.Transform3D;
130 import org.jogamp.java3d.TransformGroup;
131 import org.jogamp.vecmath.Vector3d;
132
133
134
135
136
137
138
139 public final class MainPanel extends JPanel implements ActionListener, ChangeListener {
140
141 @Serial
142 private static final long serialVersionUID = 1L;
143
144
145
146
147 public static final String version = "1.0.0";
148
149
150
151 public static final String date = "January 2025";
152
153
154
155 public static final String border =
156 " _________________________________________________________________________\n";
157
158
159
160 public static final String title = " FORCE FIELD X - Polyglot Software for Molecular Biophysics \n";
161
162 public static final String aboutString;
163
164
165
166 static final int KEYWORDS = 1;
167
168
169
170 static final int MODELING = 2;
171
172
173
174 static final ForceFieldFileFilter forceFieldFileFilter = new ForceFieldFileFilter();
175
176
177
178 static final KeyFileFilter keyFileFilter = new KeyFileFilter();
179
180 private static final Logger logger = Logger.getLogger(MainPanel.class.getName());
181
182
183
184 private static final int GRAPHICS = 0;
185
186
187
188 private static final XYZFileFilter xyzFileFilter = new XYZFileFilter();
189
190
191
192 private static final ARCFileFilter arcFileFilter = new ARCFileFilter();
193
194
195
196 private static final INTFileFilter intFileFilter = new INTFileFilter();
197
198
199
200 private static final InducedFileFilter indFileFilter = new InducedFileFilter();
201
202
203
204 private static final PDBFileFilter pdbFileFilter = new PDBFileFilter();
205
206
207
208 private static final FFXFileFilter ffxFileFilter = new FFXFileFilter();
209
210 private static final Preferences preferences = Preferences.userNodeForPackage(MainPanel.class);
211
212
213
214 static String classpath;
215
216
217
218 static File ffxDir;
219
220
221
222 private static File pwd;
223
224
225
226 private static JFileChooser fileChooser = null;
227
228 static {
229 var basedir = System.getProperty("basedir");
230 var mvnProps = new File(basedir + "/bin/build.properties");
231 var commitVersion = version + "-unknown";
232 var commitDate = date;
233 var commitSCM = "";
234 if (mvnProps.exists()) {
235 try (BufferedReader br = new BufferedReader(new FileReader(mvnProps))) {
236 var ffxVersion = "1.0.0";
237 var ffxVersionProp = "ffx.version=";
238 var gitCommitsCount = "";
239 var gitCommitsCountProp = "git.total.commit.count=";
240 var timestampProp = "timestamp=";
241 var gitRevisionProp = "git.commit.id.full=";
242 var line = br.readLine();
243 while (line != null) {
244 line = line.trim();
245 if (line.startsWith(ffxVersionProp)) {
246 ffxVersion = line.replaceFirst(ffxVersionProp, "");
247 } else if (line.startsWith(gitCommitsCountProp)) {
248 gitCommitsCount = line.replaceFirst(gitCommitsCountProp, "");
249 } else if (line.startsWith(timestampProp)) {
250 var timeStr = line.replaceFirst(timestampProp, "");
251
252 var timeToks = timeStr.split("-");
253 try {
254 var year = timeToks[2];
255 int mon = Integer.parseInt(timeToks[0]);
256 Month month = Month.of(mon);
257 var mstr = month.toString();
258 commitDate = format("%c%s %s", mstr.charAt(0), mstr.substring(1).toLowerCase(), year);
259 } catch (Exception ex) {
260 commitDate = date;
261 }
262 } else if (line.startsWith(gitRevisionProp) && !line.contains("UNKNOWN_REVISION")) {
263 var scm = line.replaceFirst(gitRevisionProp, "");
264 commitSCM = format(" %s %s \n", "Git Revision ", scm);
265 }
266 line = br.readLine();
267 }
268 var sb = new StringBuilder(ffxVersion).append("-");
269 if (!gitCommitsCount.isEmpty()) {
270 sb.append(gitCommitsCount);
271 } else {
272 sb.append("unknown");
273 }
274 commitVersion = sb.toString();
275 } catch (Exception ex) {
276
277 }
278 }
279 aboutString = " Version "
280 + commitVersion
281 + " "
282 + commitDate
283 + " \n"
284 + commitSCM
285 + " \n"
286 + """
287 Please cite the following reference when using Force Field X:
288
289 RA Gogal, AJ Nessler, AC Thiel, HV Bernabe, RA Corrigan Grove,
290 LM Cousineau, JM Litman, JM Miller, G Qi, MJ Speranza,
291 MR Tollefson, TD Fenn, JJ Michaelson, O Okada, JP Piquemal,
292 JW Ponder, J Shen, RJH Smith, W Yang, P Ren and MJ Schnieders,
293 2024, Journal of Chemical Physics, 161 (1).
294
295 Copyright (c) Michael J. Schnieders 2001-2025
296 All Rights Reserved
297
298 Force Field X is distributed under the GPL v. 3 license
299 with linking exception and is hosted by the Schnieders Lab
300 at The University of Iowa.
301
302 User Manual: https:
303 Publications: https:
304 License: https:
305 """;
306
307 try {
308 String ffxString = System.getProperty("ffx.dir", ".");
309 ffxDir = new File(ffxString);
310 classpath = System.getProperty("java.class.path");
311 pwd = MainPanel.getPWD();
312 } catch (Exception e) {
313 logger.severe(" FFX directory could not be found.\n" + e);
314 }
315 }
316
317
318
319
320 private final JFrame frame;
321
322
323
324 private int fileOpenerThreads = -1;
325
326
327
328 private MSRoot dataRoot;
329
330
331
332 private Hierarchy hierarchy;
333
334
335
336 private MainMenu mainMenu;
337
338
339
340 private GraphicsPanel graphicsPanel;
341
342
343
344 private ModelingPanel modelingPanel;
345
346
347
348 private KeywordPanel keywordPanel;
349
350
351
352 private ModelingShell modelingShell = null;
353
354
355
356 private GraphicsCanvas graphicsCanvas;
357
358
359
360 private JSplitPane splitPane;
361
362
363
364 private int splitPaneDivider;
365
366
367
368 private JLabel statusLabel;
369
370
371
372 private ForceFieldFilter forceFieldFilter;
373
374
375
376 private FFXLocale locale = null;
377
378
379
380 private JDialog aboutDialog = null;
381
382
383
384 private JTextArea aboutTextArea = null;
385
386
387
388 private Thread openThread = null;
389
390
391
392 private SystemFilter activeFilter = null;
393
394
395
396 private boolean oscillate = false;
397
398
399
400 private SimulationLoader simulation;
401
402
403
404 private String ip = "";
405
406
407
408 private int port = 2000;
409
410
411
412 private InetAddress address = null;
413
414
415
416 private InetSocketAddress socketAddress = new InetSocketAddress(port);
417
418
419
420 private boolean init = false;
421
422
423
424 private ExitStatus exitType = ExitStatus.NORMAL;
425
426
427
428
429
430
431 public MainPanel(JFrame f) {
432 frame = f;
433 }
434
435
436
437
438 public MainPanel() {
439 frame = null;
440 }
441
442
443
444
445
446
447 static File getPWD() {
448 if (pwd == null) {
449 pwd =
450 new File(
451 System.getProperty(
452 "user.dir",
453 FileSystemView.getFileSystemView().getDefaultDirectory().getAbsolutePath()));
454 }
455 return pwd;
456 }
457
458
459
460
461
462
463 static JFileChooser resetFileChooser() {
464 if (fileChooser == null) {
465 fileChooser = new JFileChooser();
466 }
467 fileChooser.resetChoosableFileFilters();
468 fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
469 fileChooser.setFileHidingEnabled(false);
470 fileChooser.setAcceptAllFileFilterUsed(true);
471 fileChooser.setCurrentDirectory(getPWD());
472 fileChooser.setMultiSelectionEnabled(false);
473 fileChooser.setSelectedFile(null);
474 return fileChooser;
475 }
476
477
478
479
480 public void about() {
481 if (aboutDialog == null) {
482 aboutDialog = new JDialog(frame, "About... ", true);
483 URL ffxURL = getClass().getClassLoader().getResource("ffx/ui/icons/splash.png");
484 ImageIcon logoIcon = new ImageIcon(ffxURL);
485 JLabel logoLabel = new JLabel(logoIcon);
486 logoLabel.setSize(600, 600);
487 logoLabel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED));
488 Container contentpane = aboutDialog.getContentPane();
489 contentpane.setLayout(new BorderLayout());
490 initAbout();
491 contentpane.add(aboutTextArea, BorderLayout.SOUTH);
492 contentpane.add(logoLabel, BorderLayout.CENTER);
493 aboutDialog.pack();
494 Dimension dim = getToolkit().getScreenSize();
495 Dimension ddim = aboutDialog.getSize();
496 aboutDialog.setLocation((dim.width - ddim.width) / 2, (dim.height - ddim.height) / 2);
497 aboutDialog.setResizable(false);
498 }
499 aboutDialog.setVisible(true);
500 }
501
502
503
504
505
506
507
508 @Override
509 public void actionPerformed(ActionEvent evt) {
510 String arg = evt.getActionCommand();
511 if (logger.isLoggable(Level.FINEST)) {
512 logger.finest(" Action: " + arg);
513 }
514
515 switch (arg) {
516 case "Open" -> open();
517 case "DownloadFromPDB" -> openFromPDB();
518 case "SaveAs" -> saveAsXYZ(null);
519 case "Close" -> close();
520 case "CloseAll" -> closeAll();
521 case "ChooseKeyFile" -> chooseKey();
522 case "ChooseLogFile" -> chooseLog();
523 case "LoadInducedData" -> openInduced();
524
525
526 case "SelectAll" -> selectAll();
527 case "MergeSelections" -> merge();
528 case "HighlightSelections" -> highlightSelections(evt);
529
530
531 case "Play" -> play();
532 case "Stop" -> stop();
533 case "StepForward" -> stepForward();
534 case "StepBack" -> stepBack();
535 case "Reset" -> reset();
536 case "Oscillate" -> oscillate(evt);
537 case "Frame" -> frame();
538 case "Speed" -> speed();
539 case "Skip" -> skip();
540
541
542 case "ConnectToLocalJob" -> connectToTINKER(null, null);
543 case "ConnectToRemoteJob" -> connect();
544 case "ReleaseJob" -> release();
545 case "SetPort" -> setPort();
546 case "SetRemoteJobAddress" -> setRemoteJobAddress();
547
548
549 case "ShowToolBar" -> showToolBar(evt);
550 case "ShowTree" -> showTree(evt);
551 case "ShowGlobalAxes" -> showGlobalAxes(evt);
552 case "ResetPanes" -> resetPanes();
553 case "ResetConsole" -> resetShell();
554 case "OceanLookAndFeel" -> oceanLookAndFeel();
555 case "WindowsLookAndFeel", "MacOSXLookAndFeel", "MotifLookAndFeel" -> platformLookAndFeel();
556 case "ShrinkGraphicsWindow" -> resizePanes(20);
557 case "ExpandGraphicsWindow" -> resizePanes(-20);
558 case "About" -> about();
559
560
561 case "GarbageCollect" -> Runtime.getRuntime().gc();
562 case "Exit" -> exit();
563 default -> {
564 try {
565 ClassLoader cl = MainPanel.class.getClassLoader();
566 URL url = cl.getResource(arg);
567 logger.info(url.toString());
568 File structureFile = new File(url.getFile());
569 logger.info(structureFile.toString());
570 String tempFile =
571 copyInputStreamToTmpFile(url.openStream(), "ffx", structureFile.getName(), "pdb");
572 open(tempFile);
573 } catch (Exception e) {
574 System.err.println("MainPanel - Menu command not found: " + arg);
575 }
576 }
577 }
578 }
579
580
581
582
583
584
585 public Thread close() {
586 FFXSystem m = hierarchy.getActive();
587 return close(m);
588 }
589
590
591
592
593
594
595
596 public Thread close(FFXSystem closedModel) {
597 if (closedModel.getParent() != null) {
598 Trajectory traj = closedModel.getTrajectory();
599 if (traj != null) {
600 traj.stop();
601 }
602 if (simulation != null && simulation.getFSystem() == closedModel) {
603 release();
604 }
605 hierarchy.removeTreeNode(closedModel);
606 closedModel.setView(RendererCache.ViewModel.DESTROY, null);
607 Thread thread = new Thread(new UIFileCloser(closedModel));
608 thread.start();
609 return thread;
610 }
611 return null;
612 }
613
614
615
616
617 public void exit() {
618 exit(exitType);
619 }
620
621
622
623
624 public void frame() {
625 Trajectory trajectory = getTrajectory();
626 if (trajectory == null) {
627 return;
628 }
629 String frameNumber = "" + trajectory.getFrame();
630 frameNumber = JOptionPane.showInputDialog("Enter the Frame Number", frameNumber);
631 try {
632 int f = Integer.parseInt(frameNumber);
633 trajectory.setFrame(f);
634 } catch (NumberFormatException e) {
635
636 }
637 }
638
639
640
641
642
643
644 public SystemFilter getFilter() {
645 return activeFilter;
646 }
647
648
649
650
651
652
653 public Frame getFrame() {
654 return frame;
655 }
656
657
658
659
660
661
662 public Hierarchy getHierarchy() {
663 return hierarchy;
664 }
665
666
667
668
669
670
671 public MainMenu getMainMenu() {
672 return mainMenu;
673 }
674
675
676
677
678
679
680 public ModelingShell getModelingShell() {
681 if (modelingShell == null) {
682 modelingShell = new ModelingShell(this);
683 modelingShell.run();
684 }
685 return modelingShell;
686 }
687
688
689
690
691 public void initialize() {
692 if (init) {
693 return;
694 }
695 init = true;
696
697 String dir =
698 System.getProperty(
699 "user.dir", FileSystemView.getFileSystemView().getDefaultDirectory().getAbsolutePath());
700 setCWD(new File(dir));
701 locale = new FFXLocale("en", "US");
702
703
704 dataRoot = new MSRoot();
705 Border bb = BorderFactory.createEtchedBorder(EtchedBorder.RAISED);
706 statusLabel = new JLabel(" ");
707 JLabel stepLabel = new JLabel(" ");
708 stepLabel.setHorizontalAlignment(JLabel.RIGHT);
709 JLabel energyLabel = new JLabel(" ");
710 energyLabel.setHorizontalAlignment(JLabel.RIGHT);
711 JPanel statusPanel = new JPanel(new GridLayout(1, 3));
712 statusPanel.setBorder(bb);
713 statusPanel.add(statusLabel);
714 statusPanel.add(stepLabel);
715 statusPanel.add(energyLabel);
716
717
718 setLayout(new BorderLayout());
719 hierarchy = new Hierarchy(this);
720 hierarchy.setStatus(statusLabel, stepLabel, energyLabel);
721 keywordPanel = new KeywordPanel(this);
722 modelingPanel = new ModelingPanel(this);
723
724 JPanel treePane = new JPanel(new BorderLayout());
725 JScrollPane scrollPane = new JScrollPane(hierarchy, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
726 JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
727 treePane.add(scrollPane, BorderLayout.CENTER);
728
729 if (!GraphicsEnvironment.isHeadless()) {
730 GraphicsConfigTemplate3D template3D = new GraphicsConfigTemplate3D();
731
732 GraphicsConfiguration gc = null;
733 try {
734 gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getBestConfiguration(template3D);
735 } catch (Exception e) {
736 logger.log(Level.SEVERE, " Exception encountered when trying to get the best GraphicsConfiguration", e);
737 }
738 try {
739 graphicsCanvas = new GraphicsCanvas(gc, this);
740 } catch (Exception e) {
741 logger.log(Level.SEVERE, " Exception encountered when trying to create the GraphicsCanvas", e);
742 }
743 graphicsPanel = new GraphicsPanel(graphicsCanvas, statusPanel);
744 }
745
746
747
748
749
750
751
752
753
754
755
756
757
758 splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, false, treePane, graphicsPanel);
759 splitPane.setResizeWeight(0.25);
760 splitPane.setOneTouchExpandable(true);
761 add(splitPane, BorderLayout.CENTER);
762
763 if (!GraphicsEnvironment.isHeadless()) {
764 mainMenu = new MainMenu(this);
765 add(mainMenu.getToolBar(), BorderLayout.NORTH);
766 getModelingShell();
767 loadPrefs();
768 }
769 }
770
771
772
773
774
775
776 public void merge(MSNode[] nodesToMerge) {
777 ArrayList<MSNode> activeNodes = new ArrayList<>();
778 for (MSNode node : nodesToMerge) {
779 if (node != null) {
780 activeNodes.add(node);
781 }
782 }
783 if (activeNodes.size() > 1) {
784 merge(activeNodes);
785 }
786 }
787
788 public Thread open(File file, String commandDescription) {
789 UIFileOpener opener = openInit(file, commandDescription);
790 openThread = new Thread(opener);
791 openThread.start();
792 setPanel(GRAPHICS);
793 return openThread;
794 }
795
796 public Thread open(List<File> files, String commandDescription) {
797 UIFileOpener openFile = openInit(files, commandDescription);
798 openThread = new Thread(openFile);
799 openThread.start();
800 setPanel(GRAPHICS);
801 return openThread;
802 }
803
804
805
806
807
808
809
810 public Thread open(String name) {
811 File file = resolveName(name);
812 if (file == null) {
813 logger.log(Level.WARNING, "{0}: could not be found.", name);
814 return null;
815 }
816 return open(file, null);
817 }
818
819
820
821
822
823
824
825 public Thread open(String[] names) {
826 if (names == null) {
827 return null;
828 }
829 List<File> files = new ArrayList<>();
830
831 for (String name : names) {
832 File file = resolveName(name);
833 if (file == null || !file.exists()) {
834 return null;
835 }
836 files.add(file);
837 }
838 return open(files, null);
839 }
840
841 public synchronized MolecularAssembly[] openWaitUtils(String file) {
842 UIFileOpener opener = openFromUtils(file);
843 Thread thread = new Thread(opener);
844 while (thread.isAlive()) {
845 try {
846 wait(1);
847 } catch (InterruptedException e) {
848 String message = "Exception waiting for " + file + " to open.";
849 logger.log(Level.WARNING, message, e);
850 return null;
851 }
852 }
853
854 MolecularAssembly[] systems = activeFilter.getMolecularAssemblyArray();
855 if (systems != null) {
856 int n = systems.length;
857 FFXSystem[] ffxSystems = new FFXSystem[n];
858 FFXSystem[] allSystems = getHierarchy().getSystems();
859 int total = allSystems.length;
860 System.arraycopy(allSystems, total - n, ffxSystems, 0, n);
861 return ffxSystems;
862 } else {
863 return null;
864 }
865 }
866
867
868
869
870 public void reset() {
871 Trajectory trajectory = getTrajectory();
872 if (trajectory == null) {
873 return;
874 }
875 trajectory.stop();
876 trajectory.rewind();
877 }
878
879 public void saveKeywordFile(File file) {
880 keywordPanel.keySave(file);
881 }
882
883
884
885
886 @Override
887 public void stateChanged(ChangeEvent evt) {
888 JTabbedPane jtp = (JTabbedPane) evt.getSource();
889 int index = jtp.getSelectedIndex();
890 if (index == 0) {
891 graphicsCanvas.selected();
892 } else if (index == 1) {
893 keywordPanel.selected();
894 } else if (index == 2) {
895 modelingPanel.selected();
896 }
897 }
898
899
900
901
902 public void stop() {
903 Trajectory trajectory = getTrajectory();
904 if (trajectory == null) {
905 return;
906 }
907 trajectory.stop();
908 }
909
910
911
912
913 @Override
914 public String toString() {
915 return "Program Control";
916 }
917
918
919
920
921 private void chooseKey() {
922 JFileChooser d = MainPanel.resetFileChooser();
923 d.setFileFilter(new KeyFileFilter());
924 d.setAcceptAllFileFilterUsed(false);
925 FFXSystem sys = getHierarchy().getActive();
926 if (sys != null) {
927 File newCWD = sys.getFile();
928 if (newCWD != null && newCWD.getParentFile() != null) {
929 d.setCurrentDirectory(newCWD.getParentFile());
930 }
931 } else {
932 return;
933 }
934 int result = d.showOpenDialog(this);
935 if (result == JFileChooser.APPROVE_OPTION) {
936 File f = d.getSelectedFile();
937 sys.setKeyFile(f);
938 sys.setKeywords(KeyFilter.open(f));
939 getKeywordPanel().loadActive(sys);
940 }
941 }
942
943
944
945
946 private void chooseLog() {
947 JFileChooser d = resetFileChooser();
948 FFXSystem sys = getHierarchy().getActive();
949 if (sys != null) {
950 File newCWD = sys.getFile();
951 if (newCWD != null && newCWD.getParentFile() != null) {
952 d.setCurrentDirectory(newCWD.getParentFile());
953 }
954 } else {
955 return;
956 }
957 d.setDialogTitle("Select a log file");
958 d.setAcceptAllFileFilterUsed(true);
959 int result = d.showOpenDialog(this);
960 if (result == JFileChooser.APPROVE_OPTION) {
961 File f = d.getSelectedFile();
962 if (f != null) {
963 sys.setLogFile(f);
964 setCWD(d.getCurrentDirectory());
965
966 }
967 }
968 }
969
970
971
972
973 synchronized void closeWait() {
974 FFXSystem active = hierarchy.getActive();
975 if (active == null) {
976 logger.log(Level.INFO, " No active system to close.");
977 return;
978 }
979 Thread thread = close(active);
980 while (thread != null && thread.isAlive()) {
981 try {
982 wait(1);
983 } catch (InterruptedException e) {
984 String message = "Exception waiting for " + active + " to close.";
985 logger.log(Level.WARNING, message, e);
986 }
987 }
988 }
989
990
991
992
993 synchronized void closeAll() {
994 while (hierarchy.getActive() != null) {
995 closeWait();
996 }
997 }
998
999
1000
1001
1002 private void connect() {
1003 if (simulation == null || simulation.isFinished()) {
1004 if (simulation != null) {
1005 simulation.release();
1006 }
1007 simulation = new SimulationLoader(null, null, this, socketAddress);
1008 simulation.connect();
1009 mainMenu.setConnect(false);
1010 setPanel(GRAPHICS);
1011 }
1012 }
1013
1014
1015
1016
1017
1018
1019
1020 void connectToTINKER(FFXSystem system, Thread modelingThread) {
1021 if (simulation == null || simulation.isFinished()) {
1022 if (simulation != null) {
1023 simulation.release();
1024 }
1025 InetSocketAddress tempAddress;
1026 try {
1027 tempAddress = new InetSocketAddress(InetAddress.getLocalHost(), port);
1028 } catch (Exception e) {
1029 try {
1030 tempAddress = new InetSocketAddress(InetAddress.getByName(null), port);
1031 } catch (Exception ex) {
1032 System.err.println("Could not determine Local Host: " + ex);
1033 return;
1034 }
1035 }
1036 simulation = new SimulationLoader(system, modelingThread, this, tempAddress);
1037 if (modelingThread != null) {
1038 modelingThread.start();
1039 }
1040 simulation.connect();
1041 mainMenu.setConnect(false);
1042 setPanel(GRAPHICS);
1043 }
1044 }
1045
1046
1047
1048
1049
1050
1051
1052 boolean createKeyFile(FFXSystem system) {
1053 String message = "Please select a parameter file " + "and a TINKER Key file will be created.";
1054 String params = (String) JOptionPane.showInputDialog(this, message, "Parameter File",
1055 JOptionPane.QUESTION_MESSAGE, null, keywordPanel.getParamFiles(), null);
1056 if (params != null) {
1057 if (params.equalsIgnoreCase("Use an existing TINKER Key file")) {
1058 JFileChooser fc = resetFileChooser();
1059 fc.setDialogTitle("Choose a KEY File");
1060 fc.setCurrentDirectory(pwd);
1061 fc.setSelectedFile(null);
1062 fc.setFileFilter(keyFileFilter);
1063 int result = fc.showOpenDialog(this);
1064 if (result == JFileChooser.APPROVE_OPTION) {
1065 File keyfile = fc.getSelectedFile();
1066 if (keyfile.exists()) {
1067 Hashtable<String, Keyword> keywordHash = KeyFilter.open(keyfile);
1068 if (keywordHash != null) {
1069 system.setKeywords(keywordHash);
1070 } else {
1071 return false;
1072 }
1073 system.setKeyFile(keyfile);
1074 system.setForceField(null);
1075 return true;
1076 }
1077 }
1078 } else {
1079 File tempFile = system.getFile();
1080 if (tempFile.getParentFile().canWrite()) {
1081 String path = system.getFile().getParent() + File.separatorChar;
1082 String keyFileName = system.getName() + ".key";
1083 File keyfile = new File(path + keyFileName);
1084 try {
1085 FileWriter fw = new FileWriter(keyfile);
1086 BufferedWriter bw = new BufferedWriter(fw);
1087 bw.write("\n");
1088 bw.write("# Force Field Selection\n");
1089 String tempParm = keywordPanel.getParamPath(params);
1090 if (tempParm.indexOf(" ") > 0) {
1091 tempParm = "\"" + keywordPanel.getParamPath(params) + "\"";
1092 }
1093 bw.write("PARAMETERS " + tempParm + "\n");
1094 bw.close();
1095 fw.close();
1096 Hashtable<String, Keyword> keywordHash = KeyFilter.open(keyfile);
1097 if (keywordHash != null) {
1098 system.setKeywords(keywordHash);
1099 } else {
1100 return false;
1101 }
1102 system.setKeyFile(keyfile);
1103 system.setForceField(null);
1104 return true;
1105 } catch (Exception e) {
1106 logger.warning("" + e);
1107 message = "There was an error creating " + keyfile.getAbsolutePath();
1108 JOptionPane.showMessageDialog(this, message);
1109 }
1110 } else {
1111 message =
1112 "Could not create a Key file because " + pwd.getAbsolutePath() + " is not writable";
1113 JOptionPane.showMessageDialog(this, message);
1114 }
1115 }
1116 }
1117 return false;
1118 }
1119
1120
1121
1122
1123
1124
1125 void exit(ExitStatus exitStatus) {
1126
1127 savePrefs();
1128
1129 Resources.logResources();
1130
1131 System.exit(exitStatus.getExitCode());
1132 }
1133
1134
1135
1136
1137
1138
1139 void setExitType(ExitStatus exitType) {
1140
1141 this.exitType = exitType;
1142 }
1143
1144
1145
1146
1147
1148
1149 MSRoot getDataRoot() {
1150 return dataRoot;
1151 }
1152
1153
1154
1155
1156
1157
1158 FFXLocale getFFXLocale() {
1159 return locale;
1160 }
1161
1162
1163
1164
1165
1166
1167 GraphicsCanvas getGraphics3D() {
1168 return graphicsCanvas;
1169 }
1170
1171
1172
1173
1174
1175
1176 KeywordPanel getKeywordPanel() {
1177 return keywordPanel;
1178 }
1179
1180 ModelingPanel getModelingPanel() {
1181 return modelingPanel;
1182 }
1183
1184
1185
1186
1187
1188
1189 JLabel getStatusBar() {
1190 return statusLabel;
1191 }
1192
1193
1194
1195
1196
1197
1198 private Trajectory getTrajectory() {
1199 FFXSystem system = hierarchy.getActive();
1200 if (system == null) {
1201 return null;
1202 }
1203 Trajectory trajectory = system.getTrajectory();
1204 if (trajectory != null) {
1205 return trajectory;
1206 }
1207 trajectory = new Trajectory(system, this);
1208 trajectory.setOscillate(oscillate);
1209 system.setTrajectory(trajectory);
1210 return trajectory;
1211 }
1212
1213
1214
1215
1216
1217
1218 private void highlightSelections(ActionEvent evt) {
1219 if (evt.getSource() instanceof JCheckBoxMenuItem jcb) {
1220 hierarchy.setHighlighting(jcb.isSelected());
1221 } else {
1222 boolean highlighting = RendererCache.highlightSelections;
1223 if (highlighting) {
1224 hierarchy.setHighlighting(false);
1225 mainMenu.setHighlighting(false);
1226 } else {
1227 hierarchy.setHighlighting(true);
1228 mainMenu.setHighlighting(true);
1229 }
1230 }
1231 }
1232
1233 private void initAbout() {
1234 aboutTextArea = new JTextArea();
1235 Font font = Font.decode(Font.MONOSPACED);
1236 aboutTextArea.setFont(font);
1237 aboutTextArea.setText(aboutString);
1238 aboutTextArea.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED));
1239 aboutTextArea.setEditable(false);
1240 }
1241
1242
1243
1244
1245
1246
1247 boolean isOpening() {
1248 return (openThread != null && openThread.isAlive());
1249 }
1250
1251
1252
1253
1254 private void loadPrefs() {
1255 String c = MainPanel.class.getName();
1256 JFrame frame1 = (JFrame) SwingUtilities.getRoot(this);
1257 Toolkit toolkit = getToolkit();
1258 Dimension screenSize = toolkit.getScreenSize();
1259 int x = preferences.getInt(c + ".x", screenSize.width / 8);
1260 int y = preferences.getInt(c + ".y", screenSize.height / 8);
1261 int width = preferences.getInt(c + ".width", screenSize.width * 3 / 4);
1262 int height = preferences.getInt(c + ".height", screenSize.height * 3 / 4);
1263 if (width > screenSize.width * 0.4
1264 && width < screenSize.width * 0.8
1265 && height > screenSize.height * 0.4
1266 && height < screenSize.height * 0.8) {
1267 frame1.setSize(width, height);
1268 } else {
1269 frame1.setSize(screenSize.width * 4 / 5, screenSize.height * 4 / 5);
1270 }
1271 if (x > 0 && x < screenSize.width / 2 && y > 0 && y < screenSize.height / 2) {
1272 frame1.setLocation(x, y);
1273 } else {
1274 frame1.setLocation(screenSize.width / 8, screenSize.height / 8);
1275 }
1276 splitPaneDivider = preferences.getInt(c + ".divider", 200);
1277 if (splitPaneDivider < frame1.getWidth() * (1.0f / 4.0f)) {
1278 splitPaneDivider = (int) (frame1.getWidth() * (1.0f / 4.0f));
1279 }
1280 splitPane.setDividerLocation(splitPaneDivider);
1281 if (!preferences.getBoolean(c + ".system", true)) {
1282 mainMenu.setSystemShowing(false);
1283 splitPane.setDividerLocation(0);
1284 } else {
1285 mainMenu.setSystemShowing(true);
1286 }
1287 if (!preferences.getBoolean(c + ".menu", true)) {
1288 remove(mainMenu.getToolBar());
1289 mainMenu.setMenuShowing(false);
1290 validate();
1291 } else {
1292 mainMenu.setMenuShowing(true);
1293 }
1294 try {
1295 port = preferences.getInt(c + ".port", 2000);
1296 ip = preferences.get(c + ".ip", InetAddress.getLocalHost().getHostAddress());
1297 if (ip != null) {
1298 address = InetAddress.getByName(ip);
1299 socketAddress = new InetSocketAddress(address, port);
1300 } else {
1301 socketAddress = new InetSocketAddress(port);
1302 }
1303 } catch (Exception e) {
1304 logger.log(Level.WARNING, e.toString());
1305 }
1306 if (graphicsCanvas != null) {
1307 graphicsCanvas.loadPrefs();
1308 }
1309 }
1310
1311
1312
1313
1314 private void merge() {
1315 ArrayList<MSNode> activeNodes = hierarchy.getActiveNodes();
1316 if (activeNodes.size() >= 2) {
1317 merge(activeNodes);
1318 }
1319 }
1320
1321
1322
1323
1324
1325
1326
1327 private void merge(ArrayList<MSNode> nodesToMerge) {
1328 ArrayList<MSNode> activeNodes = new ArrayList<>();
1329 for (MSNode node : nodesToMerge) {
1330 if (node != null && !(node instanceof MSRoot)) {
1331 activeNodes.add(node);
1332 }
1333 }
1334 if (activeNodes.size() <= 1) {
1335 return;
1336 }
1337
1338 FFXSystem active = hierarchy.getActive();
1339 File file = SystemFilter.version(hierarchy.getActive().getFile());
1340 FFXSystem system = new FFXSystem(file, "Merge Result", active.getProperties());
1341 system.setKeyFile(active.getKeyFile());
1342 system.setKeywords(KeyFilter.open(active.getKeyFile()));
1343
1344 ArrayList<Atom> mergedAtoms = new ArrayList<>();
1345 ArrayList<Bond> mergedBonds = new ArrayList<>();
1346 ArrayList<FFXSystem> systems = new ArrayList<>();
1347 TransformGroup parentTransformGroup;
1348 FFXSystem parentSystem;
1349 Transform3D parentTransform3D = new Transform3D();
1350 Vector3d parentPosition = new Vector3d();
1351 Vector3d atomPosition = new Vector3d();
1352
1353 int atomNum = 1;
1354 Vector3d zero = new Vector3d(0.0, 0.0, 0.0);
1355 for (MSNode m : activeNodes) {
1356 parentSystem = m.getMSNode(FFXSystem.class);
1357 if (parentSystem == null) {
1358 return;
1359 }
1360 if (!systems.contains(parentSystem)) {
1361 graphicsCanvas.updateSceneWait(
1362 parentSystem, false, true, RendererCache.ViewModel.WIREFRAME, false, null);
1363 systems.add(parentSystem);
1364 }
1365
1366
1367
1368 parentTransformGroup = parentSystem.getOriginToRot();
1369 parentTransformGroup.getTransform(parentTransform3D);
1370 parentTransform3D.get(parentPosition);
1371 parentTransform3D.setTranslation(zero);
1372
1373 for (Atom atom : m.getAtomList()) {
1374 atom.removeFromParent();
1375 atom.setXyzIndex(atomNum++);
1376 mergedAtoms.add(atom);
1377 atom.getV3D(atomPosition);
1378 parentTransform3D.transform(atomPosition);
1379 atomPosition.add(parentPosition);
1380 atom.moveTo(atomPosition);
1381 }
1382 for (Bond bond : m.getBondList()) {
1383 bond.removeFromParent();
1384 mergedBonds.add(bond);
1385 }
1386 }
1387 for (FFXSystem sys : systems) {
1388 close(sys);
1389 }
1390 MergeFilter mergeFilter = new MergeFilter(system, mergedAtoms, mergedBonds);
1391 UIFileOpener fileOpener = new UIFileOpener(mergeFilter, this);
1392 if (fileOpenerThreads > 0) {
1393 fileOpener.setNThreads(fileOpenerThreads);
1394 }
1395 Thread thread = new Thread(fileOpener);
1396 thread.start();
1397 }
1398
1399
1400
1401
1402 private void oceanLookAndFeel() {
1403 try {
1404 UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
1405 SwingUtilities.updateComponentTreeUI(SwingUtilities.getRoot(this));
1406 } catch (Exception e) {
1407
1408 }
1409 }
1410
1411
1412
1413
1414 private Thread open() {
1415 if (openThread != null && openThread.isAlive()) {
1416 return null;
1417 }
1418 JFileChooser fc = resetFileChooser();
1419 fc.setDialogTitle("Choose FFX, PDB, XYZ or ARC");
1420 fc.addChoosableFileFilter(xyzFileFilter);
1421 fc.addChoosableFileFilter(pdbFileFilter);
1422 fc.addChoosableFileFilter(intFileFilter);
1423 fc.addChoosableFileFilter(arcFileFilter);
1424 fc.addChoosableFileFilter(ffxFileFilter);
1425 fc.setAcceptAllFileFilterUsed(true);
1426 int result = fc.showOpenDialog(this);
1427 if (result == JFileChooser.APPROVE_OPTION) {
1428 File file = fc.getSelectedFile();
1429 return open(file, null);
1430 }
1431 return null;
1432 }
1433
1434 private UIFileOpener openFromUtils(File file, String commandDescription) {
1435 UIFileOpener opener = openInit(file, commandDescription);
1436 openThread = new Thread(opener);
1437 openThread.start();
1438 setPanel(GRAPHICS);
1439 return opener;
1440 }
1441
1442
1443
1444
1445
1446
1447
1448
1449 private UIFileOpener openInit(File file, String commandDescription) {
1450 if (file == null || !file.isFile() || !file.canRead()) {
1451 return null;
1452 }
1453 file = new File(FilenameUtils.normalize(file.getAbsolutePath()));
1454
1455 setCWD(file.getParentFile());
1456
1457
1458 CompositeConfiguration properties = Keyword.loadProperties(file);
1459
1460 FFXSystem newSystem = new FFXSystem(file, commandDescription, properties);
1461
1462 forceFieldFilter = new ForceFieldFilter(properties);
1463 ForceField forceField = forceFieldFilter.parse();
1464 String[] patches = properties.getStringArray("patch");
1465 for (String patch : patches) {
1466 logger.info(" Attempting to read force field patch from " + patch + ".");
1467 CompositeConfiguration patchConfiguration = new CompositeConfiguration();
1468 patchConfiguration.addProperty("parameters", patch);
1469 forceFieldFilter = new ForceFieldFilter(patchConfiguration);
1470 ForceField patchForceField = forceFieldFilter.parse();
1471 forceField.append(patchForceField);
1472 if (RotamerLibrary.addRotPatch(patch)) {
1473 logger.info(format(" Loaded rotamer definitions from patch %s.", patch));
1474 }
1475 }
1476 newSystem.setForceField(forceField);
1477 SystemFilter systemFilter;
1478
1479
1480 if (xyzFileFilter.acceptDeep(file)) {
1481
1482 systemFilter = new XYZFilter(file, newSystem, forceField, properties);
1483 } else if (intFileFilter.acceptDeep(file)) {
1484
1485 systemFilter = new INTFilter(file, newSystem, forceField, properties);
1486 } else {
1487
1488 systemFilter = new PDBFilter(file, newSystem, forceField, properties);
1489 }
1490
1491 setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
1492 activeFilter = systemFilter;
1493 UIFileOpener fileOpener = new UIFileOpener(systemFilter, this);
1494 if (fileOpenerThreads > 0) {
1495 fileOpener.setNThreads(fileOpenerThreads);
1496 }
1497 return fileOpener;
1498 }
1499
1500 private UIFileOpener openFromUtils(List<File> files, String commandDescription) {
1501 UIFileOpener openFile = openInit(files, commandDescription);
1502 openThread = new Thread(openFile);
1503 openThread.start();
1504 setPanel(GRAPHICS);
1505 return openFile;
1506 }
1507
1508
1509
1510
1511
1512
1513
1514
1515 private UIFileOpener openInit(List<File> files, String commandDescription) {
1516 if (files == null) {
1517 return null;
1518 }
1519 File file = new File(FilenameUtils.normalize(files.get(0).getAbsolutePath()));
1520
1521 setCWD(file.getParentFile());
1522
1523
1524 CompositeConfiguration properties = Keyword.loadProperties(file);
1525 forceFieldFilter = new ForceFieldFilter(properties);
1526 ForceField forceField = forceFieldFilter.parse();
1527
1528
1529 FFXSystem newSystem = new FFXSystem(file, commandDescription, properties);
1530 String[] patches = properties.getStringArray("patch");
1531 for (String patch : patches) {
1532 logger.info(" Attempting to read force field patch from " + patch + ".");
1533 CompositeConfiguration patchConfiguration = new CompositeConfiguration();
1534 patchConfiguration.addProperty("parameters", patch);
1535 forceFieldFilter = new ForceFieldFilter(patchConfiguration);
1536 ForceField patchForceField = forceFieldFilter.parse();
1537 forceField.append(patchForceField);
1538 if (RotamerLibrary.addRotPatch(patch)) {
1539 logger.info(format(" Loaded rotamer definitions from patch %s.", patch));
1540 }
1541 }
1542 newSystem.setForceField(forceField);
1543
1544 SystemFilter systemFilter;
1545 if (xyzFileFilter.acceptDeep(file)) {
1546
1547 systemFilter = new XYZFilter(files, newSystem, forceField, properties);
1548 } else if (intFileFilter.acceptDeep(file)) {
1549
1550 systemFilter = new INTFilter(files, newSystem, forceField, properties);
1551 } else {
1552
1553 systemFilter = new PDBFilter(files, newSystem, forceField, properties);
1554 }
1555
1556 setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
1557 activeFilter = systemFilter;
1558
1559 UIFileOpener fileOpener = new UIFileOpener(systemFilter, this);
1560 if (fileOpenerThreads > 0) {
1561 fileOpener.setNThreads(fileOpenerThreads);
1562 }
1563 return fileOpener;
1564 }
1565
1566
1567
1568
1569
1570
1571
1572 synchronized FFXSystem[] openWait(String file) {
1573 Thread thread = open(file);
1574 while (thread != null && thread.isAlive()) {
1575 try {
1576 wait(1);
1577 } catch (InterruptedException e) {
1578 String message = "Exception waiting for " + file + " to open.";
1579 logger.log(Level.WARNING, message, e);
1580 return null;
1581 }
1582 }
1583
1584 MolecularAssembly[] systems = activeFilter.getMolecularAssemblyArray();
1585 if (systems != null) {
1586 int n = systems.length;
1587 FFXSystem[] ffxSystems = new FFXSystem[n];
1588 FFXSystem[] allSystems = getHierarchy().getSystems();
1589 int total = allSystems.length;
1590 arraycopy(allSystems, total - n, ffxSystems, 0, n);
1591 return ffxSystems;
1592 } else {
1593 return null;
1594 }
1595 }
1596
1597
1598
1599
1600
1601
1602
1603
1604 synchronized FFXSystem[] openWait(String file, int nThreads) {
1605 fileOpenerThreads = nThreads;
1606 FFXSystem[] systs = openWait(file);
1607 fileOpenerThreads = -1;
1608 return systs;
1609 }
1610
1611
1612
1613
1614
1615
1616
1617 synchronized FFXSystem[] openWait(String[] files) {
1618 Thread thread = open(files);
1619 while (thread != null && thread.isAlive()) {
1620 try {
1621 wait(1);
1622 } catch (InterruptedException e) {
1623 String message = "Exception waiting for " + files[0] + " to open.";
1624 logger.log(Level.WARNING, message, e);
1625 return null;
1626 }
1627 }
1628
1629 MolecularAssembly[] systems = activeFilter.getMolecularAssemblyArray();
1630 if (systems != null) {
1631 int n = systems.length;
1632 FFXSystem[] ffxSystems = new FFXSystem[n];
1633 FFXSystem[] allSystems = getHierarchy().getSystems();
1634 int total = allSystems.length;
1635 arraycopy(allSystems, total - n, ffxSystems, 0, n);
1636 return ffxSystems;
1637 } else {
1638 return null;
1639 }
1640 }
1641
1642
1643
1644
1645
1646
1647
1648
1649 synchronized FFXSystem[] openWait(String[] files, int nThreads) {
1650 fileOpenerThreads = nThreads;
1651 FFXSystem[] systs = openWait(files);
1652 fileOpenerThreads = -1;
1653 return systs;
1654 }
1655
1656 private UIFileOpener openFromUtils(String name) {
1657 File file = resolveName(name);
1658 if (file == null) {
1659 logger.log(Level.WARNING, "{0}: could not be found.", name);
1660 return null;
1661 }
1662 return openFromUtils(file, null);
1663 }
1664
1665 private File resolveName(String name) {
1666
1667 if (name == null) {
1668 return null;
1669 }
1670 File file = new File(name);
1671
1672 if (file.exists()) {
1673 return file;
1674 }
1675
1676 file = new File(pwd + File.separator + name);
1677 if (file.exists()) {
1678 return file;
1679 }
1680
1681 if (name.startsWith("http://")) {
1682 String fileName = FilenameUtils.getName(name);
1683 if (fileName == null) {
1684 return null;
1685 }
1686 return downloadURL(name);
1687 }
1688
1689 if (name.length() == 4) {
1690 String fileName = name + ".pdb";
1691 String path = getPWD().getAbsolutePath();
1692 File pdbFile = new File(path + File.separatorChar + fileName);
1693 if (!pdbFile.exists()) {
1694 String fromURL = pdbForID(name);
1695 return downloadURL(fromURL);
1696 } else {
1697 return pdbFile;
1698 }
1699 }
1700 return null;
1701 }
1702
1703 private UIFileOpener openFromUtils(String[] names) {
1704 if (names == null) {
1705 return null;
1706 }
1707 List<File> files = new ArrayList<>();
1708
1709 for (String name : names) {
1710 File file = resolveName(name);
1711 if (file == null || !file.exists()) {
1712 return null;
1713 }
1714 files.add(file);
1715 }
1716 return openFromUtils(files, null);
1717 }
1718
1719
1720
1721
1722 private void openFromPDB() {
1723 if (openThread != null && openThread.isAlive()) {
1724 return;
1725 }
1726 String code = JOptionPane.showInputDialog("Enter the PDB Identifier (4 characters)", "");
1727 if (code == null) {
1728 return;
1729 }
1730 code = code.toLowerCase().trim();
1731 if (code.length() != 4) {
1732 return;
1733 }
1734 String fileName = code + ".pdb";
1735 String path = getPWD().getAbsolutePath();
1736 File pdbFile = new File(path + File.separatorChar + fileName);
1737 CompositeConfiguration properties = Keyword.loadProperties(pdbFile);
1738 forceFieldFilter = new ForceFieldFilter(properties);
1739 ForceField forceField = forceFieldFilter.parse();
1740 FFXSystem newSystem = new FFXSystem(pdbFile, "PDB", properties);
1741 newSystem.setForceField(forceField);
1742 if (!pdbFile.exists()) {
1743 String fromURL = pdbForID(code);
1744 pdbFile = downloadURL(fromURL);
1745 if (pdbFile == null || !pdbFile.exists()) {
1746 return;
1747 }
1748 } else {
1749 String message = format(" Reading the local copy of the PDB file %s.", pdbFile);
1750 logger.info(message);
1751 }
1752 PDBFilter pdbFilter = new PDBFilter(pdbFile, newSystem, forceField, properties);
1753 setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
1754 UIFileOpener openFile = new UIFileOpener(pdbFilter, this);
1755 if (fileOpenerThreads > 0) {
1756 openFile.setNThreads(fileOpenerThreads);
1757 }
1758 openThread = new Thread(openFile);
1759 openThread.start();
1760 setPanel(GRAPHICS);
1761 }
1762
1763 private File downloadURL(String fromString) {
1764
1765 if (fromString == null) {
1766 return null;
1767 }
1768
1769
1770 URL fromURL;
1771 try {
1772 URI uri = new URI(fromString);
1773 fromURL = uri.toURL();
1774 } catch (MalformedURLException | URISyntaxException e) {
1775 String message = format(" URL incorrectly formatted %s.", fromString);
1776 logger.log(Level.INFO, message, e);
1777 return null;
1778 }
1779
1780
1781 logger.info(format(" Downloading %s", fromString));
1782 try {
1783 File toFile = new File(FilenameUtils.getName(fromURL.getPath()));
1784 FileUtils.copyURLToFile(fromURL, toFile, 1000, 1000);
1785 logger.info(format(" Saved to %s\n", toFile.getPath()));
1786 return toFile;
1787 } catch (IOException ex) {
1788 logger.log(Level.INFO, " Failed to read URL " + fromURL.getPath(), ex);
1789 return null;
1790 }
1791 }
1792
1793 private void openInduced() {
1794 FFXSystem active = hierarchy.getActive();
1795 resetFileChooser();
1796 fileChooser.setCurrentDirectory(pwd);
1797 fileChooser.setSelectedFile(active.getFile());
1798 fileChooser.setDialogTitle("Choose Induced Dipole File");
1799 fileChooser.addChoosableFileFilter(indFileFilter);
1800 fileChooser.setAcceptAllFileFilterUsed(true);
1801 fileChooser.setFileFilter(indFileFilter);
1802 int result = fileChooser.showOpenDialog(this);
1803 if (result == JFileChooser.APPROVE_OPTION) {
1804 File f = fileChooser.getSelectedFile();
1805 InducedFilter indFilter = new InducedFilter(active, f);
1806 indFilter.read();
1807 }
1808 }
1809
1810
1811
1812
1813
1814
1815
1816
1817 boolean openKey(FFXSystem newSystem, boolean createKey) {
1818 String keyFileName;
1819 String temp = newSystem.getFile().getName();
1820 int dot = temp.lastIndexOf(".");
1821 if (dot > 0) {
1822 keyFileName = temp.substring(0, dot) + ".key";
1823 } else {
1824 keyFileName = temp + ".key";
1825 }
1826 String path = newSystem.getFile().getParent() + File.separator;
1827 File keyfile = new File(path + keyFileName);
1828 if (keyfile.exists()) {
1829 Hashtable<String, Keyword> keywordHash = KeyFilter.open(keyfile);
1830 if (keywordHash != null) {
1831 newSystem.setKeywords(keywordHash);
1832 } else {
1833 return false;
1834 }
1835 newSystem.setKeyFile(keyfile);
1836 newSystem.setForceField(null);
1837 return true;
1838 }
1839 keyfile = new File(path + "tinker.key");
1840 if (keyfile.exists()) {
1841 logger.info("Using tinker.key: " + keyfile);
1842 Hashtable<String, Keyword> keywordHash = KeyFilter.open(keyfile);
1843 if (keywordHash != null) {
1844 newSystem.setKeywords(keywordHash);
1845 } else {
1846 return false;
1847 }
1848 newSystem.setKeyFile(keyfile);
1849 newSystem.setForceField(null);
1850 return true;
1851 }
1852 if (createKey) {
1853 return createKeyFile(newSystem);
1854 }
1855 return false;
1856 }
1857
1858
1859
1860
1861
1862
1863
1864
1865 void openOn(File f, FFXSystem oldSystem, String command) {
1866 XYZFilter.readOnto(f, oldSystem);
1867 oldSystem.setCommandDescription(command);
1868 graphicsCanvas.updateScene(oldSystem, true, false, null, false, null);
1869 getHierarchy().updateStatus();
1870 getHierarchy().repaint();
1871 }
1872
1873
1874
1875
1876
1877
1878 private void oscillate(ActionEvent evt) {
1879 oscillate = ((JCheckBoxMenuItem) evt.getSource()).isSelected();
1880 FFXSystem[] systems = getHierarchy().getSystems();
1881
1882 if (systems == null) {
1883 return;
1884 }
1885
1886 for (FFXSystem system : systems) {
1887 Trajectory trajectory = system.getTrajectory();
1888 if (trajectory != null) {
1889 trajectory.setOscillate(oscillate);
1890 }
1891 }
1892 }
1893
1894
1895
1896
1897 private void platformLookAndFeel() {
1898 try {
1899 if (SystemUtils.IS_OS_LINUX) {
1900 UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");
1901 } else {
1902 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
1903 }
1904 SwingUtilities.updateComponentTreeUI(SwingUtilities.getRoot(this));
1905 } catch (ClassNotFoundException
1906 | InstantiationException
1907 | IllegalAccessException
1908 | UnsupportedLookAndFeelException e) {
1909 logger.log(Level.WARNING, "Can''t set look and feel: {0}", e);
1910 }
1911 }
1912
1913
1914
1915
1916 private void play() {
1917 Trajectory trajectory = getTrajectory();
1918 if (trajectory == null) {
1919 return;
1920 }
1921 trajectory.start();
1922 }
1923
1924
1925
1926
1927 private void release() {
1928 if (simulation != null) {
1929 simulation.release();
1930 simulation = null;
1931 mainMenu.setConnect(true);
1932 }
1933 }
1934
1935
1936
1937
1938 private void resetPanes() {
1939 resizePanes(0);
1940 }
1941
1942
1943
1944
1945 void resetShell() {
1946 if (!GraphicsEnvironment.isHeadless()) {
1947 modelingShell = getModelingShell();
1948 try {
1949 modelingShell.exit();
1950 } catch (NullPointerException e) {
1951
1952 } finally {
1953 modelingShell = null;
1954 }
1955 modelingShell = getModelingShell();
1956 }
1957 }
1958
1959
1960
1961
1962
1963
1964 private void resizePanes(int move) {
1965 if (move == 0) {
1966 splitPaneDivider = 0;
1967 mainMenu.setMenuShowing(false);
1968 mainMenu.toggleToolBarShowing();
1969 mainMenu.setSystemShowing(false);
1970 mainMenu.systemClick();
1971 } else {
1972 splitPane.setDividerLocation(splitPane.getDividerLocation() + move);
1973 }
1974 }
1975
1976
1977
1978
1979
1980
1981
1982 void saveAsXYZ(File file) {
1983 FFXSystem system = hierarchy.getActive();
1984 if (system != null && !system.isClosing()) {
1985 File saveFile = file;
1986 if (saveFile == null) {
1987 resetFileChooser();
1988 fileChooser.setCurrentDirectory(pwd);
1989 fileChooser.setFileFilter(xyzFileFilter);
1990 fileChooser.setAcceptAllFileFilterUsed(false);
1991 int result = fileChooser.showSaveDialog(this);
1992 if (result == JFileChooser.APPROVE_OPTION) {
1993 saveFile = fileChooser.getSelectedFile();
1994 pwd = saveFile.getParentFile();
1995 }
1996 }
1997 if (saveFile != null) {
1998 SystemFilter filter = new XYZFilter(saveFile, system, null, null);
1999 if (filter.writeFile(saveFile, false)) {
2000
2001 hierarchy.setActive(system);
2002 activeFilter = filter;
2003 }
2004 }
2005 }
2006 }
2007
2008
2009
2010
2011
2012
2013
2014 void saveAsP1(File file) {
2015 FFXSystem system = hierarchy.getActive();
2016 if (system != null && !system.isClosing()) {
2017 File saveFile = file;
2018 if (saveFile == null) {
2019 resetFileChooser();
2020 fileChooser.setCurrentDirectory(pwd);
2021 fileChooser.setFileFilter(xyzFileFilter);
2022 fileChooser.setAcceptAllFileFilterUsed(false);
2023 int result = fileChooser.showSaveDialog(this);
2024 if (result == JFileChooser.APPROVE_OPTION) {
2025 saveFile = fileChooser.getSelectedFile();
2026 pwd = saveFile.getParentFile();
2027 }
2028 }
2029 if (saveFile != null) {
2030 XYZFilter filter = new XYZFilter(saveFile, system, null, null);
2031 Crystal crystal = system.getCrystal().getUnitCell();
2032 if (crystal instanceof ReplicatesCrystal) {
2033 crystal = crystal.getUnitCell();
2034 }
2035 if (filter.writeFileAsP1(saveFile, false, crystal)) {
2036
2037 hierarchy.setActive(system);
2038 }
2039 activeFilter = filter;
2040 }
2041 }
2042 }
2043
2044
2045
2046
2047
2048
2049
2050 void saveAsPDB(File file) {
2051 saveAsPDB(file, true);
2052 }
2053
2054
2055
2056
2057
2058
2059
2060
2061 private void saveAsPDB(File file, boolean writeEnd) {
2062 saveAsPDB(file, writeEnd, false);
2063 }
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073 void saveAsPDB(File file, boolean writeEnd, boolean append) {
2074 FFXSystem system = hierarchy.getActive();
2075 if (system == null) {
2076 logger.log(Level.INFO, " No active system to save.");
2077 return;
2078 }
2079 if (system.isClosing()) {
2080 logger.log(Level.INFO, " {0} is being closed and can no longer be saved.", system);
2081 return;
2082 }
2083 File saveFile = file;
2084 if (saveFile == null) {
2085 resetFileChooser();
2086 fileChooser.setCurrentDirectory(pwd);
2087 fileChooser.setFileFilter(pdbFileFilter);
2088 fileChooser.setAcceptAllFileFilterUsed(false);
2089 int result = fileChooser.showSaveDialog(this);
2090 if (result == JFileChooser.APPROVE_OPTION) {
2091 saveFile = fileChooser.getSelectedFile();
2092 pwd = saveFile.getParentFile();
2093 }
2094 }
2095 if (saveFile == null) {
2096 logger.log(Level.INFO, " No filename is defined for {0}.", system);
2097 return;
2098 }
2099 PDBFilter pdbFilter = new PDBFilter(saveFile, system, null, null);
2100 if (pdbFilter.writeFile(saveFile, append, false, writeEnd)) {
2101
2102 hierarchy.setActive(system);
2103 activeFilter = pdbFilter;
2104 } else {
2105 logger.log(Level.INFO, " Save failed for: {0}", system);
2106 }
2107 }
2108
2109 void savePDBasP1(File file) {
2110 FFXSystem system = hierarchy.getActive();
2111 if (system == null) {
2112 logger.log(Level.INFO, " No active system to save.");
2113 return;
2114 }
2115 if (system.isClosing()) {
2116 logger.log(Level.INFO, " {0} is being closed and can no longer be saved.", system);
2117 return;
2118 }
2119 File saveFile = file;
2120 if (saveFile == null) {
2121 resetFileChooser();
2122 fileChooser.setCurrentDirectory(pwd);
2123 fileChooser.setFileFilter(pdbFileFilter);
2124 fileChooser.setAcceptAllFileFilterUsed(false);
2125 int result = fileChooser.showSaveDialog(this);
2126 if (result == JFileChooser.APPROVE_OPTION) {
2127 saveFile = fileChooser.getSelectedFile();
2128 pwd = saveFile.getParentFile();
2129 }
2130 }
2131 if (saveFile == null) {
2132 logger.log(Level.INFO, " No filename is defined for {0}.", system);
2133 return;
2134 }
2135
2136 PDBFilter pdbFilter = new PDBFilter(saveFile, system, null, null);
2137 pdbFilter.writeFileAsP1(saveFile);
2138 }
2139
2140
2141
2142
2143
2144
2145
2146 void saveAsPDB(MolecularAssembly[] activeSystems, File file) {
2147 File saveFile = file;
2148 if (saveFile == null) {
2149 resetFileChooser();
2150 fileChooser.setCurrentDirectory(pwd);
2151 fileChooser.setFileFilter(pdbFileFilter);
2152 fileChooser.setAcceptAllFileFilterUsed(false);
2153 int result = fileChooser.showSaveDialog(this);
2154 if (result == JFileChooser.APPROVE_OPTION) {
2155 saveFile = fileChooser.getSelectedFile();
2156 pwd = saveFile.getParentFile();
2157 }
2158 }
2159 if (saveFile != null) {
2160 PDBFilter pdbFilter = new PDBFilter(saveFile, Arrays.asList(activeSystems), null, null);
2161 pdbFilter.writeFile(saveFile, false);
2162 activeFilter = pdbFilter;
2163 }
2164 }
2165
2166
2167
2168
2169 private void savePrefs() {
2170 String c = MainPanel.class.getName();
2171 if (!GraphicsEnvironment.isHeadless()) {
2172 preferences.putInt(c + ".x", frame.getLocation().x);
2173 preferences.putInt(c + ".y", frame.getLocation().y);
2174 preferences.putInt(c + ".width", frame.getWidth());
2175 preferences.putInt(c + ".height", frame.getHeight());
2176 preferences.putBoolean(c + ".system", mainMenu.isSystemShowing());
2177 preferences.putInt(c + ".divider", splitPane.getDividerLocation());
2178 preferences.putBoolean(c + ".menu", mainMenu.isMenuShowing());
2179 preferences.putBoolean(c + ".axis", mainMenu.isAxisShowing());
2180 }
2181 if (ip == null) {
2182 ip = "";
2183 }
2184 if (address != null) {
2185 String s = address.getHostAddress();
2186 if (s != null) {
2187 preferences.put(c + ".ip", s);
2188 }
2189 preferences.putInt(c + ".port", socketAddress.getPort());
2190 }
2191 preferences.put(c + ".cwd", pwd.toString());
2192
2193 if (modelingPanel != null) {
2194 modelingPanel.savePrefs();
2195 }
2196 if (keywordPanel != null) {
2197 keywordPanel.savePrefs();
2198 }
2199 if (graphicsCanvas != null) {
2200 graphicsCanvas.savePrefs();
2201 }
2202 }
2203
2204
2205
2206
2207 private void selectAll() {
2208 if (dataRoot.getChildCount() == 0) {
2209 return;
2210 }
2211 hierarchy.selectAll();
2212 }
2213
2214
2215
2216
2217
2218
2219 void setCWD(File file) {
2220 if ((file == null) || (!file.exists())) {
2221 return;
2222 }
2223 pwd = file;
2224 }
2225
2226
2227
2228
2229
2230
2231 void setPanel(int panel) {
2232
2233 }
2234
2235
2236
2237
2238 private void setPort() {
2239 String s = "" + port;
2240 s = JOptionPane.showInputDialog("Enter a port number", s);
2241 if (s == null) {
2242 return;
2243 }
2244 int temp;
2245 try {
2246 temp = Integer.parseInt(s);
2247 } catch (NumberFormatException e) {
2248 return;
2249 }
2250 port = temp;
2251 socketAddress = new InetSocketAddress(address, port);
2252 }
2253
2254
2255
2256
2257 private void setRemoteJobAddress() {
2258 if (address == null) {
2259 try {
2260 address = InetAddress.getLocalHost();
2261 } catch (Exception e) {
2262 try {
2263 address = InetAddress.getByName(null);
2264 } catch (Exception ex) {
2265 return;
2266 }
2267 }
2268 }
2269 String s = address.getHostAddress();
2270 s = JOptionPane.showInputDialog("Enter an IP Address (XXX.XXX.XXX.XXX)", s);
2271 if (s == null) {
2272 return;
2273 }
2274 InetAddress newAddress;
2275 InetSocketAddress newSocketAddress;
2276 try {
2277 newAddress = InetAddress.getByName(s);
2278 newSocketAddress = new InetSocketAddress(newAddress, port);
2279 } catch (Exception e) {
2280 return;
2281 }
2282 address = newAddress;
2283 socketAddress = newSocketAddress;
2284 }
2285
2286
2287
2288
2289
2290
2291 private void showGlobalAxes(ActionEvent evt) {
2292 JCheckBoxMenuItem showAxesCheckBox = (JCheckBoxMenuItem) evt.getSource();
2293 graphicsCanvas.setAxisShowing(showAxesCheckBox.isSelected());
2294 }
2295
2296
2297
2298
2299
2300
2301 private void showToolBar(ActionEvent evt) {
2302 JCheckBoxMenuItem toolBarCheckBox = (JCheckBoxMenuItem) evt.getSource();
2303 if (toolBarCheckBox.isSelected()) {
2304 add(mainMenu.getToolBar(), BorderLayout.NORTH);
2305 frame.validate();
2306 } else {
2307 remove(mainMenu.getToolBar());
2308 frame.validate();
2309 }
2310 }
2311
2312
2313
2314
2315
2316
2317 private void showTree(ActionEvent evt) {
2318 JCheckBoxMenuItem treeCheckBox = (JCheckBoxMenuItem) evt.getSource();
2319 if (treeCheckBox.isSelected()) {
2320 if (splitPaneDivider < frame.getWidth() * (1.0f / 4.0f)) {
2321 splitPaneDivider = (int) (frame.getWidth() * (1.0f / 4.0f));
2322 }
2323 splitPane.setDividerLocation(splitPaneDivider);
2324 } else {
2325 splitPaneDivider = splitPane.getDividerLocation();
2326 splitPane.setDividerLocation(0.0);
2327 }
2328 }
2329
2330
2331
2332
2333 private void skip() {
2334 Trajectory trajectory = getTrajectory();
2335 if (trajectory == null) {
2336 return;
2337 }
2338 String skip = "" + trajectory.getSkip();
2339 skip = JOptionPane.showInputDialog("Enter the Number of Frames to Skip", skip);
2340 try {
2341 int f = Integer.parseInt(skip);
2342 trajectory.setSkip(f);
2343 } catch (NumberFormatException e) {
2344
2345 }
2346 }
2347
2348
2349
2350
2351 private void speed() {
2352 Trajectory trajectory = getTrajectory();
2353 if (trajectory == null) {
2354 return;
2355 }
2356 String rate = "" + trajectory.getRate();
2357 rate = JOptionPane.showInputDialog("Enter the Frame Rate (1-100)", rate);
2358 try {
2359 int f = Integer.parseInt(rate);
2360 trajectory.setRate(f);
2361 } catch (NumberFormatException e) {
2362
2363 }
2364 }
2365
2366
2367
2368
2369 private void stepBack() {
2370 Trajectory trajectory = getTrajectory();
2371 if (trajectory == null) {
2372 return;
2373 }
2374 trajectory.stop();
2375 trajectory.back();
2376 }
2377
2378
2379
2380
2381 private void stepForward() {
2382 Trajectory trajectory = getTrajectory();
2383 if (trajectory == null) {
2384 return;
2385 }
2386 trajectory.stop();
2387 trajectory.forward();
2388 }
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399 enum ExitStatus {
2400
2401 NORMAL(0),
2402
2403
2404
2405 EXCEPTION(1),
2406
2407 SEVERE(3),
2408
2409
2410 ALGORITHM_FAILURE(100),
2411
2412 OTHER(200);
2413
2414
2415 private final int exitCode;
2416
2417 ExitStatus(int exitCode) {
2418 this.exitCode = exitCode;
2419 }
2420
2421
2422
2423
2424
2425
2426 int getExitCode() {
2427 return exitCode;
2428 }
2429 }
2430 }