Clover icon

jalviewX

  1. Project Clover database Wed Oct 31 2018 15:13:58 GMT
  2. Package ext.edu.ucsf.rbvi.strucviz2

File StructureManager.java

 

Coverage histogram

../../../../../img/srcFileCovDistChart1.png
53% of files have more coverage

Code metrics

46
141
32
2
1,002
394
60
0.43
4.41
16
1.88

Classes

Class Line # Actions
StructureManager 57 141 60 202
0.077625577.8%
StructureManager.ModelType 69 0 0 0
-1.0 -
 

Contributing tests

No tests hitting this source file were found.

Source view

1    /* vim: set ts=2: */
2    /**
3    * Copyright (c) 2006 The Regents of the University of California.
4    * All rights reserved.
5    *
6    * Redistribution and use in source and binary forms, with or without
7    * modification, are permitted provided that the following conditions
8    * are met:
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,
18    * grant P41-RR01081.
19    *
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.
31    *
32    */
33    package ext.edu.ucsf.rbvi.strucviz2;
34   
35    import jalview.bin.Cache;
36    import jalview.gui.Preferences;
37   
38    import java.io.File;
39    import java.io.IOException;
40    import java.util.ArrayList;
41    import java.util.Arrays;
42    import java.util.Collection;
43    import java.util.HashMap;
44    import java.util.List;
45    import java.util.Map;
46    import java.util.Properties;
47    import java.util.Set;
48   
49    import org.slf4j.Logger;
50    import org.slf4j.LoggerFactory;
51   
52    /**
53    * This object maintains the relationship between Chimera objects and Cytoscape
54    * objects.
55    */
56   
 
57    public class StructureManager
58    {
59    static final String[] defaultStructureKeys = { "Structure", "pdb",
60    "pdbFileName", "PDB ID", "structure", "biopax.xref.PDB", "pdb_ids",
61    "ModelName", "ModelNumber" };
62   
63    static final String[] defaultChemStructKeys = { "Smiles", "smiles",
64    "SMILES" };
65   
66    static final String[] defaultResidueKeys = { "FunctionalResidues",
67    "ResidueList", "Residues" };
68   
 
69    public enum ModelType
70    {
71    PDB_MODEL, MODBASE_MODEL, SMILES
72    };
73   
74    public static Properties pathProps;
75   
76    private String chimeraCommandAttr = "ChimeraCommand";
77   
78    private String chimeraOutputTable = "ChimeraTable";
79   
80    private String chimeraOutputAttr = "ChimeraOutput";
81   
82    private boolean haveGUI = true;
83   
84    private ChimeraManager chimeraManager = null;
85   
86    static private List<ChimeraStructuralObject> chimSelectionList;
87   
88    private boolean ignoreCySelection = false;
89   
90    private File configurationDirectory = null;
91   
92    private static Logger logger = LoggerFactory
93    .getLogger(ext.edu.ucsf.rbvi.strucviz2.StructureManager.class);
94   
 
95  1 toggle public StructureManager(boolean haveGUI)
96    {
97  1 this.haveGUI = haveGUI;
98    // Create the Chimera interface
99  1 chimeraManager = new ChimeraManager(this);
100  1 chimSelectionList = new ArrayList<>();
101  1 pathProps = new Properties();
102    }
103   
 
104  0 toggle public ChimeraManager getChimeraManager()
105    {
106  0 return chimeraManager;
107    }
108   
 
109  0 toggle public boolean openStructures(Collection<List<String>> chimObjNames,
110    ModelType type)
111    {
112    // new models
113  0 Map<String, List<ChimeraModel>> newModels = new HashMap<>();
114  0 if (chimObjNames.size() > 0)
115    {
116  0 List<String> names = chimObjNames.iterator().next();
117  0 if (names == null)
118    {
119  0 return false;
120    }
121  0 for (String chimObjName : names)
122    {
123    // get or open the corresponding models if they already exist
124  0 List<ChimeraModel> currentModels = chimeraManager.getChimeraModels(
125    chimObjName, type);
126  0 if (currentModels.size() == 0)
127    {
128    // open and return models
129  0 currentModels = chimeraManager.openModel(chimObjName, type);
130  0 if (currentModels == null)
131    {
132    // failed to open model, continue with next
133  0 continue;
134    }
135    // if (type == ModelType.SMILES) {
136    // newModels.put("smiles:" + chimObjName, currentModels);
137    // } else {
138  0 newModels.put(chimObjName, currentModels);
139    // }
140    // for each model
141  0 for (ChimeraModel currentModel : currentModels)
142    {
143    // if not RIN then associate new model with the Cytoscape
144    // node
145    // if (!currentChimMap.containsKey(currentModel)) {
146    // currentChimMap.put(currentModel, new HashSet<CyIdentifiable>());
147    // }
148    }
149    }
150    }
151    }
152    else
153    {
154  0 return false;
155    }
156    // update dialog
157    // if (mnDialog != null) {
158    // mnDialog.modelChanged();
159    // }
160    // aTask.associate();
161  0 return true;
162   
163    }
164   
165    // TODO: [Release] Handle case where one network is associated with two models
166    // that are opened
167    // at the same time
168    /*
169    * public boolean openStructures(CyNetwork network, Map<CyIdentifiable,
170    * List<String>> chimObjNames, ModelType type) { if
171    * (!chimeraManager.isChimeraLaunched() &&
172    * !chimeraManager.launchChimera(getChimeraPaths(network))) {
173    * logger.error("Chimera could not be launched."); return false; } else if
174    * (chimObjNames.size() == 0) { return false; } else if (network == null) {
175    * return openStructures(chimObjNames.values(), type); }
176    *
177    * // potential rins Set<CyNetwork> potentialRINs = new HashSet<CyNetwork>();
178    * // attributes List<String> attrsFound = new ArrayList<String>();
179    * attrsFound.
180    * addAll(CytoUtils.getMatchingAttributes(network.getDefaultNodeTable(),
181    * getCurrentStructureKeys(network)));
182    * attrsFound.addAll(CytoUtils.getMatchingAttributes
183    * (network.getDefaultNodeTable(), getCurrentChemStructKeys(network))); // new
184    * models Map<String, List<ChimeraModel>> newModels = new HashMap<String,
185    * List<ChimeraModel>>(); // for each node that has an associated structure
186    * for (CyIdentifiable cyObj : chimObjNames.keySet()) { // get possible res
187    * specs List<String> specsFound = null; if (cyObj instanceof CyNode) {
188    * specsFound = ChimUtils.getResidueKeys(network.getDefaultNodeTable(), cyObj,
189    * attrsFound); } // save node to track its selection and mapping to chimera
190    * objects if (!currentCyMap.containsKey(cyObj)) { currentCyMap.put(cyObj, new
191    * HashSet<ChimeraStructuralObject>()); } // save node to network mapping to
192    * keep track of selection events if (!networkMap.containsKey(cyObj)) {
193    * networkMap.put(cyObj, new HashSet<CyNetwork>()); }
194    * networkMap.get(cyObj).add(network); // for each structure that has to be
195    * opened for (String chimObjName : chimObjNames.get(cyObj)) { // get or open
196    * the corresponding models if they already exist List<ChimeraModel>
197    * currentModels = chimeraManager.getChimeraModels(chimObjName, type); if
198    * (currentModels.size() == 0) { // open and return models currentModels =
199    * chimeraManager.openModel(chimObjName, type); if (currentModels == null) {
200    * // failed to open model, continue with next continue; } // if (type ==
201    * ModelType.SMILES) { // newModels.put("smiles:" + chimObjName,
202    * currentModels); // } else { newModels.put(chimObjName, currentModels); // }
203    * // for each model for (ChimeraModel currentModel : currentModels) { //
204    * check if it is a RIN boolean foundRIN = false; if
205    * (currentModel.getModelType().equals(ModelType.PDB_MODEL)) { // go through
206    * all node annotations and check if any of them is a residue // or a chain if
207    * (cyObj instanceof CyNode && network.containsNode((CyNode) cyObj) &&
208    * specsFound != null && specsFound.size() > 0) { for (String resSpec :
209    * specsFound) { ChimeraStructuralObject res =
210    * ChimUtils.fromAttribute(resSpec, chimeraManager); if (res != null && (res
211    * instanceof ChimeraResidue || res instanceof ChimeraChain)) { // if so,
212    * assume it might be a RIN potentialRINs.add(network); foundRIN = true;
213    * break; } } } else if (cyObj instanceof CyNetwork) { // if cyObj is a
214    * network, check for residue/chain annotations in an // arbitrary node
215    * CyNetwork rinNet = (CyNetwork) cyObj; if (rinNet.getNodeList().size() > 0)
216    * { specsFound = ChimUtils.getResidueKeys( rinNet.getDefaultNodeTable(),
217    * rinNet.getNodeList().get(0), attrsFound); for (String resSpec : specsFound)
218    * { ChimeraStructuralObject res = ChimUtils.fromAttribute( resSpec,
219    * chimeraManager); if (res != null && (res instanceof ChimeraResidue || res
220    * instanceof ChimeraChain)) { potentialRINs.add(network); foundRIN = true;
221    * break; } } } } } if (foundRIN) { continue; } // if not RIN then associate
222    * new model with the Cytoscape // node if
223    * (!currentChimMap.containsKey(currentModel)) {
224    * currentChimMap.put(currentModel, new HashSet<CyIdentifiable>()); } String
225    * cyObjName = network.getRow(cyObj).get(CyNetwork.NAME, String.class); if
226    * (cyObjName != null && cyObjName.endsWith(currentModel.getModelName())) { //
227    * it is a modbase model, associate directly
228    * currentCyMap.get(cyObj).add(currentModel);
229    * currentChimMap.get(currentModel).add(cyObj);
230    * currentModel.addCyObject(cyObj, network); } else if (specsFound != null &&
231    * specsFound.size() > 0) { for (String resSpec : specsFound) {
232    * ChimeraStructuralObject specModel = ChimUtils.fromAttribute( resSpec,
233    * chimeraManager); if (specModel == null &&
234    * resSpec.equals(currentModel.getModelName())) { specModel =
235    * chimeraManager.getChimeraModel( currentModel.getModelNumber(),
236    * currentModel.getSubModelNumber()); } if (specModel != null &&
237    * currentModel.toSpec().equals(specModel.toSpec()) ||
238    * currentModel.getModelName().equals("smiles:" + resSpec)) {
239    * currentCyMap.get(cyObj).add(currentModel);
240    * currentChimMap.get(currentModel).add(cyObj);
241    * currentModel.addCyObject(cyObj, network);
242    * currentModel.setFuncResidues(ChimUtils.parseFuncRes(
243    * getResidueList(network, cyObj), chimObjName)); } } } } } } } // networks
244    * that contain nodes associated to newly opened models // this will usually
245    * be of length 1 for (CyNetwork net : potentialRINs) {
246    * addStructureNetwork(net); } // update dialog if (mnDialog != null) {
247    * mnDialog.modelChanged(); } aTask.associate(); return true; }
248    */
 
249  0 toggle public void closeStructures(Set<String> chimObjNames)
250    {
251    // for each cytoscape object and chimera model pair
252  0 for (String modelName : chimObjNames)
253    {
254  0 List<ChimeraModel> models = chimeraManager
255    .getChimeraModels(modelName);
256  0 for (ChimeraModel model : models)
257    {
258  0 closeModel(model);
259    }
260    }
261    // if (mnDialog != null) {
262    // mnDialog.modelChanged();
263    // }
264    }
265   
266    // TODO: [Optional] Can we make a screenshot of a single molecule?
 
267  0 toggle public File saveChimeraImage()
268    {
269  0 File tmpFile = null;
270  0 try
271    {
272    // Create the temp file name
273  0 tmpFile = File.createTempFile("structureViz", ".png");
274  0 chimeraManager.sendChimeraCommand("set bgTransparency", false);
275  0 chimeraManager.sendChimeraCommand(
276    "copy file " + tmpFile.getAbsolutePath() + " png", true);
277  0 chimeraManager.sendChimeraCommand("unset bgTransparency", false);
278    } catch (IOException ioe)
279    {
280    // Log error
281  0 logger.error("Error writing image", ioe);
282    }
283  0 return tmpFile;
284    }
285   
 
286  0 toggle public void closeModel(ChimeraModel model)
287    {
288    // close model in Chimera
289  0 chimeraManager.closeModel(model);
290    // remove all associations
291    // if (currentChimMap.containsKey(model)) {
292    // for (CyIdentifiable cyObj : model.getCyObjects().keySet()) {
293    // if (cyObj == null) {
294    // continue;
295    // } else if (currentCyMap.containsKey(cyObj)) {
296    // currentCyMap.get(cyObj).remove(model);
297    // } else if (cyObj instanceof CyNetwork) {
298    // for (ChimeraResidue residue : model.getResidues()) {
299    // if (currentChimMap.containsKey(residue)) {
300    // for (CyIdentifiable cyObjRes : currentChimMap.get(residue)) {
301    // if (currentCyMap.containsKey(cyObjRes)) {
302    // currentCyMap.get(cyObjRes).remove(residue);
303    // }
304    // }
305    // currentChimMap.remove(residue);
306    // }
307    // }
308    // }
309    // }
310    // currentChimMap.remove(model);
311    // }
312    }
313   
314    // public void addStructureNetwork(CyNetwork rin) {
315    // if (rin == null) {
316    // return;
317    // }
318    // ChimeraModel model = null;
319    // // the network is not added to the model in the currentChimMap
320    // List<String> attrsFound =
321    // CytoUtils.getMatchingAttributes(rin.getDefaultNodeTable(),
322    // getCurrentStructureKeys(rin));
323    // for (CyNode node : rin.getNodeList()) {
324    // if (!networkMap.containsKey(node)) {
325    // networkMap.put(node, new HashSet<CyNetwork>());
326    // }
327    // networkMap.get(node).add(rin);
328    // List<String> specsFound =
329    // ChimUtils.getResidueKeys(rin.getDefaultNodeTable(), node,
330    // attrsFound);
331    // for (String residueSpec : specsFound) {
332    // // if (!rin.getRow(node).isSet(ChimUtils.RESIDUE_ATTR)) {
333    // // continue;
334    // // }
335    // // String residueSpec = rin.getRow(node).get(ChimUtils.RESIDUE_ATTR,
336    // String.class);
337    // ChimeraStructuralObject chimObj = ChimUtils.fromAttribute(residueSpec,
338    // chimeraManager);
339    // // chimObj.getChimeraModel().addCyObject(node, rin);
340    // if (chimObj == null || chimObj instanceof ChimeraModel) {
341    // continue;
342    // }
343    // model = chimObj.getChimeraModel();
344    // if (!currentCyMap.containsKey(node)) {
345    // currentCyMap.put(node, new HashSet<ChimeraStructuralObject>());
346    // }
347    // currentCyMap.get(node).add(chimObj);
348    // if (!currentChimMap.containsKey(chimObj)) {
349    // currentChimMap.put(chimObj, new HashSet<CyIdentifiable>());
350    // }
351    // currentChimMap.get(chimObj).add(node);
352    // }
353    // }
354    // if (model != null) {
355    // model.addCyObject(rin, rin);
356    // if (!currentCyMap.containsKey(rin)) {
357    // currentCyMap.put(rin, new HashSet<ChimeraStructuralObject>());
358    // }
359    // currentCyMap.get(rin).add(model);
360    // }
361    // }
362   
 
363  0 toggle public void exitChimera()
364    {
365    // // exit chimera, invokes clearOnExitChimera
366    // if (mnDialog != null) {
367    // mnDialog.setVisible(false);
368    // mnDialog = null;
369    // }
370    // if (alDialog != null) {
371    // alDialog.setVisible(false);
372    // }
373  0 chimeraManager.exitChimera();
374    }
375   
376    // invoked by ChimeraManager whenever Chimera exits
 
377  0 toggle public void clearOnChimeraExit()
378    {
379    // // clear structures
380    // currentCyMap.clear();
381    // currentChimMap.clear();
382    // networkMap.clear();
383  0 chimSelectionList.clear();
384    // if (chimTable != null) {
385    // ((CyTableManager)
386    // getService(CyTableManager.class)).deleteTable(chimTable.getSUID());
387    // }
388    // if (mnDialog != null) {
389    // if (mnDialog.isVisible()) {
390    // mnDialog.lostChimera();
391    // mnDialog.setVisible(false);
392    // }
393    // mnDialog = null;
394    // if (alDialog != null) {
395    // alDialog.setVisible(false);
396    // }
397    // }
398    }
399   
400    // We need to do this in two passes since some parts of a structure might be
401    // selected and some might not. Our selection model (unfortunately) only
402    // tells
403    // us that something has changed, not what...
 
404  0 toggle public void updateCytoscapeSelection()
405    {
406    // List<ChimeraStructuralObject> selectedChimObj
407  0 ignoreCySelection = true;
408    // System.out.println("update Cytoscape selection");
409    // find all possibly selected Cytoscape objects and unselect them
410    // Set<CyNetwork> networks = new HashSet<CyNetwork>();
411    // for (CyIdentifiable currentCyObj : currentCyMap.keySet()) {
412    // if (!networkMap.containsKey(currentCyObj)) {
413    // continue;
414    // }
415    // Set<CyNetwork> currentCyNetworks = networkMap.get(currentCyObj);
416    // if (currentCyNetworks == null || currentCyNetworks.size() == 0) {
417    //
418    // continue;
419    // }
420    // for (CyNetwork network : currentCyNetworks) {
421    // if ((currentCyObj instanceof CyNode && network.containsNode((CyNode)
422    // currentCyObj))
423    // || (currentCyObj instanceof CyEdge && network
424    // .containsEdge((CyEdge) currentCyObj))) {
425    // network.getRow(currentCyObj).set(CyNetwork.SELECTED, false);
426    // networks.add(network);
427    // }
428    // }
429    // }
430    //
431    // // select only those associated with selected Chimera objects
432    // Set<CyIdentifiable> currentCyObjs = new HashSet<CyIdentifiable>();
433    // for (ChimeraStructuralObject chimObj : chimSelectionList) {
434    // ChimeraModel currentSelModel = chimObj.getChimeraModel();
435    // if (currentChimMap.containsKey(currentSelModel)) {
436    // currentCyObjs.addAll(currentChimMap.get(currentSelModel));
437    // }
438    // if (currentChimMap.containsKey(chimObj)) {
439    // currentCyObjs.addAll(currentChimMap.get(chimObj));
440    // }
441    // // System.out.println(chimObj.toSpec() + ": " +
442    // // currentCyObjs.size());
443    // }
444    // for (CyIdentifiable cyObj : currentCyObjs) {
445    // // System.out.println(cyObj.toString());
446    // if (cyObj == null || !networkMap.containsKey(cyObj)) {
447    // continue;
448    // }
449    // Set<CyNetwork> currentCyNetworks = networkMap.get(cyObj);
450    // if (currentCyNetworks == null || currentCyNetworks.size() == 0) {
451    // continue;
452    // }
453    // for (CyNetwork network : currentCyNetworks) {
454    // if ((cyObj instanceof CyNode && network.containsNode((CyNode) cyObj))
455    // || (cyObj instanceof CyEdge && network.containsEdge((CyEdge) cyObj))) {
456    // network.getRow(cyObj).set(CyNetwork.SELECTED, true);
457    // networks.add(network);
458    // }
459    // }
460    // }
461    //
462    // CyNetworkViewManager cyNetViewManager = (CyNetworkViewManager)
463    // getService(CyNetworkViewManager.class);
464    // // Update network views
465    // for (CyNetwork network : networks) {
466    // Collection<CyNetworkView> views =
467    // cyNetViewManager.getNetworkViews(network);
468    // for (CyNetworkView view : views) {
469    // view.updateView();
470    // }
471    // }
472  0 ignoreCySelection = false;
473    }
474   
 
475  0 toggle public void cytoscapeSelectionChanged(Map<Long, Boolean> selectedRows)
476    {
477    // if (ignoreCySelection || currentCyMap.size() == 0) {
478    // return;
479    // }
480    // // clearSelectionList();
481    // // System.out.println("cytoscape selection changed");
482    // // iterate over all cy objects with associated models
483    // for (CyIdentifiable cyObj : currentCyMap.keySet()) {
484    // if (cyObj instanceof CyNetwork ||
485    // !selectedRows.containsKey(cyObj.getSUID())) {
486    // continue;
487    // }
488    // for (ChimeraStructuralObject chimObj : currentCyMap.get(cyObj)) {
489    // if (selectedRows.get(cyObj.getSUID())) {
490    // addChimSelection(chimObj);
491    // if (chimObj instanceof ChimeraResidue) {
492    // if (chimObj.getChimeraModel().isSelected()) {
493    // removeChimSelection(chimObj.getChimeraModel());
494    // } else if (chimObj.getChimeraModel()
495    // .getChain(((ChimeraResidue) chimObj).getChainId()).isSelected()) {
496    // removeChimSelection(chimObj.getChimeraModel().getChain(
497    // ((ChimeraResidue) chimObj).getChainId()));
498    // }
499    // }
500    // } else {
501    // removeChimSelection(chimObj);
502    // if (chimObj.hasSelectedChildren() && chimObj instanceof ChimeraModel) {
503    // for (ChimeraResidue residue : ((ChimeraModel) chimObj)
504    // .getSelectedResidues()) {
505    // removeChimSelection(residue);
506    // }
507    // }
508    // }
509    // }
510    // }
511    // System.out.println("selection list: " + getChimSelectionCount());
512  0 updateChimeraSelection();
513  0 selectionChanged();
514    }
515   
516    // Save models in a HashMap/Set for better performance?
 
517  0 toggle public void updateChimeraSelection()
518    {
519    // System.out.println("update Chimera selection");
520  0 String selSpec = "";
521  0 for (int i = 0; i < chimSelectionList.size(); i++)
522    {
523  0 ChimeraStructuralObject nodeInfo = chimSelectionList.get(i);
524    // we do not care about the model anymore
525  0 selSpec = selSpec.concat(nodeInfo.toSpec());
526  0 if (i < chimSelectionList.size() - 1)
527    {
528  0 selSpec.concat("|");
529    }
530    }
531  0 if (selSpec.length() > 0)
532    {
533  0 chimeraManager.select("sel " + selSpec);
534    }
535    else
536    {
537  0 chimeraManager.select("~sel");
538    }
539    }
540   
541    /**
542    * This is called by the selectionListener to let us know that the user has
543    * changed their selection in Chimera. We need to go back to Chimera to find
544    * out what is currently selected and update our list.
545    */
 
546  0 toggle public void chimeraSelectionChanged()
547    {
548    // System.out.println("Chimera selection changed");
549  0 clearSelectionList();
550    // Execute the command to get the list of models with selections
551  0 Map<Integer, ChimeraModel> selectedModelsMap = chimeraManager
552    .getSelectedModels();
553    // Now get the residue-level data
554  0 chimeraManager.getSelectedResidues(selectedModelsMap);
555    // Get the selected objects
556  0 try
557    {
558  0 for (ChimeraModel selectedModel : selectedModelsMap.values())
559    {
560  0 int modelNumber = selectedModel.getModelNumber();
561  0 int subModelNumber = selectedModel.getSubModelNumber();
562    // Get the corresponding "real" model
563  0 if (chimeraManager.hasChimeraModel(modelNumber, subModelNumber))
564    {
565  0 ChimeraModel dataModel = chimeraManager.getChimeraModel(
566    modelNumber, subModelNumber);
567  0 if (dataModel.getResidueCount() == selectedModel
568    .getResidueCount()
569    || dataModel.getModelType() == StructureManager.ModelType.SMILES)
570    {
571    // Select the entire model
572  0 addChimSelection(dataModel);
573    // dataModel.setSelected(true);
574    }
575    else
576    {
577  0 for (ChimeraChain selectedChain : selectedModel.getChains())
578    {
579  0 ChimeraChain dataChain = dataModel.getChain(selectedChain
580    .getChainId());
581  0 if (selectedChain.getResidueCount() == dataChain
582    .getResidueCount())
583    {
584  0 addChimSelection(dataChain);
585    // dataChain.setSelected(true);
586    }
587    // else {
588    // Need to select individual residues
589  0 for (ChimeraResidue res : selectedChain.getResidues())
590    {
591  0 String residueIndex = res.getIndex();
592  0 ChimeraResidue residue = dataChain.getResidue(residueIndex);
593  0 if (residue == null)
594    {
595  0 continue;
596    }
597  0 addChimSelection(residue);
598    // residue.setSelected(true);
599    } // resIter.hasNext
600    // }
601    } // chainIter.hasNext()
602    }
603    }
604    } // modelIter.hasNext()
605    } catch (Exception ex)
606    {
607  0 logger.warn("Could not update selection", ex);
608    }
609    // System.out.println("selection list: " + getChimSelectionCount());
610    // Finally, update the navigator panel
611  0 selectionChanged();
612  0 updateCytoscapeSelection();
613    }
614   
 
615  0 toggle public void selectFunctResidues(Collection<ChimeraModel> models)
616    {
617  0 clearSelectionList();
618  0 for (ChimeraModel model : models)
619    {
620  0 for (ChimeraResidue residue : model.getFuncResidues())
621    {
622  0 addChimSelection(residue);
623    }
624    }
625  0 updateChimeraSelection();
626  0 updateCytoscapeSelection();
627  0 selectionChanged();
628    }
629   
630    // public void selectFunctResidues(CyNode node, CyNetwork network) {
631    // clearSelectionList();
632    // if (currentCyMap.containsKey(node)) {
633    // Set<ChimeraStructuralObject> chimObjects = currentCyMap.get(node);
634    // for (ChimeraStructuralObject obj : chimObjects) {
635    // if (obj instanceof ChimeraModel) {
636    // ChimeraModel model = (ChimeraModel) obj;
637    // for (ChimeraResidue residue : model.getFuncResidues()) {
638    // addChimSelection(residue);
639    // }
640    // }
641    // }
642    // }
643    // updateChimeraSelection();
644    // updateCytoscapeSelection();
645    // selectionChanged();
646    // }
647   
 
648  0 toggle public List<ChimeraStructuralObject> getChimSelectionList()
649    {
650  0 return chimSelectionList;
651    }
652   
 
653  0 toggle public int getChimSelectionCount()
654    {
655  0 return chimSelectionList.size();
656    }
657   
658    /**
659    * Add a selection to the selection list. This is called primarily by the
660    * Model Navigator Dialog to keep the selections in sync
661    *
662    * @param selectionToAdd
663    * the selection to add to our list
664    */
 
665  0 toggle public void addChimSelection(ChimeraStructuralObject selectionToAdd)
666    {
667  0 if (selectionToAdd != null
668    && !chimSelectionList.contains(selectionToAdd))
669    {
670  0 chimSelectionList.add(selectionToAdd);
671  0 selectionToAdd.setSelected(true);
672    }
673    }
674   
675    /**
676    * Remove a selection from the selection list. This is called primarily by the
677    * Model Navigator Dialog to keep the selections in sync
678    *
679    * @param selectionToRemove
680    * the selection to remove from our list
681    */
 
682  0 toggle public void removeChimSelection(ChimeraStructuralObject selectionToRemove)
683    {
684  0 if (selectionToRemove != null
685    && chimSelectionList.contains(selectionToRemove))
686    {
687  0 chimSelectionList.remove(selectionToRemove);
688  0 selectionToRemove.setSelected(false);
689    }
690    }
691   
692    /**
693    * Clear the list of selected objects
694    */
 
695  0 toggle public void clearSelectionList()
696    {
697  0 for (ChimeraStructuralObject cso : chimSelectionList)
698    {
699  0 if (cso != null)
700    {
701  0 cso.setSelected(false);
702    }
703    }
704  0 chimSelectionList.clear();
705    }
706   
707    /**
708    * Associate a new network with the corresponding Chimera objects.
709    *
710    * @param network
711    */
712   
713    /**
714    * Dump and refresh all of our model/chain/residue info
715    */
 
716  0 toggle public void updateModels()
717    {
718    // Stop all of our listeners while we try to handle this
719  0 chimeraManager.stopListening();
720   
721    // Get all of the open models
722  0 List<ChimeraModel> newModelList = chimeraManager.getModelList();
723   
724    // Match them up -- assume that the model #'s haven't changed
725  0 for (ChimeraModel newModel : newModelList)
726    {
727    // Get the color (for our navigator)
728  0 newModel.setModelColor(chimeraManager.getModelColor(newModel));
729   
730    // Get our model info
731  0 int modelNumber = newModel.getModelNumber();
732  0 int subModelNumber = newModel.getSubModelNumber();
733   
734    // If we already know about this model number, get the Structure,
735    // which tells us about the associated CyNode
736  0 if (chimeraManager.hasChimeraModel(modelNumber, subModelNumber))
737    {
738  0 ChimeraModel oldModel = chimeraManager.getChimeraModel(modelNumber,
739    subModelNumber);
740  0 chimeraManager.removeChimeraModel(modelNumber, subModelNumber);
741  0 newModel.setModelType(oldModel.getModelType());
742  0 if (oldModel.getModelType() == ModelType.SMILES)
743    {
744  0 newModel.setModelName(oldModel.getModelName());
745    }
746    // re-assign associations to cytoscape objects
747    // Map<CyIdentifiable, CyNetwork> oldModelCyObjs =
748    // oldModel.getCyObjects();
749    // for (CyIdentifiable cyObj : oldModelCyObjs.keySet()) {
750    // // add cy objects to the new model
751    // newModel.addCyObject(cyObj, oldModelCyObjs.get(cyObj));
752    // if (currentCyMap.containsKey(cyObj)) {
753    // currentCyMap.get(cyObj).add(newModel);
754    // if (currentCyMap.get(cyObj).contains(oldModel)) {
755    // currentCyMap.get(cyObj).remove(oldModel);
756    // }
757    // }
758    // }
759    // // add new model to the chimera objects map and remove old model
760    // if (currentChimMap.containsKey(oldModel)) {
761    // currentChimMap.put(newModel, currentChimMap.get(oldModel));
762    // currentChimMap.remove(oldModel);
763    // }
764    }
765    // add new model to ChimeraManager
766  0 chimeraManager.addChimeraModel(modelNumber, subModelNumber, newModel);
767   
768    // Get the residue information
769  0 if (newModel.getModelType() != ModelType.SMILES)
770    {
771  0 chimeraManager.addResidues(newModel);
772    }
773    // for (CyIdentifiable cyObj : newModel.getCyObjects().keySet()) {
774    // if (cyObj != null && cyObj instanceof CyNetwork) {
775    // addStructureNetwork((CyNetwork) cyObj);
776    // } else if (cyObj != null && cyObj instanceof CyNode) {
777    // newModel.setFuncResidues(ChimUtils.parseFuncRes(
778    // getResidueList(newModel.getCyObjects().get(cyObj), cyObj),
779    // newModel.getModelName()));
780    // }
781    // }
782    }
783   
784    // associate all models with any node or network
785    // aTask.associate();
786   
787    // Restart all of our listeners
788  0 chimeraManager.startListening();
789    // Done
790    }
791   
 
792  0 toggle public void launchModelNavigatorDialog()
793    {
794    // TODO: [Optional] Use haveGUI flag
795    // if (!haveGUI) {
796    // return;
797    // }
798    // if (mnDialog == null) {
799    // CySwingApplication cyApplication = (CySwingApplication)
800    // getService(CySwingApplication.class);
801    // mnDialog = new ModelNavigatorDialog(cyApplication.getJFrame(), this);
802    // mnDialog.pack();
803    // }
804    // mnDialog.setVisible(true);
805    }
806   
 
807  0 toggle public boolean isMNDialogOpen()
808    {
809    // if (mnDialog != null && mnDialog.isVisible()) {
810    // return true;
811    // }
812  0 return false;
813    }
814   
815    /**
816    * Invoked by the listener thread.
817    */
 
818  0 toggle public void modelChanged()
819    {
820    // if (mnDialog != null) {
821    // mnDialog.modelChanged();
822    // }
823    }
824   
825    /**
826    * Inform our interface that the selection has changed
827    */
 
828  0 toggle public void selectionChanged()
829    {
830    // if (mnDialog != null) {
831    // // System.out.println("update dialog selection");
832    // mnDialog.updateSelection(new
833    // ArrayList<ChimeraStructuralObject>(chimSelectionList));
834    // }
835    }
836   
 
837  0 toggle public void launchAlignDialog(boolean useChains)
838    {
839    // TODO: [Optional] Use haveGUI flag
840    // Sometimes it does not appear in Windows
841    // if (!haveGUI) {
842    // return;
843    // }
844    // if (alDialog != null) {
845    // alDialog.setVisible(false);
846    // alDialog.dispose();
847    // }
848    // System.out.println("launch align dialog");
849  0 List<ChimeraStructuralObject> chimObjectList = new ArrayList<>();
850  0 for (ChimeraModel model : chimeraManager.getChimeraModels())
851    {
852  0 if (useChains)
853    {
854  0 for (ChimeraChain chain : model.getChains())
855    {
856  0 chimObjectList.add(chain);
857    }
858    }
859    else
860    {
861  0 chimObjectList.add(model);
862    }
863    }
864    // Bring up the dialog
865    // CySwingApplication cyApplication = (CySwingApplication)
866    // getService(CySwingApplication.class);
867    // alDialog = new AlignStructuresDialog(cyApplication.getJFrame(), this,
868    // chimObjectList);
869    // alDialog.pack();
870    // alDialog.setVisible(true);
871    }
872   
 
873  0 toggle public List<String> getAllStructureKeys()
874    {
875  0 return Arrays.asList(defaultStructureKeys);
876    }
877   
 
878  0 toggle public List<String> getAllChemStructKeys()
879    {
880  0 return Arrays.asList(defaultChemStructKeys);
881    }
882   
 
883  0 toggle public List<String> getAllResidueKeys()
884    {
885  0 return Arrays.asList(defaultResidueKeys);
886    }
887   
 
888  0 toggle public List<String> getAllChimeraResidueAttributes()
889    {
890  0 List<String> attributes = new ArrayList<>();
891    // attributes.addAll(rinManager.getResAttrs());
892  0 attributes.addAll(chimeraManager.getAttrList());
893  0 return attributes;
894    }
895   
896    StructureSettings defaultSettings = null;
897   
898    // TODO: [Optional] Change priority of Chimera paths
 
899  1 toggle public static List<String> getChimeraPaths()
900    {
901  1 List<String> pathList = new ArrayList<>();
902   
903    // if no network is available and the settings have been modified by the
904    // user, check for a
905    // path to chimera
906    //
907    // For Jalview, Preferences/Cache plays this role instead
908    // if (defaultSettings != null)
909    // {
910    // String defaultPath = defaultSettings.getChimeraPath();
911    // if (defaultPath != null && !defaultPath.equals(""))
912    // {
913    // pathList.add(defaultPath);
914    // return pathList;
915    // }
916    // }
917   
918    /*
919    * Jalview addition: check if path set in user preferences.
920    */
921  1 String userPath = Cache.getDefault(Preferences.CHIMERA_PATH, null);
922  1 if (userPath != null)
923    {
924  0 pathList.add(0, userPath);
925    }
926   
927    // Add default installation paths
928  1 String os = System.getProperty("os.name");
929  1 if (os.startsWith("Linux"))
930    {
931  1 pathList.add("/usr/local/chimera/bin/chimera");
932  1 pathList.add("/usr/local/bin/chimera");
933  1 pathList.add("/usr/bin/chimera");
934    }
935  0 else if (os.startsWith("Windows"))
936    {
937  0 for (String root : new String[] { "\\Program Files",
938    "C:\\Program Files", "\\Program Files (x86)",
939    "C:\\Program Files (x86)" })
940    {
941  0 for (String version : new String[] { "1.11", "1.11.1", "1.11.2",
942    "1.12", "1.12.1", "1.12.2", "1.13" })
943    {
944  0 pathList.add(root + "\\Chimera " + version + "\\bin\\chimera");
945  0 pathList.add(
946    root + "\\Chimera " + version + "\\bin\\chimera.exe");
947    }
948    }
949    }
950  0 else if (os.startsWith("Mac"))
951    {
952  0 pathList.add("/Applications/Chimera.app/Contents/MacOS/chimera");
953    }
954  1 return pathList;
955    }
956   
 
957  0 toggle public void setChimeraPathProperty(String path)
958    {
959    // CytoUtils.setDefaultChimeraPath(registrar, chimeraPropertyName,
960    // chimeraPathPropertyKey,
961    // path);
962    }
963   
 
964  0 toggle public void setStructureSettings(StructureSettings structureSettings)
965    {
966  0 this.defaultSettings = structureSettings;
967    }
968   
 
969  0 toggle public String getCurrentChimeraPath(Object object)
970    {
971  0 if (defaultSettings != null)
972    {
973  0 return defaultSettings.getChimeraPath();
974    }
975    else
976    {
977  0 return "";
978    }
979    }
980   
981    // public void initChimTable() {
982    // CyTableManager manager = (CyTableManager) getService(CyTableManager.class);
983    // CyTableFactory factory = (CyTableFactory) getService(CyTableFactory.class);
984    // for (CyTable table : manager.getGlobalTables()) {
985    // if (table.getTitle().equals(chimeraOutputTable)) {
986    // manager.deleteTable(table.getSUID());
987    // }
988    // }
989    // chimTable = factory.createTable(chimeraOutputTable, chimeraCommandAttr,
990    // String.class,
991    // false, true);
992    // manager.addTable(chimTable);
993    // if (chimTable.getColumn(chimeraOutputAttr) == null) {
994    // chimTable.createListColumn(chimeraOutputAttr, String.class, false);
995    // }
996    // }
997   
998    // public void addChimReply(String command, List<String> reply) {
999    // chimTable.getRow(command).set(chimeraOutputAttr, reply);
1000    // }
1001   
1002    }