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