3 * Copyright (c) 2006 The Regents of the University of California.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions, and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions, and the following
13 * disclaimer in the documentation and/or other materials provided
14 * with the distribution.
15 * 3. Redistributions must acknowledge that this software was
16 * originally developed by the UCSF Computer Graphics Laboratory
17 * under support by the NIH National Center for Research Resources,
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
26 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 package ext.edu.ucsf.rbvi.strucviz2;
35 import jalview.bin.Cache;
36 import jalview.gui.Preferences;
37 import jalview.util.Platform;
40 import java.io.IOException;
41 import java.util.ArrayList;
42 import java.util.Arrays;
43 import java.util.Collection;
44 import java.util.HashMap;
45 import java.util.List;
47 import java.util.Properties;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
54 * This object maintains the relationship between Chimera objects and Cytoscape
58 public class StructureManager
60 static final String[] defaultStructureKeys = { "Structure", "pdb",
61 "pdbFileName", "PDB ID", "structure", "biopax.xref.PDB", "pdb_ids",
62 "ModelName", "ModelNumber" };
64 static final String[] defaultChemStructKeys = { "Smiles", "smiles",
67 static final String[] defaultResidueKeys = { "FunctionalResidues",
68 "ResidueList", "Residues" };
72 PDB_MODEL, MODBASE_MODEL, SMILES
75 public static Properties pathProps;
77 private String chimeraCommandAttr = "ChimeraCommand";
79 private String chimeraOutputTable = "ChimeraTable";
81 private String chimeraOutputAttr = "ChimeraOutput";
83 private boolean haveGUI = true;
85 private ChimeraManager chimeraManager = null;
87 static private List<ChimeraStructuralObject> chimSelectionList;
89 private boolean ignoreCySelection = false;
91 private File configurationDirectory = null;
93 private static Logger logger = LoggerFactory
94 .getLogger(ext.edu.ucsf.rbvi.strucviz2.StructureManager.class);
96 public StructureManager(boolean haveGUI)
98 this.haveGUI = haveGUI;
99 // Create the Chimera interface
100 chimeraManager = new ChimeraManager(this);
101 chimSelectionList = new ArrayList<>();
102 pathProps = new Properties();
105 public ChimeraManager getChimeraManager()
107 return chimeraManager;
110 public boolean openStructures(Collection<List<String>> chimObjNames,
114 Map<String, List<ChimeraModel>> newModels = new HashMap<>();
115 if (chimObjNames.size() > 0)
117 List<String> names = chimObjNames.iterator().next();
122 for (String chimObjName : names)
124 // get or open the corresponding models if they already exist
125 List<ChimeraModel> currentModels = chimeraManager
126 .getChimeraModels(chimObjName, type);
127 if (currentModels.size() == 0)
129 // open and return models
130 currentModels = chimeraManager.openModel(chimObjName, type);
131 if (currentModels == null)
133 // failed to open model, continue with next
136 // if (type == ModelType.SMILES) {
137 // newModels.put("smiles:" + chimObjName, currentModels);
139 newModels.put(chimObjName, currentModels);
142 for (ChimeraModel currentModel : currentModels)
144 // if not RIN then associate new model with the Cytoscape
146 // if (!currentChimMap.containsKey(currentModel)) {
147 // currentChimMap.put(currentModel, new HashSet<CyIdentifiable>());
158 // if (mnDialog != null) {
159 // mnDialog.modelChanged();
161 // aTask.associate();
166 // TODO: [Release] Handle case where one network is associated with two models
170 * public boolean openStructures(CyNetwork network, Map<CyIdentifiable,
171 * List<String>> chimObjNames, ModelType type) { if
172 * (!chimeraManager.isChimeraLaunched() &&
173 * !chimeraManager.launchChimera(getChimeraPaths(network))) {
174 * logger.error("Chimera could not be launched."); return false; } else if
175 * (chimObjNames.size() == 0) { return false; } else if (network == null) {
176 * return openStructures(chimObjNames.values(), type); }
178 * // potential rins Set<CyNetwork> potentialRINs = new HashSet<CyNetwork>();
179 * // attributes List<String> attrsFound = new ArrayList<String>();
181 * addAll(CytoUtils.getMatchingAttributes(network.getDefaultNodeTable(),
182 * getCurrentStructureKeys(network)));
183 * attrsFound.addAll(CytoUtils.getMatchingAttributes
184 * (network.getDefaultNodeTable(), getCurrentChemStructKeys(network))); // new
185 * models Map<String, List<ChimeraModel>> newModels = new HashMap<String,
186 * List<ChimeraModel>>(); // for each node that has an associated structure
187 * for (CyIdentifiable cyObj : chimObjNames.keySet()) { // get possible res
188 * specs List<String> specsFound = null; if (cyObj instanceof CyNode) {
189 * specsFound = ChimUtils.getResidueKeys(network.getDefaultNodeTable(), cyObj,
190 * attrsFound); } // save node to track its selection and mapping to chimera
191 * objects if (!currentCyMap.containsKey(cyObj)) { currentCyMap.put(cyObj, new
192 * HashSet<ChimeraStructuralObject>()); } // save node to network mapping to
193 * keep track of selection events if (!networkMap.containsKey(cyObj)) {
194 * networkMap.put(cyObj, new HashSet<CyNetwork>()); }
195 * networkMap.get(cyObj).add(network); // for each structure that has to be
196 * opened for (String chimObjName : chimObjNames.get(cyObj)) { // get or open
197 * the corresponding models if they already exist List<ChimeraModel>
198 * currentModels = chimeraManager.getChimeraModels(chimObjName, type); if
199 * (currentModels.size() == 0) { // open and return models currentModels =
200 * chimeraManager.openModel(chimObjName, type); if (currentModels == null) {
201 * // failed to open model, continue with next continue; } // if (type ==
202 * ModelType.SMILES) { // newModels.put("smiles:" + chimObjName,
203 * currentModels); // } else { newModels.put(chimObjName, currentModels); // }
204 * // for each model for (ChimeraModel currentModel : currentModels) { //
205 * check if it is a RIN boolean foundRIN = false; if
206 * (currentModel.getModelType().equals(ModelType.PDB_MODEL)) { // go through
207 * all node annotations and check if any of them is a residue // or a chain if
208 * (cyObj instanceof CyNode && network.containsNode((CyNode) cyObj) &&
209 * specsFound != null && specsFound.size() > 0) { for (String resSpec :
210 * specsFound) { ChimeraStructuralObject res =
211 * ChimUtils.fromAttribute(resSpec, chimeraManager); if (res != null && (res
212 * instanceof ChimeraResidue || res instanceof ChimeraChain)) { // if so,
213 * assume it might be a RIN potentialRINs.add(network); foundRIN = true;
214 * break; } } } else if (cyObj instanceof CyNetwork) { // if cyObj is a
215 * network, check for residue/chain annotations in an // arbitrary node
216 * CyNetwork rinNet = (CyNetwork) cyObj; if (rinNet.getNodeList().size() > 0)
217 * { specsFound = ChimUtils.getResidueKeys( rinNet.getDefaultNodeTable(),
218 * rinNet.getNodeList().get(0), attrsFound); for (String resSpec : specsFound)
219 * { ChimeraStructuralObject res = ChimUtils.fromAttribute( resSpec,
220 * chimeraManager); if (res != null && (res instanceof ChimeraResidue || res
221 * instanceof ChimeraChain)) { potentialRINs.add(network); foundRIN = true;
222 * break; } } } } } if (foundRIN) { continue; } // if not RIN then associate
223 * new model with the Cytoscape // node if
224 * (!currentChimMap.containsKey(currentModel)) {
225 * currentChimMap.put(currentModel, new HashSet<CyIdentifiable>()); } String
226 * cyObjName = network.getRow(cyObj).get(CyNetwork.NAME, String.class); if
227 * (cyObjName != null && cyObjName.endsWith(currentModel.getModelName())) { //
228 * it is a modbase model, associate directly
229 * currentCyMap.get(cyObj).add(currentModel);
230 * currentChimMap.get(currentModel).add(cyObj);
231 * currentModel.addCyObject(cyObj, network); } else if (specsFound != null &&
232 * specsFound.size() > 0) { for (String resSpec : specsFound) {
233 * ChimeraStructuralObject specModel = ChimUtils.fromAttribute( resSpec,
234 * chimeraManager); if (specModel == null &&
235 * resSpec.equals(currentModel.getModelName())) { specModel =
236 * chimeraManager.getChimeraModel( currentModel.getModelNumber(),
237 * currentModel.getSubModelNumber()); } if (specModel != null &&
238 * currentModel.toSpec().equals(specModel.toSpec()) ||
239 * currentModel.getModelName().equals("smiles:" + resSpec)) {
240 * currentCyMap.get(cyObj).add(currentModel);
241 * currentChimMap.get(currentModel).add(cyObj);
242 * currentModel.addCyObject(cyObj, network);
243 * currentModel.setFuncResidues(ChimUtils.parseFuncRes(
244 * getResidueList(network, cyObj), chimObjName)); } } } } } } } // networks
245 * that contain nodes associated to newly opened models // this will usually
246 * be of length 1 for (CyNetwork net : potentialRINs) {
247 * addStructureNetwork(net); } // update dialog if (mnDialog != null) {
248 * mnDialog.modelChanged(); } aTask.associate(); return true; }
250 public void closeStructures(Set<String> chimObjNames)
252 // for each cytoscape object and chimera model pair
253 for (String modelName : chimObjNames)
255 List<ChimeraModel> models = chimeraManager
256 .getChimeraModels(modelName);
257 for (ChimeraModel model : models)
262 // if (mnDialog != null) {
263 // mnDialog.modelChanged();
267 // TODO: [Optional] Can we make a screenshot of a single molecule?
268 public File saveChimeraImage()
273 // Create the temp file name
274 tmpFile = File.createTempFile("structureViz", ".png");
275 chimeraManager.sendChimeraCommand("set bgTransparency", false);
276 chimeraManager.sendChimeraCommand(
277 "copy file " + tmpFile.getAbsolutePath() + " png", true);
278 chimeraManager.sendChimeraCommand("unset bgTransparency", false);
279 } catch (IOException ioe)
282 logger.error("Error writing image", ioe);
287 public void closeModel(ChimeraModel model)
289 // close model in Chimera
290 chimeraManager.closeModel(model);
291 // remove all associations
292 // if (currentChimMap.containsKey(model)) {
293 // for (CyIdentifiable cyObj : model.getCyObjects().keySet()) {
294 // if (cyObj == null) {
296 // } else if (currentCyMap.containsKey(cyObj)) {
297 // currentCyMap.get(cyObj).remove(model);
298 // } else if (cyObj instanceof CyNetwork) {
299 // for (ChimeraResidue residue : model.getResidues()) {
300 // if (currentChimMap.containsKey(residue)) {
301 // for (CyIdentifiable cyObjRes : currentChimMap.get(residue)) {
302 // if (currentCyMap.containsKey(cyObjRes)) {
303 // currentCyMap.get(cyObjRes).remove(residue);
306 // currentChimMap.remove(residue);
311 // currentChimMap.remove(model);
315 // public void addStructureNetwork(CyNetwork rin) {
316 // if (rin == null) {
319 // ChimeraModel model = null;
320 // // the network is not added to the model in the currentChimMap
321 // List<String> attrsFound =
322 // CytoUtils.getMatchingAttributes(rin.getDefaultNodeTable(),
323 // getCurrentStructureKeys(rin));
324 // for (CyNode node : rin.getNodeList()) {
325 // if (!networkMap.containsKey(node)) {
326 // networkMap.put(node, new HashSet<CyNetwork>());
328 // networkMap.get(node).add(rin);
329 // List<String> specsFound =
330 // ChimUtils.getResidueKeys(rin.getDefaultNodeTable(), node,
332 // for (String residueSpec : specsFound) {
333 // // if (!rin.getRow(node).isSet(ChimUtils.RESIDUE_ATTR)) {
336 // // String residueSpec = rin.getRow(node).get(ChimUtils.RESIDUE_ATTR,
338 // ChimeraStructuralObject chimObj = ChimUtils.fromAttribute(residueSpec,
340 // // chimObj.getChimeraModel().addCyObject(node, rin);
341 // if (chimObj == null || chimObj instanceof ChimeraModel) {
344 // model = chimObj.getChimeraModel();
345 // if (!currentCyMap.containsKey(node)) {
346 // currentCyMap.put(node, new HashSet<ChimeraStructuralObject>());
348 // currentCyMap.get(node).add(chimObj);
349 // if (!currentChimMap.containsKey(chimObj)) {
350 // currentChimMap.put(chimObj, new HashSet<CyIdentifiable>());
352 // currentChimMap.get(chimObj).add(node);
355 // if (model != null) {
356 // model.addCyObject(rin, rin);
357 // if (!currentCyMap.containsKey(rin)) {
358 // currentCyMap.put(rin, new HashSet<ChimeraStructuralObject>());
360 // currentCyMap.get(rin).add(model);
364 public void exitChimera()
366 // // exit chimera, invokes clearOnExitChimera
367 // if (mnDialog != null) {
368 // mnDialog.setVisible(false);
371 // if (alDialog != null) {
372 // alDialog.setVisible(false);
374 chimeraManager.exitChimera();
377 // invoked by ChimeraManager whenever Chimera exits
378 public void clearOnChimeraExit()
380 // // clear structures
381 // currentCyMap.clear();
382 // currentChimMap.clear();
383 // networkMap.clear();
384 chimSelectionList.clear();
385 // if (chimTable != null) {
387 // getService(CyTableManager.class)).deleteTable(chimTable.getSUID());
389 // if (mnDialog != null) {
390 // if (mnDialog.isVisible()) {
391 // mnDialog.lostChimera();
392 // mnDialog.setVisible(false);
395 // if (alDialog != null) {
396 // alDialog.setVisible(false);
401 // We need to do this in two passes since some parts of a structure might be
402 // selected and some might not. Our selection model (unfortunately) only
404 // us that something has changed, not what...
405 public void updateCytoscapeSelection()
407 // List<ChimeraStructuralObject> selectedChimObj
408 ignoreCySelection = true;
409 // System.out.println("update Cytoscape selection");
410 // find all possibly selected Cytoscape objects and unselect them
411 // Set<CyNetwork> networks = new HashSet<CyNetwork>();
412 // for (CyIdentifiable currentCyObj : currentCyMap.keySet()) {
413 // if (!networkMap.containsKey(currentCyObj)) {
416 // Set<CyNetwork> currentCyNetworks = networkMap.get(currentCyObj);
417 // if (currentCyNetworks == null || currentCyNetworks.size() == 0) {
421 // for (CyNetwork network : currentCyNetworks) {
422 // if ((currentCyObj instanceof CyNode && network.containsNode((CyNode)
424 // || (currentCyObj instanceof CyEdge && network
425 // .containsEdge((CyEdge) currentCyObj))) {
426 // network.getRow(currentCyObj).set(CyNetwork.SELECTED, false);
427 // networks.add(network);
432 // // select only those associated with selected Chimera objects
433 // Set<CyIdentifiable> currentCyObjs = new HashSet<CyIdentifiable>();
434 // for (ChimeraStructuralObject chimObj : chimSelectionList) {
435 // ChimeraModel currentSelModel = chimObj.getChimeraModel();
436 // if (currentChimMap.containsKey(currentSelModel)) {
437 // currentCyObjs.addAll(currentChimMap.get(currentSelModel));
439 // if (currentChimMap.containsKey(chimObj)) {
440 // currentCyObjs.addAll(currentChimMap.get(chimObj));
442 // // System.out.println(chimObj.toSpec() + ": " +
443 // // currentCyObjs.size());
445 // for (CyIdentifiable cyObj : currentCyObjs) {
446 // // System.out.println(cyObj.toString());
447 // if (cyObj == null || !networkMap.containsKey(cyObj)) {
450 // Set<CyNetwork> currentCyNetworks = networkMap.get(cyObj);
451 // if (currentCyNetworks == null || currentCyNetworks.size() == 0) {
454 // for (CyNetwork network : currentCyNetworks) {
455 // if ((cyObj instanceof CyNode && network.containsNode((CyNode) cyObj))
456 // || (cyObj instanceof CyEdge && network.containsEdge((CyEdge) cyObj))) {
457 // network.getRow(cyObj).set(CyNetwork.SELECTED, true);
458 // networks.add(network);
463 // CyNetworkViewManager cyNetViewManager = (CyNetworkViewManager)
464 // getService(CyNetworkViewManager.class);
465 // // Update network views
466 // for (CyNetwork network : networks) {
467 // Collection<CyNetworkView> views =
468 // cyNetViewManager.getNetworkViews(network);
469 // for (CyNetworkView view : views) {
470 // view.updateView();
473 ignoreCySelection = false;
476 public void cytoscapeSelectionChanged(Map<Long, Boolean> selectedRows)
478 // if (ignoreCySelection || currentCyMap.size() == 0) {
481 // // clearSelectionList();
482 // // System.out.println("cytoscape selection changed");
483 // // iterate over all cy objects with associated models
484 // for (CyIdentifiable cyObj : currentCyMap.keySet()) {
485 // if (cyObj instanceof CyNetwork ||
486 // !selectedRows.containsKey(cyObj.getSUID())) {
489 // for (ChimeraStructuralObject chimObj : currentCyMap.get(cyObj)) {
490 // if (selectedRows.get(cyObj.getSUID())) {
491 // addChimSelection(chimObj);
492 // if (chimObj instanceof ChimeraResidue) {
493 // if (chimObj.getChimeraModel().isSelected()) {
494 // removeChimSelection(chimObj.getChimeraModel());
495 // } else if (chimObj.getChimeraModel()
496 // .getChain(((ChimeraResidue) chimObj).getChainId()).isSelected()) {
497 // removeChimSelection(chimObj.getChimeraModel().getChain(
498 // ((ChimeraResidue) chimObj).getChainId()));
502 // removeChimSelection(chimObj);
503 // if (chimObj.hasSelectedChildren() && chimObj instanceof ChimeraModel) {
504 // for (ChimeraResidue residue : ((ChimeraModel) chimObj)
505 // .getSelectedResidues()) {
506 // removeChimSelection(residue);
512 // System.out.println("selection list: " + getChimSelectionCount());
513 updateChimeraSelection();
517 // Save models in a HashMap/Set for better performance?
518 public void updateChimeraSelection()
520 // System.out.println("update Chimera selection");
522 for (int i = 0; i < chimSelectionList.size(); i++)
524 ChimeraStructuralObject nodeInfo = chimSelectionList.get(i);
525 // we do not care about the model anymore
526 selSpec = selSpec.concat(nodeInfo.toSpec());
527 if (i < chimSelectionList.size() - 1)
532 if (selSpec.length() > 0)
534 chimeraManager.select("sel " + selSpec);
538 chimeraManager.select("~sel");
543 * This is called by the selectionListener to let us know that the user has
544 * changed their selection in Chimera. We need to go back to Chimera to find
545 * out what is currently selected and update our list.
547 public void chimeraSelectionChanged()
549 // System.out.println("Chimera selection changed");
550 clearSelectionList();
551 // Execute the command to get the list of models with selections
552 Map<Integer, ChimeraModel> selectedModelsMap = chimeraManager
553 .getSelectedModels();
554 // Now get the residue-level data
555 chimeraManager.getSelectedResidues(selectedModelsMap);
556 // Get the selected objects
559 for (ChimeraModel selectedModel : selectedModelsMap.values())
561 int modelNumber = selectedModel.getModelNumber();
562 int subModelNumber = selectedModel.getSubModelNumber();
563 // Get the corresponding "real" model
564 if (chimeraManager.hasChimeraModel(modelNumber, subModelNumber))
566 ChimeraModel dataModel = chimeraManager
567 .getChimeraModel(modelNumber, subModelNumber);
568 if (dataModel.getResidueCount() == selectedModel.getResidueCount()
570 .getModelType() == StructureManager.ModelType.SMILES)
572 // Select the entire model
573 addChimSelection(dataModel);
574 // dataModel.setSelected(true);
578 for (ChimeraChain selectedChain : selectedModel.getChains())
580 ChimeraChain dataChain = dataModel
581 .getChain(selectedChain.getChainId());
582 if (selectedChain.getResidueCount() == dataChain
585 addChimSelection(dataChain);
586 // dataChain.setSelected(true);
589 // Need to select individual residues
590 for (ChimeraResidue res : selectedChain.getResidues())
592 String residueIndex = res.getIndex();
593 ChimeraResidue residue = dataChain.getResidue(residueIndex);
598 addChimSelection(residue);
599 // residue.setSelected(true);
602 } // chainIter.hasNext()
605 } // modelIter.hasNext()
606 } catch (Exception ex)
608 logger.warn("Could not update selection", ex);
610 // System.out.println("selection list: " + getChimSelectionCount());
611 // Finally, update the navigator panel
613 updateCytoscapeSelection();
616 public void selectFunctResidues(Collection<ChimeraModel> models)
618 clearSelectionList();
619 for (ChimeraModel model : models)
621 for (ChimeraResidue residue : model.getFuncResidues())
623 addChimSelection(residue);
626 updateChimeraSelection();
627 updateCytoscapeSelection();
631 // public void selectFunctResidues(CyNode node, CyNetwork network) {
632 // clearSelectionList();
633 // if (currentCyMap.containsKey(node)) {
634 // Set<ChimeraStructuralObject> chimObjects = currentCyMap.get(node);
635 // for (ChimeraStructuralObject obj : chimObjects) {
636 // if (obj instanceof ChimeraModel) {
637 // ChimeraModel model = (ChimeraModel) obj;
638 // for (ChimeraResidue residue : model.getFuncResidues()) {
639 // addChimSelection(residue);
644 // updateChimeraSelection();
645 // updateCytoscapeSelection();
646 // selectionChanged();
649 public List<ChimeraStructuralObject> getChimSelectionList()
651 return chimSelectionList;
654 public int getChimSelectionCount()
656 return chimSelectionList.size();
660 * Add a selection to the selection list. This is called primarily by the
661 * Model Navigator Dialog to keep the selections in sync
663 * @param selectionToAdd
664 * the selection to add to our list
666 public void addChimSelection(ChimeraStructuralObject selectionToAdd)
668 if (selectionToAdd != null
669 && !chimSelectionList.contains(selectionToAdd))
671 chimSelectionList.add(selectionToAdd);
672 selectionToAdd.setSelected(true);
677 * Remove a selection from the selection list. This is called primarily by the
678 * Model Navigator Dialog to keep the selections in sync
680 * @param selectionToRemove
681 * the selection to remove from our list
683 public void removeChimSelection(ChimeraStructuralObject selectionToRemove)
685 if (selectionToRemove != null
686 && chimSelectionList.contains(selectionToRemove))
688 chimSelectionList.remove(selectionToRemove);
689 selectionToRemove.setSelected(false);
694 * Clear the list of selected objects
696 public void clearSelectionList()
698 for (ChimeraStructuralObject cso : chimSelectionList)
702 cso.setSelected(false);
705 chimSelectionList.clear();
709 * Associate a new network with the corresponding Chimera objects.
715 * Dump and refresh all of our model/chain/residue info
717 public void updateModels()
719 // Stop all of our listeners while we try to handle this
720 chimeraManager.stopListening();
722 // Get all of the open models
723 List<ChimeraModel> newModelList = chimeraManager.getModelList();
725 // Match them up -- assume that the model #'s haven't changed
726 for (ChimeraModel newModel : newModelList)
728 // Get the color (for our navigator)
729 newModel.setModelColor(chimeraManager.getModelColor(newModel));
731 // Get our model info
732 int modelNumber = newModel.getModelNumber();
733 int subModelNumber = newModel.getSubModelNumber();
735 // If we already know about this model number, get the Structure,
736 // which tells us about the associated CyNode
737 if (chimeraManager.hasChimeraModel(modelNumber, subModelNumber))
739 ChimeraModel oldModel = chimeraManager.getChimeraModel(modelNumber,
741 chimeraManager.removeChimeraModel(modelNumber, subModelNumber);
742 newModel.setModelType(oldModel.getModelType());
743 if (oldModel.getModelType() == ModelType.SMILES)
745 newModel.setModelName(oldModel.getModelName());
747 // re-assign associations to cytoscape objects
748 // Map<CyIdentifiable, CyNetwork> oldModelCyObjs =
749 // oldModel.getCyObjects();
750 // for (CyIdentifiable cyObj : oldModelCyObjs.keySet()) {
751 // // add cy objects to the new model
752 // newModel.addCyObject(cyObj, oldModelCyObjs.get(cyObj));
753 // if (currentCyMap.containsKey(cyObj)) {
754 // currentCyMap.get(cyObj).add(newModel);
755 // if (currentCyMap.get(cyObj).contains(oldModel)) {
756 // currentCyMap.get(cyObj).remove(oldModel);
760 // // add new model to the chimera objects map and remove old model
761 // if (currentChimMap.containsKey(oldModel)) {
762 // currentChimMap.put(newModel, currentChimMap.get(oldModel));
763 // currentChimMap.remove(oldModel);
766 // add new model to ChimeraManager
767 chimeraManager.addChimeraModel(modelNumber, subModelNumber, newModel);
769 // Get the residue information
770 if (newModel.getModelType() != ModelType.SMILES)
772 chimeraManager.addResidues(newModel);
774 // for (CyIdentifiable cyObj : newModel.getCyObjects().keySet()) {
775 // if (cyObj != null && cyObj instanceof CyNetwork) {
776 // addStructureNetwork((CyNetwork) cyObj);
777 // } else if (cyObj != null && cyObj instanceof CyNode) {
778 // newModel.setFuncResidues(ChimUtils.parseFuncRes(
779 // getResidueList(newModel.getCyObjects().get(cyObj), cyObj),
780 // newModel.getModelName()));
785 // associate all models with any node or network
786 // aTask.associate();
788 // Restart all of our listeners
789 chimeraManager.startListening();
793 public void launchModelNavigatorDialog()
795 // TODO: [Optional] Use haveGUI flag
799 // if (mnDialog == null) {
800 // CySwingApplication cyApplication = (CySwingApplication)
801 // getService(CySwingApplication.class);
802 // mnDialog = new ModelNavigatorDialog(cyApplication.getJFrame(), this);
805 // mnDialog.setVisible(true);
808 public boolean isMNDialogOpen()
810 // if (mnDialog != null && mnDialog.isVisible()) {
817 * Invoked by the listener thread.
819 public void modelChanged()
821 // if (mnDialog != null) {
822 // mnDialog.modelChanged();
827 * Inform our interface that the selection has changed
829 public void selectionChanged()
831 // if (mnDialog != null) {
832 // // System.out.println("update dialog selection");
833 // mnDialog.updateSelection(new
834 // ArrayList<ChimeraStructuralObject>(chimSelectionList));
838 public void launchAlignDialog(boolean useChains)
840 // TODO: [Optional] Use haveGUI flag
841 // Sometimes it does not appear in Windows
845 // if (alDialog != null) {
846 // alDialog.setVisible(false);
847 // alDialog.dispose();
849 // System.out.println("launch align dialog");
850 List<ChimeraStructuralObject> chimObjectList = new ArrayList<>();
851 for (ChimeraModel model : chimeraManager.getChimeraModels())
855 for (ChimeraChain chain : model.getChains())
857 chimObjectList.add(chain);
862 chimObjectList.add(model);
865 // Bring up the dialog
866 // CySwingApplication cyApplication = (CySwingApplication)
867 // getService(CySwingApplication.class);
868 // alDialog = new AlignStructuresDialog(cyApplication.getJFrame(), this,
871 // alDialog.setVisible(true);
874 public List<String> getAllStructureKeys()
876 return Arrays.asList(defaultStructureKeys);
879 public List<String> getAllChemStructKeys()
881 return Arrays.asList(defaultChemStructKeys);
884 public List<String> getAllResidueKeys()
886 return Arrays.asList(defaultResidueKeys);
889 public List<String> getAllChimeraResidueAttributes()
891 List<String> attributes = new ArrayList<>();
892 // attributes.addAll(rinManager.getResAttrs());
893 attributes.addAll(chimeraManager.getAttrList());
897 StructureSettings defaultSettings = null;
899 // TODO: [Optional] Change priority of Chimera paths
900 public static List<String> getChimeraPaths()
902 List<String> pathList = new ArrayList<>();
904 // if no network is available and the settings have been modified by the
908 // For Jalview, Preferences/Cache plays this role instead
909 // if (defaultSettings != null)
911 // String defaultPath = defaultSettings.getChimeraPath();
912 // if (defaultPath != null && !defaultPath.equals(""))
914 // pathList.add(defaultPath);
920 * Jalview addition: check if path set in user preferences.
922 String userPath = Cache.getDefault(Preferences.CHIMERA_PATH, null);
923 if (userPath != null)
925 pathList.add(0, userPath);
928 // Add default installation paths
929 String os = System.getProperty("os.name");
930 if (os.startsWith("Linux"))
932 pathList.add("/usr/local/chimera/bin/chimera");
933 pathList.add("/usr/local/bin/chimera");
934 pathList.add("/usr/bin/chimera");
935 pathList.add(Platform.getUserPath("opt/bin/chimera"));
937 else if (os.startsWith("Windows"))
939 for (String root : new String[] { "\\Program Files",
940 "C:\\Program Files", "\\Program Files (x86)",
941 "C:\\Program Files (x86)" })
943 for (String version : new String[] { "1.11", "1.11.1", "1.11.2",
944 "1.12", "1.12.1", "1.12.2", "1.13" })
946 pathList.add(root + "\\Chimera " + version + "\\bin\\chimera");
948 root + "\\Chimera " + version + "\\bin\\chimera.exe");
952 else if (os.startsWith("Mac"))
954 pathList.add("/Applications/Chimera.app/Contents/MacOS/chimera");
959 public void setChimeraPathProperty(String path)
961 // CytoUtils.setDefaultChimeraPath(registrar, chimeraPropertyName,
962 // chimeraPathPropertyKey,
966 public void setStructureSettings(StructureSettings structureSettings)
968 this.defaultSettings = structureSettings;
971 public String getCurrentChimeraPath(Object object)
973 if (defaultSettings != null)
975 return defaultSettings.getChimeraPath();
983 // public void initChimTable() {
984 // CyTableManager manager = (CyTableManager) getService(CyTableManager.class);
985 // CyTableFactory factory = (CyTableFactory) getService(CyTableFactory.class);
986 // for (CyTable table : manager.getGlobalTables()) {
987 // if (table.getTitle().equals(chimeraOutputTable)) {
988 // manager.deleteTable(table.getSUID());
991 // chimTable = factory.createTable(chimeraOutputTable, chimeraCommandAttr,
994 // manager.addTable(chimTable);
995 // if (chimTable.getColumn(chimeraOutputAttr) == null) {
996 // chimTable.createListColumn(chimeraOutputAttr, String.class, false);
1000 // public void addChimReply(String command, List<String> reply) {
1001 // chimTable.getRow(command).set(chimeraOutputAttr, reply);