From 9c7d465159eba89ba31976169e6030b3615f6955 Mon Sep 17 00:00:00 2001 From: Lea Buchweitz Date: Thu, 15 Aug 2019 21:25:49 +0200 Subject: [PATCH] Support for a new dynamic visualization. --- .../simulator/fba/CSVDataConverterTest.java | 3 - .../sbml/simulator/fba/ConstraintsTest.java | 3 - .../fba/FluxBalanceAnalysisTest.java | 3 - .../simulator/fba/FluxMinimizationTest.java | 3 - .../fba/FluxMinimizationUtilsTest.java | 3 - .../fba/dynamic/DynamicFBAFluxMinIITest.java | 7 +- .../simulator/fba/dynamic/DynamicFBATest.java | 9 +- .../sbml/simulator/gui/graph/DynamicGraph.xml | 24 + .../simulator/gui/graph/DynamicGraph_de.xml | 25 + .../simulator/gui/graph/GPL_CONCENTRATION.png | Bin 0 -> 472 bytes .../sbml/simulator/gui/html/package-info.java | 3 - .../sbml/simulator/gui/img/package-info.java | 3 - .../sbml/simulator/locales/package-info.java | 3 - .../optimization/EstimationInitOperator.java | 3 - src/org/sbml/optimization/EvA2GUIStarter.java | 3 - src/org/sbml/optimization/QuantityRange.java | 3 - src/org/sbml/optimization/package-info.java | 3 - .../problem/EstimationOptions.java | 3 - .../problem/EstimationProblem.java | 3 - .../optimization/problem/package-info.java | 3 - .../sbml/simulator/CommandLineManager.java | 3 - .../sbml/simulator/QualityMeasurement.java | 3 - src/org/sbml/simulator/SBMLsimulator.java | 6 +- .../simulator/SimulationConfiguration.java | 3 - src/org/sbml/simulator/SimulationManager.java | 3 - src/org/sbml/simulator/SimulationOptions.java | 3 - .../fba/controller/CSVDataConverter.java | 708 +++++---- .../fba/controller/CSVDataReader.java | 3 - .../fba/controller/CalculateNullSpace.java | 3 - .../simulator/fba/controller/Constraints.java | 453 +++--- .../fba/controller/FluxBalanceAnalysis.java | 3 - .../fba/controller/FluxMinimization.java | 5 +- .../fba/controller/FluxMinimizationUtils.java | 3 - .../fba/controller/TargetFunction.java | 3 - .../fba/controller/package-info.java | 3 - .../simulator/fba/dynamic/DynamicFBA.java | 3 - .../fba/dynamic/FluxMinimization.java | 3 - .../fba/dynamic/FluxMinimizationII.java | 5 - .../fba/dynamic/FluxMinimizationIIa.java | 4 - .../simulator/fba/dynamic/TargetFunction.java | 3 - .../simulator/fba/dynamic/package-info.java | 3 - .../sbml/simulator/fba/gui/ChartPanel.java | 3 - .../fba/gui/FBAButtonPressedDialog.java | 376 +++-- .../sbml/simulator/fba/gui/FBAOptions.java | 304 ++-- src/org/sbml/simulator/fba/gui/FBAPanel.java | 937 ++++++----- .../simulator/fba/gui/FBASettingPanel.java | 823 +++++----- src/org/sbml/simulator/fba/gui/VODPanel.java | 10 +- .../sbml/simulator/fba/gui/package-info.java | 3 - .../simulator/gui/InteractiveScanPanel.java | 3 - src/org/sbml/simulator/gui/LegendPanel.java | 4 - .../simulator/gui/QuantitySelectionPanel.java | 6 - .../sbml/simulator/gui/SimulationPanel.java | 46 +- .../simulator/gui/SimulationToolPanel.java | 7 +- .../gui/SimulationVisualizationPanel.java | 20 +- .../sbml/simulator/gui/SimulationWorker.java | 3 - src/org/sbml/simulator/gui/SimulatorUI.java | 42 +- .../gui/graph/AGraphManipulator.java | 1123 ++++++------- .../simulator/gui/graph/ButtonPressed.java | 53 + .../gui/graph/CameraAnimationView.java | 396 +++++ .../gui/graph/ConcentrationGraphUI.java | 136 ++ .../gui/graph/DynamicControlPanel.java | 1126 ++++++------- .../gui/graph/DynamicController.java | 361 ++++- .../sbml/simulator/gui/graph/DynamicCore.java | 1386 ++++++++++------- .../sbml/simulator/gui/graph/DynamicView.java | 16 +- .../simulator/gui/graph/GraphOptions.java | 450 +++--- .../simulator/gui/graph/IDynamicGraph.java | 45 +- .../gui/graph/IGraphManipulator.java | 74 +- .../simulator/gui/graph/ImageGenerator.java | 418 ++--- .../gui/graph/ManipulatorOfFillLevel.java | 229 +++ .../gui/graph/ManipulatorOfNodeColor.java | 409 +++-- .../graph/ManipulatorOfNodeColorAndSize.java | 85 +- .../gui/graph/ManipulatorOfNodeSize.java | 64 +- .../graph/ManipulatorOfNodeSizeAndColor.java | 382 +++-- .../simulator/gui/graph/RearrangeCycles.java | 382 +++++ .../gui/graph/TestCycleArranging.java | 155 ++ .../simulator/gui/graph/package-info.java | 3 - src/org/sbml/simulator/gui/package-info.java | 3 - .../plot/BoxAndWhiskerXYToolTipGenerator.java | 3 - .../simulator/gui/plot/BoxPlotDataset.java | 5 - .../sbml/simulator/gui/plot/MetaDataset.java | 3 - src/org/sbml/simulator/gui/plot/Plot.java | 3 - .../sbml/simulator/gui/plot/PlotOptions.java | 3 - .../sbml/simulator/gui/plot/SeriesInfo.java | 3 - .../gui/plot/XYBoxAndWhiskerRenderer.java | 3 - .../simulator/gui/plot/XYDatasetAdapter.java | 3 - .../sbml/simulator/gui/plot/package-info.java | 3 - .../gui/table/LegendTableCellRenderer.java | 3 - .../simulator/gui/table/LegendTableModel.java | 3 - .../simulator/gui/table/package-info.java | 3 - .../sbml/simulator/io/CSVDataImporter.java | 3 - src/org/sbml/simulator/io/CSVReadingTask.java | 3 - .../sbml/simulator/io/SimulatorIOOptions.java | 3 - src/org/sbml/simulator/io/package-info.java | 3 - .../simulator/math/SplineCalculation.java | 3 - src/org/sbml/simulator/math/package-info.java | 3 - src/org/sbml/simulator/package-info.java | 3 - .../simulator/stability/gui/package-info.java | 3 - .../stability/math/IdentityMatrix.java | 103 +- .../stability/math/StabilityMatrix.java | 795 +++++----- .../stability/math/StoichiometricMatrix.java | 897 ++++++----- .../stability/math/package-info.java | 3 - .../simulator/gui/CSVDataImporterTest.java | 3 - .../sbml/simulator/gui/ChoiceFormatTest.java | 3 - test/org/sbml/simulator/gui/ToolPanel.java | 3 - .../simulator/gui/XYDataSetCollection.java | 3 - .../simulator/gui/graph/BugTestJSlider.java | 4 - .../sbml/simulator/gui/graph/Controller.java | 3 - .../sbml/simulator/gui/graph/JSliderTest.java | 3 - .../org/sbml/simulator/gui/graph/RunTest.java | 3 - test/org/sbml/simulator/math/Plotter.java | 5 +- .../simulator/math/SimulationModeTest.java | 3 - .../sbml/simulator/math/SimulationTest.java | 5 +- .../math/SimulationTestAutomatic.java | 3 - .../simulator/math/UnitDerivitionTest.java | 3 - 114 files changed, 7521 insertions(+), 5602 deletions(-) create mode 100644 resources/org/sbml/simulator/gui/graph/GPL_CONCENTRATION.png create mode 100644 src/org/sbml/simulator/gui/graph/ButtonPressed.java create mode 100644 src/org/sbml/simulator/gui/graph/CameraAnimationView.java create mode 100644 src/org/sbml/simulator/gui/graph/ConcentrationGraphUI.java create mode 100644 src/org/sbml/simulator/gui/graph/ManipulatorOfFillLevel.java create mode 100644 src/org/sbml/simulator/gui/graph/RearrangeCycles.java create mode 100644 src/org/sbml/simulator/gui/graph/TestCycleArranging.java diff --git a/examples/org/sbml/simulator/fba/CSVDataConverterTest.java b/examples/org/sbml/simulator/fba/CSVDataConverterTest.java index cbd2117..ec7036c 100644 --- a/examples/org/sbml/simulator/fba/CSVDataConverterTest.java +++ b/examples/org/sbml/simulator/fba/CSVDataConverterTest.java @@ -1,6 +1,4 @@ /* - * $Id: ContraintsUtilsTest.java 18:43:52 Meike Aichele$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -25,7 +23,6 @@ /** * @author Meike Aichele - * @version $Rev$ * @date 13.06.2012 * @since 1.0 */ diff --git a/examples/org/sbml/simulator/fba/ConstraintsTest.java b/examples/org/sbml/simulator/fba/ConstraintsTest.java index a8bcd7f..ee5b85a 100644 --- a/examples/org/sbml/simulator/fba/ConstraintsTest.java +++ b/examples/org/sbml/simulator/fba/ConstraintsTest.java @@ -1,6 +1,4 @@ /* - * $Id: ConstraintsTest.java 19:03:59 Meike Aichele$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -27,7 +25,6 @@ /** * @author Meike Aichele - * @version $Rev$ * @date 13.06.2012 * @since 1.0 */ diff --git a/examples/org/sbml/simulator/fba/FluxBalanceAnalysisTest.java b/examples/org/sbml/simulator/fba/FluxBalanceAnalysisTest.java index fb4e780..d1b166e 100644 --- a/examples/org/sbml/simulator/fba/FluxBalanceAnalysisTest.java +++ b/examples/org/sbml/simulator/fba/FluxBalanceAnalysisTest.java @@ -1,6 +1,4 @@ /* - * $Id: FluxBalanceAnalysisTest.java 19:04:44 Meike Aichele$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -39,7 +37,6 @@ /** * @author Meike Aichele - * @version $Rev$ * @date 17.06.2012 * @since 1.0 */ diff --git a/examples/org/sbml/simulator/fba/FluxMinimizationTest.java b/examples/org/sbml/simulator/fba/FluxMinimizationTest.java index c450efa..b773b4e 100644 --- a/examples/org/sbml/simulator/fba/FluxMinimizationTest.java +++ b/examples/org/sbml/simulator/fba/FluxMinimizationTest.java @@ -1,6 +1,4 @@ /* - * $Id: FluxMinimizationTest.java 12:30:10 Meike Aichele$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -29,7 +27,6 @@ /** * @author Meike Aichele - * @version $Rev$ * @date 09.06.2012 * @since 1.0 */ diff --git a/examples/org/sbml/simulator/fba/FluxMinimizationUtilsTest.java b/examples/org/sbml/simulator/fba/FluxMinimizationUtilsTest.java index 1b488ed..28af9b6 100644 --- a/examples/org/sbml/simulator/fba/FluxMinimizationUtilsTest.java +++ b/examples/org/sbml/simulator/fba/FluxMinimizationUtilsTest.java @@ -1,6 +1,4 @@ /* - * $Id: FluxMinimizationUtilsTest.java 17:35:33 Meike Aichele$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -27,7 +25,6 @@ /** * @author Meike Aichele - * @version $Rev$ * @date 13.06.2012 * @since 1.0 */ diff --git a/examples/org/sbml/simulator/fba/dynamic/DynamicFBAFluxMinIITest.java b/examples/org/sbml/simulator/fba/dynamic/DynamicFBAFluxMinIITest.java index 9e8a738..80ca161 100644 --- a/examples/org/sbml/simulator/fba/dynamic/DynamicFBAFluxMinIITest.java +++ b/examples/org/sbml/simulator/fba/dynamic/DynamicFBAFluxMinIITest.java @@ -1,6 +1,4 @@ /* - * $$Id${file_name} ${time} ${user}$$ - * $$URL${file_name} $$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -35,8 +33,9 @@ import de.zbit.io.csv.CSVWriter; /** - * @author Stephanie Tscherneck, Robin Fähnrich, Roland Keller - * @version $Rev$ + * @author Stephanie Tscherneck + * @author Robin Fähnrich + * @author Roland Keller * @since 1.0 * ${tags} */ diff --git a/examples/org/sbml/simulator/fba/dynamic/DynamicFBATest.java b/examples/org/sbml/simulator/fba/dynamic/DynamicFBATest.java index 7771705..c3a4389 100644 --- a/examples/org/sbml/simulator/fba/dynamic/DynamicFBATest.java +++ b/examples/org/sbml/simulator/fba/dynamic/DynamicFBATest.java @@ -1,10 +1,6 @@ /* - * $Id$URL: - * https://rarepos.cs.uni-tuebingen - * .de/svn-path/SBMLsimulator/trunk/examples/org/ - * sbml/simulator/fba/dynamic/DynamicFBATest.java $ - * --------------------------------------------------------------------- This - * file is part of SBMLsimulator, a Java-based simulator for models of + * --------------------------------------------------------------------- + * This file is part of SBMLsimulator, a Java-based simulator for models of * biochemical processes encoded in the modeling language SBML. * * Copyright (C) 2007-2016 by the University of Tuebingen, Germany. @@ -33,7 +29,6 @@ * Test a dynamic flux balance analysis. * * @author Robin Fähnrich - * @version $Rev$ * @since 1.0 */ public class DynamicFBATest { diff --git a/resources/org/sbml/simulator/gui/graph/DynamicGraph.xml b/resources/org/sbml/simulator/gui/graph/DynamicGraph.xml index 69867fa..c283153 100644 --- a/resources/org/sbml/simulator/gui/graph/DynamicGraph.xml +++ b/resources/org/sbml/simulator/gui/graph/DynamicGraph.xml @@ -21,10 +21,14 @@ Save the dynamic visualization as a video. Resolution can be adjusted with resolution multiplier in options and the resulting speed of the video itself will be approximately the same as the chosen simulation speed. Image Take a screenshot of the whole graph. Resolution can be adjusted with resolution multiplier in options. + Graph of metabolic concentration + Shows a graph with all metabolic concentrations over time and the current one. Nodelabels Switch for node labels. Reactionlabels Switch for reaction labels. + Loopsimulation + Simulation restarts over and over again Fast Normal Slow @@ -36,12 +40,19 @@ Node color Abs.size/rel.color Rel.size/abs.color + Rel.Filling level/abs.color Visualization Chose visualization style and data for the dynamic visualization. Choose time point of visualization. Generate video with {0}x{1} pixel. Picture sucessfully saved. + + + Concentration + Time + Concentration + Videofiles (*.mov, *.avi, *.mp4, *.mpg, *.wmv, *.flv) @@ -79,6 +90,8 @@ Enable/Disable uniform node colors instead of node colors given in legend. Color for uniform node color Sets the color for uniform node color. + Choose concentration colors + Choose colors of the concentrations on your own Dynamic change of node size Options for the dynamic change of node size. Dynamic change of node color @@ -132,5 +145,16 @@ By enabling this option you can force to use the resolution multiplier even if the video output resolution would be big enough. Picture whole graph Choose if the whole graph should be pictured in videos and screenshots or just the current display window. + Camera animation + Add file for camera animation + Camera animation + Shows the added camera animation in chosen speed, if play or video is pressed + Without + No camera animation is shown + + + File with reactionglyphs + File with speciesglyphs + Radius of circle diff --git a/resources/org/sbml/simulator/gui/graph/DynamicGraph_de.xml b/resources/org/sbml/simulator/gui/graph/DynamicGraph_de.xml index fde669a..8f4dda3 100644 --- a/resources/org/sbml/simulator/gui/graph/DynamicGraph_de.xml +++ b/resources/org/sbml/simulator/gui/graph/DynamicGraph_de.xml @@ -21,10 +21,14 @@ Speichert die dynamische Visualisierung als Video. Die Auflösung kann über den Auflösungsmultiplikator in den Optionen angepasst werden und die Videogeschwindigkeit ist annähernd dieselbe, wie die eingestellte Simulationsgeschwindigkeit. Bild Speichert das aktuelle Netzwerk als Bilddatei. Die Auflösung kann über den Auflösungsmultiplikator in den Optionen angepasst werden. + Graph der metabolischen Konzentrationen + Zeigt einen Graph mit allen metabolischen Konzentrationen insgesamt und zum aktuellen Zeitpunkt Knotenbeschriftung Blendet die Konzentrationen ein/aus. Reaktionenbeschriftung Blendet die Reaktionsgeschwindigkeiten ein/aus. + Loopsimulation + Simulation wird immer wieder von vorne gestartet Schnell Normal Langsam @@ -36,12 +40,19 @@ Knotenfarbe Abs.Größe/rel.Farbe Rel.Größe/abs.Farbe + Rel.Füllstände/abs.Farbe Visualisierung Wählen Sie die Art der dynamischen Visualisierung und die zu visualisierenden Daten aus. Stellen Sie den Zeitpunkt der Visualisierung ein. Erzeuge Video mit {0}x{1} Pixel. Bild erfolgreich gespeichert. + + + Konzentrationsübersicht + Zeit + Konzentrationen + Videodateien (*.mov, *.avi, *.mp4, *.mpg, *.wmv, *.flv) @@ -77,6 +88,8 @@ Bei dynamischer Änderung der Knotengröße, definiert dies die maximale Knotengröße. Einheitliche Knotenfarbe Einheitliche Knotenfarbe, anstatt den Farben in der Legende. + Konzentrationsfarben selbst wählen + Alle Farben für die Konzentrationen selbst wählen Knotenfarbe Farbeinstellung für die einheitliche Knotenfarbe. Dynamische Änderung der Knotengröße @@ -132,5 +145,17 @@ Mit dieser Option kann der Auflösungsmultiplikator erzwungen werden auch wenn die Videoauflösung groß genug wäre. Komplettes Netzwerk abbilden Wählen Sie, ob das komplette Netzwerk auf Bildern und Videos dargestellt werden soll oder nur die aktuelle Ansicht. + Kameraanimation + Füge Datei für Kameraanimation hinzu + Kameraanimation + Zeigt die geladene Kameraanimation bei Simulationsstart in gewählter Geschwindigkeit + Ohne + Es wird keine Kameraanimation gezeigt + + + + Datei mit Reaktionsknoten + Datei mit Metaboliten + Radius des Kreises diff --git a/resources/org/sbml/simulator/gui/graph/GPL_CONCENTRATION.png b/resources/org/sbml/simulator/gui/graph/GPL_CONCENTRATION.png new file mode 100644 index 0000000000000000000000000000000000000000..9fe659da1490d1f8eb965bdef7454ece3c7c764c GIT binary patch literal 472 zcmeAS@N?(olHy`uVBq!ia0vp^LO?9Y!OXzGIHB1l7RX^N4sv&5Sa(k5C6L3C?&#~t zz_78O`%fY(klz^K6XFV_2NvXt>ZSr+pj8s&7tFxI!6P7}pkiU`;NlSw5|NNm(9qP} zKY9A>`72g$*uDSo>GQYmKmYvo`|qB}n^%FlI14-?iy0XB4ude`@%$AjK*3d>E{-7* z;l2|(g$^kQIEyb0`?zXR#ck)cx&Qt%-wi0K3Ep(lsnJpC_(F}HeA>b49T$)Jn>?Mn zp#Bo?j1>Q3(Fdw0Bow!$rs`kf(cGjJ;Ur_U@04zDg@0*D z=6+7;Qn{b=~H8 p8?X5sE3W create a button for that - /** - * Writes the computed values of the flux balance analysis in the given csv-File, which has 2 columns and for every reaction/ species a line. - * The first line contains the heading "Reaction_id" or "Species_id" (first column) and "steady_state_value" (second column). - * @param computed_solution - * @param file - * @throws Exception - */ - public void writeComputedValuesInCSV(double[] computed_solution, File file) throws Exception { - modifiedDocument = FluxMinimizationUtils.getExpandedDocument(modifiedDocument); - CSVWriter writer = new CSVWriter(); - String[][] data = null; - Boolean isFluxOrErrorSolution = null; - Boolean isConcSolution = null; - if (computed_solution.length == modifiedDocument.getModel().getReactionCount()) { - data = new String[modifiedDocument.getModel().getReactionCount()+1][2]; - data[0][0] = "Reaction_id"; - isFluxOrErrorSolution = true; - } else if (computed_solution.length == modifiedDocument.getModel().getSpeciesCount()) { - data = new String[modifiedDocument.getModel().getSpeciesCount()+1][2]; - data[0][0] = "Species_id"; - isConcSolution = true; - } - if (isConcSolution == null && isFluxOrErrorSolution == null) { - // then the array has the wrong length - throw new IllegalArgumentException("Solution is neither corressponding to the reactions in this model nor to " + - "the species."); - } - data[0][1] = "steady_state_value"; - if (isFluxOrErrorSolution != null && isFluxOrErrorSolution) { - // write the reactions ids - for (int j = 1; j < modifiedDocument.getModel().getReactionCount(); j++) { - data[j][0] = modifiedDocument.getModel().getReaction(j).getId(); - data[j][1] = Double.toString(computed_solution[j]); - } - } else if (isConcSolution != null && isConcSolution) { - // write the species ids - for (int i = 1; i < modifiedDocument.getModel().getSpeciesCount(); i++) { - data[i][0] = modifiedDocument.getModel().getSpecies(i).getId(); - data[i][1] = Double.toString(computed_solution[i]); - } - } - // write the solution - writer.write(data, file); - } - -// /** -// * Writes the incoming data from the CSV-file in an array. When it was a Gibbs data file -// * the data will be written in the {@link# gibbsArray} else it was a concentration data file -// * and the data will be written in the {@link# concentrationsArray}. -// * @param obj -// * @throws Exception -// */ -// public void writeDataInArray(Object obj) throws Exception { -// if (obj instanceof String[][]) { -// String[][] data = (String[][]) obj; -// String[] values = new String[data.length]; -// String[] keys = new String[data.length]; -// int fileMatchToDocument = 0; -// // values are in the second column and keys in the first column -// for(int i = 0; i < data.length; i++) { -// values[i] = data[i][1]; -// keys[i] = data[i][0]; -// } -// -// if (isGibbsFile != null && isGibbsFile) { -// -// } else if(isConcentrationFile != null && isConcentrationFile) { -// initializeConcentrationArray(); -// for(int i = 0; i < values.length; i++) { -// if (modifiedDocument.getModel().containsSpecies(keys[i])) { -// modifiedDocument.getModel().getSpecies(keys[i]).putUserObject(KEY_CONCENTRATIONS, values[i]); -// int index = modifiedDocument.getModel().getListOfSpecies().getIndex(modifiedDocument.getModel().getSpecies(keys[i])); -// concentrationsArray[index] = Double.parseDouble(values[i]); -// fileMatchToDocument++; -// } -// } -// } -//// else if (isSystemBoundariesFile != null && isSystemBoundariesFile) {} -// if (fileMatchToDocument == 0) { -// throw new Exception("given file does not match with opened SBMLDocument"); -// } -// } -// } - - public double[] readGibbs(String file) throws IOException { - initializeGibbsArray(); - - String line; - - BufferedReader input = new BufferedReader(new FileReader(file)); - boolean header = true; - while ((line = input.readLine()) != null) { - if (!header) { - String[] helper = line.split("\t"); - if (modifiedDocument.getModel().containsReaction(helper[0])) { - if (!FluxMinimizationUtils.eliminatedReactions.contains(helper[0])) { - modifiedDocument.getModel().getReaction(helper[0]).putUserObject(KEY_GIBBS, Double.parseDouble(helper[1])); - int index = modifiedDocument.getModel().getListOfReactions().getIndex(modifiedDocument.getModel().getReaction(helper[0])); - gibbsArray[index] = Double.parseDouble(helper[1]); - if (modifiedDocument.getModel().containsReaction(helper[0] + FluxMinimizationUtils.endingForBackwardReaction)) { -// modifiedDocument.getModel().getReaction(helper[0] + FluxMinimizationUtils.endingForBackwardReaction).putUserObject(KEY_GIBBS, "isReverse"); - modifiedDocument.getModel().getReaction(helper[0] + FluxMinimizationUtils.endingForBackwardReaction).putUserObject(KEY_GIBBS, -Double.parseDouble(helper[1])); - int index2 = modifiedDocument.getModel().getListOfReactions().getIndex(modifiedDocument.getModel().getReaction(helper[0] + FluxMinimizationUtils.endingForBackwardReaction)); - gibbsArray[index2] = -Double.parseDouble(helper[1]); - } - } - } - else { - System.out.println(helper[0] + " unknown reaction"); - } - } - else { - header = false; - } - } - return gibbsArray; - } - - public double[] readSystemBoundaries(String file) throws IOException { - initializeSystemBoundariesArray(); - - String line; - - BufferedReader input = new BufferedReader(new FileReader(file)); - boolean header = true; - while ((line = input.readLine()) != null) { - if (!header) { - String[] helper = line.split("\t"); - - if (modifiedDocument.getModel().containsSpecies(helper[0])) { - int index = modifiedDocument.getModel().getListOfSpecies().getIndex(modifiedDocument.getModel().getSpecies(helper[0])); - if (helper[1].equals("-")) { - systemBoundariesArray[index] = -1; - } - else if (helper[1].equals("+")) { - systemBoundariesArray[index] = +1; - } - else if (helper[1].equals("=")) { - systemBoundariesArray[index] = 0; - } - else { - System.out.println(helper[0] + " unknown sign"); - } - } - else { - System.out.println(helper[0] + " unknown species"); - } - - } - else { - header = false; - } - } - return systemBoundariesArray; - } + /** + * key string for concentration values + */ + public static final String KEY_CONCENTRATIONS = "concentration"; + + /** + * key string for Gibbs values + */ + public static final String KEY_GIBBS = "gibbs"; + + /** + * Containing the read concentrations. + */ + private double[] concentrationsArray; + + /** + * Containing the read Gibbs energies. + */ + private double[] gibbsArray; + + /** + * true if a concentration file is given + */ + private Boolean isConcentrationFile; + + /** + * true if a gibbs file is given + */ + private Boolean isGibbsFile; + + /** + * true if a system boundaries file is given + */ + private Boolean isSystemBoundariesFile; + + /** + * Containing the corresponding {@link SBMLDocument}. + */ + private SBMLDocument modifiedDocument; + + /** + * Containing the reader to read the csv files + */ + private CSVDataReader reader; + + /** + * Containing the species indices of species at the system boundaries + */ + private double[] systemBoundariesArray; + + /** + * Call this constructor if no system boundaries file is given, + * for the automated creation of the system boundaries. + * @param originalDoc + * @throws Exception + */ + public CSVDataConverter(SBMLDocument originalDoc) throws Exception { + this.modifiedDocument = FluxMinimizationUtils.getExpandedDocument(originalDoc); + this.systemBoundariesArray = FluxMinimizationUtils.getSystemBoundaries(originalDoc); + } + + /** + * Call this constructor for the creation of a the systems boundaries array. + * @param originalDoc + * @param systemBoundariesFile + */ + public CSVDataConverter(SBMLDocument originalDoc, boolean systemBoundariesFile) { + this.modifiedDocument = FluxMinimizationUtils.eliminateTransportsAndSplitReversibleReactions(originalDoc); + } + + /** + * Call this constructor for the creation of the gibbs and the concentration array. + * @param originalDoc + * @param systemBoundaries + * @throws Exception + */ + public CSVDataConverter(SBMLDocument originalDoc, double[] systemBoundaries) throws Exception { + this.modifiedDocument = FluxMinimizationUtils.getExpandedDocument(originalDoc, systemBoundaries); + } + + /** + * @return the concentrationsArray + */ + public double[] getConcentrationsArray() { + return concentrationsArray; + } + + /** + * @return the gibbsArray + */ + public double[] getGibbsArray() { + return gibbsArray; + } + + /** + * + * @return the csv-Reader + */ + public CSVDataReader getReader() { + return reader; + } + + /** + * + * @return the systemBoundariesArray + */ + public double[] getSystemBoundariesArray() { + return systemBoundariesArray; + } + + /** + * Initializes the Concentration-array, so that every cell is filled with 10^(-11), + * because that is the normal minimal amount in nature, and when there is + * read a file with concentrations, the content will be overwritten. + */ + private void initializeConcentrationArray() { + concentrationsArray = new double[modifiedDocument.getModel().getSpeciesCount()]; + for (int i = 0; i < concentrationsArray.length; i++) { + concentrationsArray[i] = Math.pow(10, -11); + } + } + + /** + * Initializes the Gibbs-array, so that every cell is filled with NaN and when there is + * read a file with Gibbs energies, the content will be overwritten. + */ + private void initializeGibbsArray() { + gibbsArray = new double[modifiedDocument.getModel().getReactionCount()]; + for (int i = 0; i < gibbsArray.length; i++) { + gibbsArray[i] = Double.NaN; + } + } + + private void initializeSystemBoundariesArray() { + systemBoundariesArray = new double[modifiedDocument.getModel().getSpeciesCount()]; + for (int i =0; i < systemBoundariesArray.length; i++) { + systemBoundariesArray[i] = Double.NaN; + } + } + + /** + * Method to read equilibrium concentrations from a file. + * + * @param file + * @return concentrationsArray + * @throws Exception + */ + public double[] readConcentrationsFromFile (File file) throws Exception { + this.isConcentrationFile = true; + this.isGibbsFile = null; + this.isSystemBoundariesFile = null; + readFromFile(file); + return concentrationsArray; + } + + /** + * Reads out the Gibbs energies or concentrations from a given file and writes it in an array, that the method returns. + * + * @param file + * @throws Exception + */ + private void readFromFile(File file) throws Exception { + reader = new CSVDataReader(file,null); + reader.addPropertyChangeListener(EventHandler.create(PropertyChangeListener.class, this, "writeDataInArray", "newValue")); + reader.cancel(true); + } + + /** + * Reads out the Gibbs energies from a given file and writes it in the array gibbsEnergies + * + * @param file + * @return gibbsArray + * @throws Exception + */ + public double[] readGibbsFromFile(File file) throws Exception { + this.isGibbsFile = true; + this.isConcentrationFile = null; + this.isSystemBoundariesFile = null; + readFromFile(file); + return gibbsArray; + } + + /** + * + * @param file + * @return + * @throws Exception + */ + public double[] readSystemBoundariesFromFile(File file) throws Exception { + this.isSystemBoundariesFile = true; + this.isGibbsFile = null; + this.isConcentrationFile = null; + readFromFile(file); + return systemBoundariesArray; + } + + //TODO: call this method in the gui --> create a button for that + /** + * Writes the computed values of the flux balance analysis in the given csv-File, which has 2 columns and for every reaction/ species a line. + * The first line contains the heading "Reaction_id" or "Species_id" (first column) and "steady_state_value" (second column). + * @param computed_solution + * @param file + * @throws Exception + */ + public void writeComputedValuesInCSV(double[] computed_solution, File file) throws Exception { + modifiedDocument = FluxMinimizationUtils.getExpandedDocument(modifiedDocument); + CSVWriter writer = new CSVWriter(); + String[][] data = null; + Boolean isFluxOrErrorSolution = null; + Boolean isConcSolution = null; + if (computed_solution.length == modifiedDocument.getModel().getReactionCount()) { + data = new String[modifiedDocument.getModel().getReactionCount()+1][2]; + data[0][0] = "Reaction_id"; + isFluxOrErrorSolution = true; + } else if (computed_solution.length == modifiedDocument.getModel().getSpeciesCount()) { + data = new String[modifiedDocument.getModel().getSpeciesCount()+1][2]; + data[0][0] = "Species_id"; + isConcSolution = true; + } + if (isConcSolution == null && isFluxOrErrorSolution == null) { + // then the array has the wrong length + throw new IllegalArgumentException("Solution is neither corressponding to the reactions in this model nor to " + + "the species."); + } + data[0][1] = "steady_state_value"; + if (isFluxOrErrorSolution != null && isFluxOrErrorSolution) { + // write the reactions ids + for (int j = 1; j < modifiedDocument.getModel().getReactionCount(); j++) { + data[j][0] = modifiedDocument.getModel().getReaction(j).getId(); + data[j][1] = Double.toString(computed_solution[j]); + } + } else if (isConcSolution != null && isConcSolution) { + // write the species ids + for (int i = 1; i < modifiedDocument.getModel().getSpeciesCount(); i++) { + data[i][0] = modifiedDocument.getModel().getSpecies(i).getId(); + data[i][1] = Double.toString(computed_solution[i]); + } + } + // write the solution + writer.write(data, file); + } + + // /** + // * Writes the incoming data from the CSV-file in an array. When it was a Gibbs data file + // * the data will be written in the {@link# gibbsArray} else it was a concentration data file + // * and the data will be written in the {@link# concentrationsArray}. + // * @param obj + // * @throws Exception + // */ + // public void writeDataInArray(Object obj) throws Exception { + // if (obj instanceof String[][]) { + // String[][] data = (String[][]) obj; + // String[] values = new String[data.length]; + // String[] keys = new String[data.length]; + // int fileMatchToDocument = 0; + // // values are in the second column and keys in the first column + // for(int i = 0; i < data.length; i++) { + // values[i] = data[i][1]; + // keys[i] = data[i][0]; + // } + // + // if (isGibbsFile != null && isGibbsFile) { + // + // } else if(isConcentrationFile != null && isConcentrationFile) { + // initializeConcentrationArray(); + // for(int i = 0; i < values.length; i++) { + // if (modifiedDocument.getModel().containsSpecies(keys[i])) { + // modifiedDocument.getModel().getSpecies(keys[i]).putUserObject(KEY_CONCENTRATIONS, values[i]); + // int index = modifiedDocument.getModel().getListOfSpecies().getIndex(modifiedDocument.getModel().getSpecies(keys[i])); + // concentrationsArray[index] = Double.parseDouble(values[i]); + // fileMatchToDocument++; + // } + // } + // } + //// else if (isSystemBoundariesFile != null && isSystemBoundariesFile) {} + // if (fileMatchToDocument == 0) { + // throw new Exception("given file does not match with opened SBMLDocument"); + // } + // } + // } + + public double[] readGibbs(String file) throws IOException { + initializeGibbsArray(); + + String line; + + BufferedReader input = new BufferedReader(new FileReader(file)); + boolean header = true; + while ((line = input.readLine()) != null) { + if (!header) { + String[] helper = line.split("\t"); + if (modifiedDocument.getModel().containsReaction(helper[0])) { + if (!FluxMinimizationUtils.eliminatedReactions.contains(helper[0])) { + modifiedDocument.getModel().getReaction(helper[0]).putUserObject(KEY_GIBBS, Double.parseDouble(helper[1])); + int index = modifiedDocument.getModel().getListOfReactions().getIndex(modifiedDocument.getModel().getReaction(helper[0])); + gibbsArray[index] = Double.parseDouble(helper[1]); + if (modifiedDocument.getModel().containsReaction(helper[0] + FluxMinimizationUtils.endingForBackwardReaction)) { + // modifiedDocument.getModel().getReaction(helper[0] + FluxMinimizationUtils.endingForBackwardReaction).putUserObject(KEY_GIBBS, "isReverse"); + modifiedDocument.getModel().getReaction(helper[0] + FluxMinimizationUtils.endingForBackwardReaction).putUserObject(KEY_GIBBS, -Double.parseDouble(helper[1])); + int index2 = modifiedDocument.getModel().getListOfReactions().getIndex(modifiedDocument.getModel().getReaction(helper[0] + FluxMinimizationUtils.endingForBackwardReaction)); + gibbsArray[index2] = -Double.parseDouble(helper[1]); + } + } + } + else { + System.out.println(helper[0] + " unknown reaction"); + } + } + else { + header = false; + } + } + return gibbsArray; + } + + public double[] readSystemBoundaries(String file) throws IOException { + initializeSystemBoundariesArray(); + + String line; + + BufferedReader input = new BufferedReader(new FileReader(file)); + boolean header = true; + while ((line = input.readLine()) != null) { + if (!header) { + String[] helper = line.split("\t"); + + if (modifiedDocument.getModel().containsSpecies(helper[0])) { + int index = modifiedDocument.getModel().getListOfSpecies().getIndex(modifiedDocument.getModel().getSpecies(helper[0])); + if (helper[1].equals("-")) { + systemBoundariesArray[index] = -1; + } + else if (helper[1].equals("+")) { + systemBoundariesArray[index] = +1; + } + else if (helper[1].equals("=")) { + systemBoundariesArray[index] = 0; + } + else { + System.out.println(helper[0] + " unknown sign"); + } + } + else { + System.out.println(helper[0] + " unknown species"); + } + + } + else { + header = false; + } + } + return systemBoundariesArray; + } + } diff --git a/src/org/sbml/simulator/fba/controller/CSVDataReader.java b/src/org/sbml/simulator/fba/controller/CSVDataReader.java index cc247fc..9b31511 100644 --- a/src/org/sbml/simulator/fba/controller/CSVDataReader.java +++ b/src/org/sbml/simulator/fba/controller/CSVDataReader.java @@ -1,6 +1,4 @@ /* - * $Id: CSVDataReader.java 16:16:00 Meike Aichele$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -31,7 +29,6 @@ * Reads the CSV-files in background. * * @author Meike Aichele - * @version $Rev$ * @date 04.06.2012 * @since 1.0 */ diff --git a/src/org/sbml/simulator/fba/controller/CalculateNullSpace.java b/src/org/sbml/simulator/fba/controller/CalculateNullSpace.java index 312b17f..5e81b42 100644 --- a/src/org/sbml/simulator/fba/controller/CalculateNullSpace.java +++ b/src/org/sbml/simulator/fba/controller/CalculateNullSpace.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -26,7 +24,6 @@ /** * @author Stephanie Tscherneck - * @version $Rev$ */ public class CalculateNullSpace { diff --git a/src/org/sbml/simulator/fba/controller/Constraints.java b/src/org/sbml/simulator/fba/controller/Constraints.java index 80aa4cd..4604b7d 100644 --- a/src/org/sbml/simulator/fba/controller/Constraints.java +++ b/src/org/sbml/simulator/fba/controller/Constraints.java @@ -1,6 +1,4 @@ /* - * $Id: Constraints.java 16:17:07 Meike Aichele$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -27,236 +25,235 @@ * and ideal gas constant R in J/(mol * K). * * @author Meike Aichele - * @version $Rev$ * @date 07.05.2012 * @since 1.0 */ public class Constraints { - /** - * Contains the computed Gibbs energies - */ - private double[] computedGibbsEnergies; - - /** - * Contains the concentrations in equilibrium / steady state - */ - private double[] equilibriumConcentrations; - - /** - * Contains the Gibbs energies in steady state - */ - private double[] equilibriumGibbsEnergies; - - /** - * Contains the opened {@link SBMLDocument} - */ - public SBMLDocument originalDocument; - - /** - * The ideal gas constant R in J/(mol * K) - */ - public double R = 8.3144621; - - /** - * contains the species specific information whether the species belongs to the system boundary or not. - * NaN if species is not at the system boundary - * -1 if HC00083_i \t - : case if species can only be consumed - * +1 if HC00083_i \t + : case if species can only be produced - * 0 if HC00083_i \t = : case if species can be consumed or produced - */ - private double[] systemBoundaries; - - /** - * Contains the temperature in Kelvin under standard conditions (25 degree Celsius) - */ - public double T = 298.15; - - /** - * Constructor, that gets a {@link SBMLDocument} and creates a new - * array of Gibbs energies, that stays empty if the user doesn't check - * in a Gibbs energy file. - * - * @param doc - * @throws Exception - */ - public Constraints (SBMLDocument doc) throws Exception { - this(doc, null, null, null); - } - - - /** - * Constructor that computes the GibbsEnergies from the incoming gibbs_eq - * @param originalDoc - * @param gibbs_eq - * @param c_eq - * @param systemBoundaries - * @throws Exception - */ - public Constraints (SBMLDocument originalDoc, double[] gibbs_eq, double[] c_eq, double[] systemBoundaries) throws Exception { - this(originalDoc, gibbs_eq, c_eq, systemBoundaries, false); - } - - /** - * Constructor that computes the GibbsEnergies from the incoming gibbs_eq and c_eq. - * - * @param originalDoc - * @param gibbs_eq - * @param c_eq - * @param systemBoundaries - * @param kiloJoule (true, if gibbsEnergies are given in [kJ/mol]) - * @throws Exception - */ - public Constraints (SBMLDocument originalDoc, double[] gibbs_eq, double[] c_eq, double[] systemBoundaries, boolean kiloJoule) throws Exception { - originalDocument = originalDoc; - equilibriumConcentrations = c_eq; - this.systemBoundaries = systemBoundaries; - - if (kiloJoule) { - equilibriumGibbsEnergies = getEquillibriumGibbsEnergiesfromkKiloJoule(gibbs_eq); - } - else { - equilibriumGibbsEnergies = gibbs_eq; - } - computeGibbsEnergies(equilibriumGibbsEnergies); - } - - /** - * Computes the Gibbs energies with the formula delta(Gibbs)_j = delta(Gibbs)_j_eq + R * T * ln(sum( N[j][i] * c_eq[j] )). - * @param equilibriumsGibbs in kJ/mol - * @throws Exception - */ - private double[] computeGibbsEnergies(double[] equilibriumsGibbs) throws Exception { - if ((equilibriumsGibbs != null) && (this.originalDocument != null) && (equilibriumConcentrations != null)) { - - // initialize - StoichiometricMatrix N = FluxMinimizationUtils.getExpandedStoichiometricMatrix(originalDocument); - SBMLDocument modifiedDocument = FluxMinimizationUtils.getExpandedDocument(originalDocument, systemBoundaries); - computedGibbsEnergies = new double[equilibriumsGibbs.length]; - Model modModel = modifiedDocument.getModel(); - - // compute delta(Gibbs)_j = delta(Gibbs)_j_eq + R * T * sum(N[i][j] * ln(S[i])) - for (int j = 0; j < modModel.getReactionCount(); j++) { - double sum = 0; - // compute sum( N[i][j] * ln(S_eq[i]) ) equals to the sum( N[i][j] * c_eq[i] ) - for (int i = 0; i < modModel.getSpeciesCount(); i++) { - if (!Double.isNaN(equilibriumConcentrations[i])) { - sum += N.get(i, j) * Math.log(equilibriumConcentrations[i]); - } - } - // delta(Gibbs)_j = delta(Gibbs)_j_eq + R * T * sum( N[i][j] * ln(c_eq[i]) ) - - computedGibbsEnergies[j] = (equilibriumsGibbs[j]) + (R*T*sum); - } - - for (int j = 0; j < modModel.getReactionCount(); j++) { - String reactionID = modModel.getReaction(j).getId(); - if (reactionID.startsWith(FluxMinimizationUtils.degradationPrefix)) { - computedGibbsEnergies[j] = Double.NaN; // for system boundary added reactions - } - } - } - - // return the computed Gibbs energies - return computedGibbsEnergies; - } - - - /** - * Computes the maximum of J_j / G_j for every reaction j in the model - * @param fluxVector - * @return r_max - */ - public double computeR_max(double[] fluxVector) { - // initialization - double r_max = Double.MIN_NORMAL; - - if (computedGibbsEnergies != null) { - for (int i = 0; i < fluxVector.length; i++) { - // if you divide by NaN, r_max will be NaN and if you divide by zero, you get r_max = infinity - if (!Double.isNaN(computedGibbsEnergies[i]) && computedGibbsEnergies[i] != 0) { - double d = Math.abs(fluxVector[i])/Math.abs(computedGibbsEnergies[i]); - r_max = Math.max(r_max,(d)); - } - } - } - return r_max; - } - - - /** - * Computed Gibbs energies by - * delta(Gibbs)_j = delta(Gibbs)_j_eq + R * T * sum( N[i][j] * ln(S[i]) ) - * @return the computed gibbsEnergies - */ - public double[] getComputedGibbsEnergies() { - return computedGibbsEnergies; - } - - - /** - * @return the equilibrium concentrations - */ - public double[] getEquilibriumConcentrations() { - return equilibriumConcentrations; - } - - - /** - * @return the gibbsEnergies - */ - public double[] getEquilibriumGibbsEnergies() { - return equilibriumGibbsEnergies; - } - - /** - * Converts Gibbs values given in [kJ/mol] to [J/mol]. - * - * @param gibbs_eq - * @return adapted Gibbs energies - */ - private double[] getEquillibriumGibbsEnergiesfromkKiloJoule(double[] gibbs_eq) { - double[] adaptedGibbsEnergies = new double[gibbs_eq.length]; - for (int i = 0; i < gibbs_eq.length; i++) { - adaptedGibbsEnergies[i] = gibbs_eq[i] * 1000; - } - return adaptedGibbsEnergies; - } - - - /** - * - * @return - */ - public double[] getSystemBoundaries() { - return systemBoundaries; - } - - - /** - * @param c_eq the equilibrium concentrations to set - */ - public void setEquilibriumConcentrations(double[] c_eq) { - this.equilibriumConcentrations = c_eq; - } - - - /** - * @param gibbsEnergies the gibbsEnergies to set - * @throws Exception - */ - public void setEquilibriumGibbsEnergies(double[] gibbsEnergies) throws Exception { - this.equilibriumGibbsEnergies = gibbsEnergies; - computeGibbsEnergies(gibbsEnergies); - } - - - /** - * - * @param systemBoundaries - */ - public void setSystemBoundaries(double[] systemBoundaries) { - this.systemBoundaries = systemBoundaries; - } + /** + * Contains the computed Gibbs energies + */ + private double[] computedGibbsEnergies; + + /** + * Contains the concentrations in equilibrium / steady state + */ + private double[] equilibriumConcentrations; + + /** + * Contains the Gibbs energies in steady state + */ + private double[] equilibriumGibbsEnergies; + + /** + * Contains the opened {@link SBMLDocument} + */ + public SBMLDocument originalDocument; + + /** + * The ideal gas constant R in J/(mol * K) + */ + public double R = 8.3144621; + + /** + * contains the species specific information whether the species belongs to the system boundary or not. + * NaN if species is not at the system boundary + * -1 if HC00083_i \t - : case if species can only be consumed + * +1 if HC00083_i \t + : case if species can only be produced + * 0 if HC00083_i \t = : case if species can be consumed or produced + */ + private double[] systemBoundaries; + + /** + * Contains the temperature in Kelvin under standard conditions (25 degree Celsius) + */ + public double T = 298.15; + + /** + * Constructor, that gets a {@link SBMLDocument} and creates a new + * array of Gibbs energies, that stays empty if the user doesn't check + * in a Gibbs energy file. + * + * @param doc + * @throws Exception + */ + public Constraints (SBMLDocument doc) throws Exception { + this(doc, null, null, null); + } + + + /** + * Constructor that computes the GibbsEnergies from the incoming gibbs_eq + * @param originalDoc + * @param gibbs_eq + * @param c_eq + * @param systemBoundaries + * @throws Exception + */ + public Constraints (SBMLDocument originalDoc, double[] gibbs_eq, double[] c_eq, double[] systemBoundaries) throws Exception { + this(originalDoc, gibbs_eq, c_eq, systemBoundaries, false); + } + + /** + * Constructor that computes the GibbsEnergies from the incoming gibbs_eq and c_eq. + * + * @param originalDoc + * @param gibbs_eq + * @param c_eq + * @param systemBoundaries + * @param kiloJoule (true, if gibbsEnergies are given in [kJ/mol]) + * @throws Exception + */ + public Constraints (SBMLDocument originalDoc, double[] gibbs_eq, double[] c_eq, double[] systemBoundaries, boolean kiloJoule) throws Exception { + originalDocument = originalDoc; + equilibriumConcentrations = c_eq; + this.systemBoundaries = systemBoundaries; + + if (kiloJoule) { + equilibriumGibbsEnergies = getEquillibriumGibbsEnergiesfromkKiloJoule(gibbs_eq); + } + else { + equilibriumGibbsEnergies = gibbs_eq; + } + computeGibbsEnergies(equilibriumGibbsEnergies); + } + + /** + * Computes the Gibbs energies with the formula delta(Gibbs)_j = delta(Gibbs)_j_eq + R * T * ln(sum( N[j][i] * c_eq[j] )). + * @param equilibriumsGibbs in kJ/mol + * @throws Exception + */ + private double[] computeGibbsEnergies(double[] equilibriumsGibbs) throws Exception { + if ((equilibriumsGibbs != null) && (this.originalDocument != null) && (equilibriumConcentrations != null)) { + + // initialize + StoichiometricMatrix N = FluxMinimizationUtils.getExpandedStoichiometricMatrix(originalDocument); + SBMLDocument modifiedDocument = FluxMinimizationUtils.getExpandedDocument(originalDocument, systemBoundaries); + computedGibbsEnergies = new double[equilibriumsGibbs.length]; + Model modModel = modifiedDocument.getModel(); + + // compute delta(Gibbs)_j = delta(Gibbs)_j_eq + R * T * sum(N[i][j] * ln(S[i])) + for (int j = 0; j < modModel.getReactionCount(); j++) { + double sum = 0; + // compute sum( N[i][j] * ln(S_eq[i]) ) equals to the sum( N[i][j] * c_eq[i] ) + for (int i = 0; i < modModel.getSpeciesCount(); i++) { + if (!Double.isNaN(equilibriumConcentrations[i])) { + sum += N.get(i, j) * Math.log(equilibriumConcentrations[i]); + } + } + // delta(Gibbs)_j = delta(Gibbs)_j_eq + R * T * sum( N[i][j] * ln(c_eq[i]) ) + + computedGibbsEnergies[j] = (equilibriumsGibbs[j]) + (R*T*sum); + } + + for (int j = 0; j < modModel.getReactionCount(); j++) { + String reactionID = modModel.getReaction(j).getId(); + if (reactionID.startsWith(FluxMinimizationUtils.degradationPrefix)) { + computedGibbsEnergies[j] = Double.NaN; // for system boundary added reactions + } + } + } + + // return the computed Gibbs energies + return computedGibbsEnergies; + } + + + /** + * Computes the maximum of J_j / G_j for every reaction j in the model + * @param fluxVector + * @return r_max + */ + public double computeR_max(double[] fluxVector) { + // initialization + double r_max = Double.MIN_NORMAL; + + if (computedGibbsEnergies != null) { + for (int i = 0; i < fluxVector.length; i++) { + // if you divide by NaN, r_max will be NaN and if you divide by zero, you get r_max = infinity + if (!Double.isNaN(computedGibbsEnergies[i]) && computedGibbsEnergies[i] != 0) { + double d = Math.abs(fluxVector[i])/Math.abs(computedGibbsEnergies[i]); + r_max = Math.max(r_max,(d)); + } + } + } + return r_max; + } + + + /** + * Computed Gibbs energies by + * delta(Gibbs)_j = delta(Gibbs)_j_eq + R * T * sum( N[i][j] * ln(S[i]) ) + * @return the computed gibbsEnergies + */ + public double[] getComputedGibbsEnergies() { + return computedGibbsEnergies; + } + + + /** + * @return the equilibrium concentrations + */ + public double[] getEquilibriumConcentrations() { + return equilibriumConcentrations; + } + + + /** + * @return the gibbsEnergies + */ + public double[] getEquilibriumGibbsEnergies() { + return equilibriumGibbsEnergies; + } + + /** + * Converts Gibbs values given in [kJ/mol] to [J/mol]. + * + * @param gibbs_eq + * @return adapted Gibbs energies + */ + private double[] getEquillibriumGibbsEnergiesfromkKiloJoule(double[] gibbs_eq) { + double[] adaptedGibbsEnergies = new double[gibbs_eq.length]; + for (int i = 0; i < gibbs_eq.length; i++) { + adaptedGibbsEnergies[i] = gibbs_eq[i] * 1000; + } + return adaptedGibbsEnergies; + } + + + /** + * + * @return + */ + public double[] getSystemBoundaries() { + return systemBoundaries; + } + + + /** + * @param c_eq the equilibrium concentrations to set + */ + public void setEquilibriumConcentrations(double[] c_eq) { + this.equilibriumConcentrations = c_eq; + } + + + /** + * @param gibbsEnergies the gibbsEnergies to set + * @throws Exception + */ + public void setEquilibriumGibbsEnergies(double[] gibbsEnergies) throws Exception { + this.equilibriumGibbsEnergies = gibbsEnergies; + computeGibbsEnergies(gibbsEnergies); + } + + + /** + * + * @param systemBoundaries + */ + public void setSystemBoundaries(double[] systemBoundaries) { + this.systemBoundaries = systemBoundaries; + } } diff --git a/src/org/sbml/simulator/fba/controller/FluxBalanceAnalysis.java b/src/org/sbml/simulator/fba/controller/FluxBalanceAnalysis.java index 5e60dba..d0b1b6d 100644 --- a/src/org/sbml/simulator/fba/controller/FluxBalanceAnalysis.java +++ b/src/org/sbml/simulator/fba/controller/FluxBalanceAnalysis.java @@ -1,6 +1,4 @@ /* - * $Id: FluxBalanceAnalysis.java 16:07:08 Meike Aichele$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -37,7 +35,6 @@ * It also contains a MultiTable for the visualization of the computed fluxes. * * @author Meike Aichele - * @version $Rev$ * @date 07.05.2012 * @since 1.0 */ diff --git a/src/org/sbml/simulator/fba/controller/FluxMinimization.java b/src/org/sbml/simulator/fba/controller/FluxMinimization.java index 92fc783..870c92d 100644 --- a/src/org/sbml/simulator/fba/controller/FluxMinimization.java +++ b/src/org/sbml/simulator/fba/controller/FluxMinimization.java @@ -1,6 +1,4 @@ /* - * $Id: FluxMinimization.java 16:15:22 Meike Aichele$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -28,10 +26,9 @@ /** * Computes and contains all components you need for a flux minimization target function for FBA (flux balance analysis), * like the error, the flux vector, the concentrations (in steady-state and at the beginning) and the gibbs energies - * for the reactions in the model. + * for the reactions in the model. * * @author Meike Aichele - * @version $Rev$ * @date 07.05.2012 * @since 1.0 */ diff --git a/src/org/sbml/simulator/fba/controller/FluxMinimizationUtils.java b/src/org/sbml/simulator/fba/controller/FluxMinimizationUtils.java index f8fc715..f503a07 100644 --- a/src/org/sbml/simulator/fba/controller/FluxMinimizationUtils.java +++ b/src/org/sbml/simulator/fba/controller/FluxMinimizationUtils.java @@ -1,6 +1,4 @@ /* - * $Id: FluxVector.java 16:25:58 Meike Aichele$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -48,7 +46,6 @@ * It also contains a method to compute the Error array for FluxMinimization. * * @author Meike Aichele - * @version $Rev$ * @date 07.05.2012 * @since 1.0 */ diff --git a/src/org/sbml/simulator/fba/controller/TargetFunction.java b/src/org/sbml/simulator/fba/controller/TargetFunction.java index ffa5655..c693ad8 100644 --- a/src/org/sbml/simulator/fba/controller/TargetFunction.java +++ b/src/org/sbml/simulator/fba/controller/TargetFunction.java @@ -1,6 +1,4 @@ /* - * $Id: TargetFunction.java 16:08:51 Meike Aichele$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -19,7 +17,6 @@ /** * @author Meike Aichele - * @version $Rev$ * @date 07.05.2012 * @since 1.0 */ diff --git a/src/org/sbml/simulator/fba/controller/package-info.java b/src/org/sbml/simulator/fba/controller/package-info.java index 90aebe3..9f4f520 100644 --- a/src/org/sbml/simulator/fba/controller/package-info.java +++ b/src/org/sbml/simulator/fba/controller/package-info.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -19,7 +17,6 @@ /** * * @author - * @version $Rev$ * @since */ package org.sbml.simulator.fba.controller; diff --git a/src/org/sbml/simulator/fba/dynamic/DynamicFBA.java b/src/org/sbml/simulator/fba/dynamic/DynamicFBA.java index 8cfb6d0..9570c8c 100644 --- a/src/org/sbml/simulator/fba/dynamic/DynamicFBA.java +++ b/src/org/sbml/simulator/fba/dynamic/DynamicFBA.java @@ -1,6 +1,4 @@ /* - * $Id: DynamicFBA.java 13:11:23 faehnrich$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -33,7 +31,6 @@ /** * * @author Robin Fähnrich - * @version $Rev$ * @since 1.0 */ public class DynamicFBA { diff --git a/src/org/sbml/simulator/fba/dynamic/FluxMinimization.java b/src/org/sbml/simulator/fba/dynamic/FluxMinimization.java index 1288412..90917d0 100644 --- a/src/org/sbml/simulator/fba/dynamic/FluxMinimization.java +++ b/src/org/sbml/simulator/fba/dynamic/FluxMinimization.java @@ -1,6 +1,4 @@ /* - * $Id: FluxMinimization.java 11:34:24 faehnrich$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -47,7 +45,6 @@ * lambda_4 * ||delta_r G||) * * @author Robin Fähnrich - * @version $Rev$ * @since 1.0 */ public class FluxMinimization extends TargetFunction { diff --git a/src/org/sbml/simulator/fba/dynamic/FluxMinimizationII.java b/src/org/sbml/simulator/fba/dynamic/FluxMinimizationII.java index 1681fda..5bdcef3 100644 --- a/src/org/sbml/simulator/fba/dynamic/FluxMinimizationII.java +++ b/src/org/sbml/simulator/fba/dynamic/FluxMinimizationII.java @@ -1,6 +1,4 @@ /* - * $Id: FluxMinimizationII.java 00:24:09 faehnrich$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -41,7 +39,6 @@ * lambda_2 * Sum_k^m [c_k(t_i+1) -(c_k(t_i) + N*J*delta_t)]) * * @author Robin Fähnrich - * @version $Rev$ * @since 1.0 */ public class FluxMinimizationII extends TargetFunction { @@ -712,6 +709,4 @@ public void saveValuesForCurrentTimePoint(MultiTable workingSolutionMultiTable) } - - } diff --git a/src/org/sbml/simulator/fba/dynamic/FluxMinimizationIIa.java b/src/org/sbml/simulator/fba/dynamic/FluxMinimizationIIa.java index 9962c36..6f8cc8f 100644 --- a/src/org/sbml/simulator/fba/dynamic/FluxMinimizationIIa.java +++ b/src/org/sbml/simulator/fba/dynamic/FluxMinimizationIIa.java @@ -1,6 +1,4 @@ /* - * $Id$ $URL: - * FluxMinimizationIIa.java $ * --------------------------------------------------------------------- This * file is part of SBMLsimulator, a Java-based simulator for models of * biochemical processes encoded in the modeling language SBML. @@ -25,7 +23,6 @@ /** * @author Roland Keller - * @version $Rev$ */ public class FluxMinimizationIIa extends FluxMinimizationII { @@ -324,5 +321,4 @@ public void addConstraintsToTargetFunction(IloCplex cplex) } - } diff --git a/src/org/sbml/simulator/fba/dynamic/TargetFunction.java b/src/org/sbml/simulator/fba/dynamic/TargetFunction.java index cacc1a5..710d460 100644 --- a/src/org/sbml/simulator/fba/dynamic/TargetFunction.java +++ b/src/org/sbml/simulator/fba/dynamic/TargetFunction.java @@ -1,6 +1,4 @@ /* - * $Id: TargetFunction.java 11:31:26 faehnrich$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -29,7 +27,6 @@ /** * * @author Robin Fähnrich - * @version $Rev$ * @since 1.0 */ public abstract class TargetFunction { diff --git a/src/org/sbml/simulator/fba/dynamic/package-info.java b/src/org/sbml/simulator/fba/dynamic/package-info.java index 459e84b..5998e51 100644 --- a/src/org/sbml/simulator/fba/dynamic/package-info.java +++ b/src/org/sbml/simulator/fba/dynamic/package-info.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -19,7 +17,6 @@ /** * * @author - * @version $Rev$ * @since */ package org.sbml.simulator.fba.dynamic; diff --git a/src/org/sbml/simulator/fba/gui/ChartPanel.java b/src/org/sbml/simulator/fba/gui/ChartPanel.java index f18ab9a..3d61ab9 100644 --- a/src/org/sbml/simulator/fba/gui/ChartPanel.java +++ b/src/org/sbml/simulator/fba/gui/ChartPanel.java @@ -1,6 +1,4 @@ /* - * $Id: ChartPanel.java 16:42:12 Meike Aichele$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -31,7 +29,6 @@ * of fba is shown. * * @author Meike Aichele - * @version $Rev$ * @date 07.05.2012 * @since 1.0 */ diff --git a/src/org/sbml/simulator/fba/gui/FBAButtonPressedDialog.java b/src/org/sbml/simulator/fba/gui/FBAButtonPressedDialog.java index 298ca73..0d17ccf 100644 --- a/src/org/sbml/simulator/fba/gui/FBAButtonPressedDialog.java +++ b/src/org/sbml/simulator/fba/gui/FBAButtonPressedDialog.java @@ -1,6 +1,4 @@ /* - * $Id: FBAButtonPressedDialog.java 19:44:04 Meike Aichele$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -37,196 +35,196 @@ * Creates a dialog window where the user is requested to load a concentration and a Gibbs file * for flux balance analysis. * @author Meike Aichele - * @version $Rev$ + * @version $Rev: 1159 $ * @date 12.07.2012 * @since 1.0 */ public class FBAButtonPressedDialog extends JDialog implements ActionListener{ - /** - * Cancel button to exit the dialog without loading a file - */ - private JButton buttonCancel; - - /** - * button which opens a file chooser to choose a file - */ - private JButton buttonConcentrationsFile; - - /** - * button which opens a file chooser to choose a file - */ - private JButton buttonEnergieDatei; - - /** - * OK button which closes the dialog, when files are loaded - */ - private JButton buttonOk; - - /** - * the incoming concentration file - */ - private File concentrationFile; - - /** - * the incoming Gibbs energie file - */ - private File energieFile; - - /** - * boolean that is true if files were loaded - */ - private boolean hasFiles; - - /** - * default serial version - */ - private static final long serialVersionUID = 1L; - - - - /** - * field to write in the concentration file path - */ - private JTextField textFieldConcentrationsFile; - - /** - * field to write in the Gibbs energie file path - */ - private JTextField textFieldEnergieFile; - - /** - * Creates a new dialog to load the files for flux balance analysis. - * @param windowAncestor - * @param documentModal - */ - public FBAButtonPressedDialog(Window windowAncestor, - ModalityType documentModal) { - super(windowAncestor, documentModal); - initialize(); - hasFiles = false; - } - - /* - * (non-Javadoc) - * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) - */ - public void actionPerformed(ActionEvent e) { - JFileChooser filechooser = new JFileChooser(); - filechooser.setMultiSelectionEnabled(false); - filechooser.setDialogType(JFileChooser.OPEN_DIALOG); - filechooser.setFileSelectionMode(JFileChooser.FILES_ONLY); - - if (e.getSource().equals(buttonEnergieDatei)) { - if (filechooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { - energieFile = filechooser.getSelectedFile(); - textFieldEnergieFile.setText(energieFile.getPath()); - } else { - energieFile = null; - textFieldEnergieFile.setText(""); - } - checkOk(); - } - if (e.getSource().equals(buttonConcentrationsFile)) { - if (filechooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { - concentrationFile = filechooser.getSelectedFile(); - textFieldConcentrationsFile.setText(concentrationFile.getPath()); - } else { - concentrationFile = null; - textFieldConcentrationsFile.setText(""); - } - checkOk(); - } - if (e.getSource().equals(buttonCancel)) { - dispose(); - } - if (e.getSource().equals(buttonOk)) { - hasFiles = true; - dispose(); - } - } - - /** - * Sets the ok-button enabled if there is no file entered - */ - private void checkOk() { - if (energieFile != null || concentrationFile != null) { - buttonOk.setEnabled(true); - } else { - buttonOk.setEnabled(false); - } - } - - /** - * - * @return the incoming concentration file - */ - public File getConcentrationFile() { - return concentrationFile; - } - - /** - * @return the incoming Gibbs energie file - */ - public File getEnergieFile() { - return energieFile; - } - - /** - * @return hasFiles - */ - public boolean hasFiles() { - return hasFiles; - } - - /** - * Create the Buttons and Fields in the dialog - */ - private void initialize() { - setTitle("Please load the files to compute flux balance analysis"); - setSize(new Dimension(500, 300)); - setLayout(new BorderLayout()); - - JPanel container = new JPanel(new GridLayout(3, 1)); - - /* - * fields and buttons for the gibbs file - */ - JPanel panelEnergieFile = new JPanel(new BorderLayout()); - panelEnergieFile.setBorder(BorderFactory.createTitledBorder("Gibbs energie file: ")); - textFieldEnergieFile = new JTextField(); - buttonEnergieDatei = new JButton("..."); - buttonEnergieDatei.addActionListener(this); - panelEnergieFile.add(textFieldEnergieFile, BorderLayout.CENTER); - panelEnergieFile.add(buttonEnergieDatei, BorderLayout.EAST); - container.add(panelEnergieFile); - - /* - * fields and buttons for the concentrations file - */ - JPanel panelConcFile = new JPanel(new BorderLayout()); - panelConcFile.setBorder(BorderFactory.createTitledBorder("Concentrations file:")); - textFieldConcentrationsFile = new JTextField(); - buttonConcentrationsFile = new JButton("..."); - buttonConcentrationsFile.addActionListener(this); - panelConcFile.add(textFieldConcentrationsFile, BorderLayout.CENTER); - panelConcFile.add(buttonConcentrationsFile, BorderLayout.EAST); - container.add(panelConcFile); - - /* - * ok and cancel buttons - */ - JPanel panelButtons = new JPanel(new FlowLayout(FlowLayout.RIGHT)); - buttonOk = new JButton("Ok"); - buttonOk.setEnabled(false); - buttonOk.addActionListener(this); - buttonCancel = new JButton("Cancel"); - buttonCancel.addActionListener(this); - panelButtons.add(buttonOk, BorderLayout.WEST); - panelButtons.add(buttonCancel, BorderLayout.EAST); - add(panelButtons, BorderLayout.SOUTH); - - add(container, BorderLayout.NORTH); - setSize(new Dimension(450, 200)); - } + /** + * Cancel button to exit the dialog without loading a file + */ + private JButton buttonCancel; + + /** + * button which opens a file chooser to choose a file + */ + private JButton buttonConcentrationsFile; + + /** + * button which opens a file chooser to choose a file + */ + private JButton buttonEnergieDatei; + + /** + * OK button which closes the dialog, when files are loaded + */ + private JButton buttonOk; + + /** + * the incoming concentration file + */ + private File concentrationFile; + + /** + * the incoming Gibbs energie file + */ + private File energieFile; + + /** + * boolean that is true if files were loaded + */ + private boolean hasFiles; + + /** + * default serial version + */ + private static final long serialVersionUID = 1L; + + + + /** + * field to write in the concentration file path + */ + private JTextField textFieldConcentrationsFile; + + /** + * field to write in the Gibbs energie file path + */ + private JTextField textFieldEnergieFile; + + /** + * Creates a new dialog to load the files for flux balance analysis. + * @param windowAncestor + * @param documentModal + */ + public FBAButtonPressedDialog(Window windowAncestor, + ModalityType documentModal) { + super(windowAncestor, documentModal); + initialize(); + hasFiles = false; + } + + /* + * (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + */ + public void actionPerformed(ActionEvent e) { + JFileChooser filechooser = new JFileChooser(); + filechooser.setMultiSelectionEnabled(false); + filechooser.setDialogType(JFileChooser.OPEN_DIALOG); + filechooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + + if (e.getSource().equals(buttonEnergieDatei)) { + if (filechooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { + energieFile = filechooser.getSelectedFile(); + textFieldEnergieFile.setText(energieFile.getPath()); + } else { + energieFile = null; + textFieldEnergieFile.setText(""); + } + checkOk(); + } + if (e.getSource().equals(buttonConcentrationsFile)) { + if (filechooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { + concentrationFile = filechooser.getSelectedFile(); + textFieldConcentrationsFile.setText(concentrationFile.getPath()); + } else { + concentrationFile = null; + textFieldConcentrationsFile.setText(""); + } + checkOk(); + } + if (e.getSource().equals(buttonCancel)) { + dispose(); + } + if (e.getSource().equals(buttonOk)) { + hasFiles = true; + dispose(); + } + } + + /** + * Sets the ok-button enabled if there is no file entered + */ + private void checkOk() { + if (energieFile != null || concentrationFile != null) { + buttonOk.setEnabled(true); + } else { + buttonOk.setEnabled(false); + } + } + + /** + * + * @return the incoming concentration file + */ + public File getConcentrationFile() { + return concentrationFile; + } + + /** + * @return the incoming Gibbs energie file + */ + public File getEnergieFile() { + return energieFile; + } + + /** + * @return hasFiles + */ + public boolean hasFiles() { + return hasFiles; + } + + /** + * Create the Buttons and Fields in the dialog + */ + private void initialize() { + setTitle("Please load the files to compute flux balance analysis"); + setSize(new Dimension(500, 300)); + setLayout(new BorderLayout()); + + JPanel container = new JPanel(new GridLayout(3, 1)); + + /* + * fields and buttons for the gibbs file + */ + JPanel panelEnergieFile = new JPanel(new BorderLayout()); + panelEnergieFile.setBorder(BorderFactory.createTitledBorder("Gibbs energie file: ")); + textFieldEnergieFile = new JTextField(); + buttonEnergieDatei = new JButton("..."); + buttonEnergieDatei.addActionListener(this); + panelEnergieFile.add(textFieldEnergieFile, BorderLayout.CENTER); + panelEnergieFile.add(buttonEnergieDatei, BorderLayout.EAST); + container.add(panelEnergieFile); + + /* + * fields and buttons for the concentrations file + */ + JPanel panelConcFile = new JPanel(new BorderLayout()); + panelConcFile.setBorder(BorderFactory.createTitledBorder("Concentrations file:")); + textFieldConcentrationsFile = new JTextField(); + buttonConcentrationsFile = new JButton("..."); + buttonConcentrationsFile.addActionListener(this); + panelConcFile.add(textFieldConcentrationsFile, BorderLayout.CENTER); + panelConcFile.add(buttonConcentrationsFile, BorderLayout.EAST); + container.add(panelConcFile); + + /* + * ok and cancel buttons + */ + JPanel panelButtons = new JPanel(new FlowLayout(FlowLayout.RIGHT)); + buttonOk = new JButton("Ok"); + buttonOk.setEnabled(false); + buttonOk.addActionListener(this); + buttonCancel = new JButton("Cancel"); + buttonCancel.addActionListener(this); + panelButtons.add(buttonOk, BorderLayout.WEST); + panelButtons.add(buttonCancel, BorderLayout.EAST); + add(panelButtons, BorderLayout.SOUTH); + + add(container, BorderLayout.NORTH); + setSize(new Dimension(450, 200)); + } } diff --git a/src/org/sbml/simulator/fba/gui/FBAOptions.java b/src/org/sbml/simulator/fba/gui/FBAOptions.java index 002ecf1..e303db6 100644 --- a/src/org/sbml/simulator/fba/gui/FBAOptions.java +++ b/src/org/sbml/simulator/fba/gui/FBAOptions.java @@ -1,6 +1,4 @@ /* - * $Id: FBAProperties.java 15:29:01 Meike Aichele$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -32,161 +30,159 @@ /** * @author Meike Aichele - * @version $Rev$ * @date 17.07.2012 * @since 1.0 */ public interface FBAOptions extends KeyProvider { - /** - * Contains the choice for the target function in {@link FluxBalanceAnalysis} - * - * @author Meike Aichele - * @version $Rev$ - * @date 17.07.2012 - * @since 1.0 - */ - public static enum Manipulators { - ; - - /** - * @return all target functions - */ - public static String[] getAllManipulators() { - return new String[] { "Flux Minimization" , "Biomass Optimization"}; - } - } - - - /** - * The bundle for the user's current language. - */ - public static final ResourceBundle bundle = ResourceManager - .getBundle("org.sbml.simulator.locales.Simulator"); - - - /** - * Choose to activate the constraint J*G < 0 - */ - public static final Option ACTIVATE_CONSTRAINT_JG_LESS_THAN_0 = new Option( - "ACTIVATE_CONSTRAINT_JG_LESS_THAN_0", Boolean.class, bundle, Boolean.TRUE); - - - /** - * Choose to activate the constraint |J|-r_max*|G| < 0 - */ - public static final Option ACTIVATE_CONSTRAINT_J_R_MAX_G_LESS_THAN_0 = new Option( - "ACTIVATE_CONSTRAINT_J_R_MAX_G_LESS_THAN_0", Boolean.class, bundle, Boolean.TRUE); - - - /** - * Choose to activate the constraint J>0 - */ - public static final Option ACTIVATE_CONSTRAINT_J_GREATER_THAN_0 = new Option( - "ACTIVATE_CONSTRAINT_J_GREATER_THAN_0", Boolean.class, bundle, Boolean.TRUE); - - /** - * Choose to activate the constraint to compute the errors - */ - public static final Option ACTIVATE_CONSTRAINT_ERROR = new Option( - "ACTIVATE_CONSTRAINT_ERROR", Boolean.class, bundle, Boolean.TRUE); - - - /** - * Choose a target function - */ - public static final Option DEFAULT_TARGET_FUNCTION = new Option( - "DEFAULT_TARGET_FUNCTION", String.class, bundle, new Range(String.class, Manipulators.getAllManipulators()), "Flux Minimization"); - - /** - * Change lambda1 to weight the concentrations in the target function - */ - public static final Option LAMBDA1 = new Option( - "LAMBDA1", Double.class, bundle, Double.valueOf(TargetFunction.lambda1)); - - /** - * Change lambda2 to weight the errors in the target function - */ - public static final Option LAMBDA2 = new Option( - "LAMBDA2", Double.class, bundle, Double.valueOf(TargetFunction.lambda2)); - - /** - * Change lambda3 to weight the L-Matrix in the target function - */ - public static final Option LAMBDA3 = new Option( - "LAMBDA3", Double.class, bundle, Double.valueOf(TargetFunction.lambda3)); - - /** - * Change lambda4 to weight the Gibbs energies in the target function - */ - public static final Option LAMBDA4 = new Option( - "LAMBDA4", Double.class, bundle, Double.valueOf(TargetFunction.lambda4)); - - /** - * Load a concentration file - */ - public static final Option LOAD_CONCENTRATION_FILE = new Option( - "LOAD_CONCENTRATION_FILE", File.class, bundle, new Range(File.class, - SBFileFilter.createCSVFileFilter()), new File( - System.getProperty("user.dir"))); - - - /** - * Load a Gibbs file - */ - public static final Option LOAD_GIBBS_FILE = new Option( - "LOAD_GIBBS_FILE", File.class, bundle, new Range(File.class, - SBFileFilter.createCSVFileFilter()), new File( - System.getProperty("user.dir"))); - - - /** - * Load a System Boundaries file - */ - public static final Option LOAD_SYSTEM_BOUNDARIES_FILE = new Option( - "LOAD_SYSTEM_BOUNDARIES_FILE", File.class, bundle, new Range(File.class, - SBFileFilter.createTextFileFilter()), new File( - System.getProperty("user.dir"))); - - - /** - * Group to active some constraints - */ - @SuppressWarnings("unchecked") - public static final OptionGroup SET_CONSTRAINTS = new OptionGroup( - "SET_CONSTRAINTS", bundle, ACTIVATE_CONSTRAINT_JG_LESS_THAN_0, ACTIVATE_CONSTRAINT_J_R_MAX_G_LESS_THAN_0, ACTIVATE_CONSTRAINT_J_GREATER_THAN_0, ACTIVATE_CONSTRAINT_ERROR); - - - /** - * Set the iterations for the CPLEX algorithm - */ - public static final Option SET_ITERATIONS = new Option( - "SET_ITERATIONS", Integer.class, bundle, new Range( - Integer.class, "{(1, 100000]}"), Integer.valueOf(600)); - - - /** - * Group to load files - */ - @SuppressWarnings("unchecked") - public static final OptionGroup SET_FILES_GROUP = new OptionGroup( - "SET_FILES_GROUP", bundle, LOAD_GIBBS_FILE, LOAD_CONCENTRATION_FILE, LOAD_SYSTEM_BOUNDARIES_FILE); - - - /** - * Group of lambdas - */ - @SuppressWarnings("unchecked") - public static final OptionGroup SET_LAMBDAS = new OptionGroup( - "SET_LAMBDAS", bundle, LAMBDA1, - LAMBDA2, LAMBDA3, LAMBDA4); - - /** - * Group to set the target function and the iterations - */ - @SuppressWarnings("unchecked") - public static final OptionGroup SET_TARGET_AND_ITERATIONS = new OptionGroup( - "SET_TARGET_AND_ITERATIONS", bundle, DEFAULT_TARGET_FUNCTION, SET_ITERATIONS); - - + /** + * Contains the choice for the target function in {@link FluxBalanceAnalysis} + * + * @author Meike Aichele + * @date 17.07.2012 + * @since 1.0 + */ + public static enum Manipulators { + ; + + /** + * @return all target functions + */ + public static String[] getAllManipulators() { + return new String[] { "Flux Minimization" , "Biomass Optimization"}; + } + } + + + /** + * The bundle for the user's current language. + */ + public static final ResourceBundle bundle = ResourceManager + .getBundle("org.sbml.simulator.locales.Simulator"); + + + /** + * Choose to activate the constraint J*G < 0 + */ + public static final Option ACTIVATE_CONSTRAINT_JG_LESS_THAN_0 = new Option( + "ACTIVATE_CONSTRAINT_JG_LESS_THAN_0", Boolean.class, bundle, Boolean.TRUE); + + + /** + * Choose to activate the constraint |J|-r_max*|G| < 0 + */ + public static final Option ACTIVATE_CONSTRAINT_J_R_MAX_G_LESS_THAN_0 = new Option( + "ACTIVATE_CONSTRAINT_J_R_MAX_G_LESS_THAN_0", Boolean.class, bundle, Boolean.TRUE); + + + /** + * Choose to activate the constraint J>0 + */ + public static final Option ACTIVATE_CONSTRAINT_J_GREATER_THAN_0 = new Option( + "ACTIVATE_CONSTRAINT_J_GREATER_THAN_0", Boolean.class, bundle, Boolean.TRUE); + + /** + * Choose to activate the constraint to compute the errors + */ + public static final Option ACTIVATE_CONSTRAINT_ERROR = new Option( + "ACTIVATE_CONSTRAINT_ERROR", Boolean.class, bundle, Boolean.TRUE); + + + /** + * Choose a target function + */ + public static final Option DEFAULT_TARGET_FUNCTION = new Option( + "DEFAULT_TARGET_FUNCTION", String.class, bundle, new Range(String.class, Manipulators.getAllManipulators()), "Flux Minimization"); + + /** + * Change lambda1 to weight the concentrations in the target function + */ + public static final Option LAMBDA1 = new Option( + "LAMBDA1", Double.class, bundle, Double.valueOf(TargetFunction.lambda1)); + + /** + * Change lambda2 to weight the errors in the target function + */ + public static final Option LAMBDA2 = new Option( + "LAMBDA2", Double.class, bundle, Double.valueOf(TargetFunction.lambda2)); + + /** + * Change lambda3 to weight the L-Matrix in the target function + */ + public static final Option LAMBDA3 = new Option( + "LAMBDA3", Double.class, bundle, Double.valueOf(TargetFunction.lambda3)); + + /** + * Change lambda4 to weight the Gibbs energies in the target function + */ + public static final Option LAMBDA4 = new Option( + "LAMBDA4", Double.class, bundle, Double.valueOf(TargetFunction.lambda4)); + + /** + * Load a concentration file + */ + public static final Option LOAD_CONCENTRATION_FILE = new Option( + "LOAD_CONCENTRATION_FILE", File.class, bundle, new Range(File.class, + SBFileFilter.createCSVFileFilter()), new File( + System.getProperty("user.dir"))); + + + /** + * Load a Gibbs file + */ + public static final Option LOAD_GIBBS_FILE = new Option( + "LOAD_GIBBS_FILE", File.class, bundle, new Range(File.class, + SBFileFilter.createCSVFileFilter()), new File( + System.getProperty("user.dir"))); + + + /** + * Load a System Boundaries file + */ + public static final Option LOAD_SYSTEM_BOUNDARIES_FILE = new Option( + "LOAD_SYSTEM_BOUNDARIES_FILE", File.class, bundle, new Range(File.class, + SBFileFilter.createTextFileFilter()), new File( + System.getProperty("user.dir"))); + + + /** + * Group to active some constraints + */ + @SuppressWarnings("unchecked") + public static final OptionGroup SET_CONSTRAINTS = new OptionGroup( + "SET_CONSTRAINTS", bundle, ACTIVATE_CONSTRAINT_JG_LESS_THAN_0, ACTIVATE_CONSTRAINT_J_R_MAX_G_LESS_THAN_0, ACTIVATE_CONSTRAINT_J_GREATER_THAN_0, ACTIVATE_CONSTRAINT_ERROR); + + + /** + * Set the iterations for the CPLEX algorithm + */ + public static final Option SET_ITERATIONS = new Option( + "SET_ITERATIONS", Integer.class, bundle, new Range( + Integer.class, "{(1, 100000]}"), Integer.valueOf(600)); + + + /** + * Group to load files + */ + @SuppressWarnings("unchecked") + public static final OptionGroup SET_FILES_GROUP = new OptionGroup( + "SET_FILES_GROUP", bundle, LOAD_GIBBS_FILE, LOAD_CONCENTRATION_FILE, LOAD_SYSTEM_BOUNDARIES_FILE); + + + /** + * Group of lambdas + */ + @SuppressWarnings("unchecked") + public static final OptionGroup SET_LAMBDAS = new OptionGroup( + "SET_LAMBDAS", bundle, LAMBDA1, + LAMBDA2, LAMBDA3, LAMBDA4); + + /** + * Group to set the target function and the iterations + */ + @SuppressWarnings("unchecked") + public static final OptionGroup SET_TARGET_AND_ITERATIONS = new OptionGroup( + "SET_TARGET_AND_ITERATIONS", bundle, DEFAULT_TARGET_FUNCTION, SET_ITERATIONS); + + } diff --git a/src/org/sbml/simulator/fba/gui/FBAPanel.java b/src/org/sbml/simulator/fba/gui/FBAPanel.java index c551ca1..da251ef 100644 --- a/src/org/sbml/simulator/fba/gui/FBAPanel.java +++ b/src/org/sbml/simulator/fba/gui/FBAPanel.java @@ -1,6 +1,4 @@ /* - * $Id: FBAPanel.java 16:38:58 Meike Aichele$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -49,478 +47,477 @@ * - a VODPanel, which visualizes the results of fba in a diagram. * * @author Meike Aichele - * @version $Rev$ * @date 07.05.2012 * @since 1.0 */ public class FBAPanel extends JPanel implements ActionListener, TableModelListener{ - /** - * The tab with the chart of concentrations - */ - private ChartPanel chartConc; - - /** - * The tab with the chart of fluxes - */ - private ChartPanel chartFlux; - - /** - * The concentration file - */ - private File concFile; - - /** - * The concentration lower bounds - */ - private double[] ConcLowerBound; - - /** - * The concentration upper bounds - */ - private double[] ConcUpperBound; - - /** - * The current opened {@link SBMLDocument} - */ - private SBMLDocument originalDoc; - - /** - * Constraint compute Error is on, when this variable is set true. - */ - private boolean Error_constraint; - - /** - * The current computed {@link FluxBalanceAnalysis} - */ - private FluxBalanceAnalysis fba; - - /** - * The fluxes lower bounds - */ - private double[] FluxLowerBound; - - /** - * The fluxes upper bounds - */ - private double[] FluxUpperBound; - - /** - * the Gibbs energy file - */ - private File gibbsFile; - - /** - * Number of iterations for CPLEX - */ - private int iterations; - - /** - * Constraint J*G < 0 is on, when this variable is set true. - */ - private boolean JG_less_than_0; - - /** - * Constraint J > 0 is on, when this variable is set true. - */ - private boolean J_greater_0; - - /** - * Constraint |J| - r_max*|G| < 0 is on, when this variable is set true - */ - private boolean J_rmax_G_less_than_0; - - /** - * weighted factor lambda1 to weight the concentrations - */ - private double lambda1; - - /** - * weighted factor lambda2 to weight the errors - */ - private double lambda2; - - /** - * weighted factor lambda3 to weight the L-Matrix - */ - private double lambda3; - - /** - * weighted factor lambda4 to weight the Gibbs energies - */ - private double lambda4; - - /** - * Contains the parent simulator panel. - */ - private SimulationPanel simultorPanel; - - /** - * serial version number - */ - private static final long serialVersionUID = 1L; - - /** - * The setting panel wich contains the upper and lower bounds of fluxes and concentrations - */ - private FBASettingPanel settings; - - /** - * Contains the system boundaries file. - */ - private File systemBoundariesFile; - - /** - * The target fluxes - */ - private String[] targetFluxes = null; - - /** - * Contains if this is the first call of FBA - */ - private boolean theFirstCall = true; - - /** - * Contains the visualization of data - */ - private VODPanel vod; - - /** - * Constructor that sets all the different panels - * @param document - */ - public FBAPanel (SBMLDocument document) { - super(new BorderLayout()); - originalDoc = document; - - //set the panels - this.chartConc = new ChartPanel(document); - this.chartFlux = new ChartPanel(document); - this.settings = new FBASettingPanel(this); - this.vod = new VODPanel(); - - //init the fba panel - init(); - setVisible(true); - } - - - /* - * (non-Javadoc) - * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) - */ - @Override - public void actionPerformed(ActionEvent e) { - // TODO Auto-generated method stub - } - - /** - * Check if the options were changed. - */ - private void checkPreferences() { - //check files - SBPreferences sbPrefs = SBPreferences.getPreferencesFor(FBAOptions.class); - if (sbPrefs.getFile(FBAOptions.LOAD_CONCENTRATION_FILE) != null) { - concFile = sbPrefs.getFile(FBAOptions.LOAD_CONCENTRATION_FILE); - } - if (sbPrefs.getFile(FBAOptions.LOAD_GIBBS_FILE)!= null) { - gibbsFile = sbPrefs.getFile(FBAOptions.LOAD_GIBBS_FILE); - } - if (sbPrefs.getFile(FBAOptions.LOAD_SYSTEM_BOUNDARIES_FILE) != null) { - systemBoundariesFile = sbPrefs.getFile(FBAOptions.LOAD_SYSTEM_BOUNDARIES_FILE); - } - //check constraints and interations - Error_constraint = sbPrefs.getBoolean(FBAOptions.ACTIVATE_CONSTRAINT_ERROR); - JG_less_than_0 = sbPrefs.getBoolean(FBAOptions.ACTIVATE_CONSTRAINT_JG_LESS_THAN_0); - J_rmax_G_less_than_0 = sbPrefs.getBoolean(FBAOptions.ACTIVATE_CONSTRAINT_J_R_MAX_G_LESS_THAN_0); - J_greater_0 = sbPrefs.getBoolean(FBAOptions.ACTIVATE_CONSTRAINT_J_GREATER_THAN_0); - iterations = sbPrefs.getInt(FBAOptions.SET_ITERATIONS); - - //check lambdas - lambda1 = sbPrefs.getDouble(FBAOptions.LAMBDA1); - lambda2 = sbPrefs.getDouble(FBAOptions.LAMBDA2); - lambda3 = sbPrefs.getDouble(FBAOptions.LAMBDA3); - lambda4 = sbPrefs.getDouble(FBAOptions.LAMBDA4); - - //check upper and lower bounds - ConcLowerBound = settings.getConcLowerBoundValues(); - ConcUpperBound = settings.getConcUpperBoundValues(); - FluxLowerBound = settings.getFluxLowerBoundValues(); - FluxUpperBound = settings.getFluxUpperBoundValues(); - } - - - /** - * @return the concFile - */ - public File getConcFile() { - return concFile; - } - - - /** - * @return the currentDoc - */ - public SBMLDocument getCurrentDoc() { - return originalDoc; - } - - - /** - * @return the fba - */ - public FluxBalanceAnalysis getFba() { - return fba; - } - - - /** - * @return the settings - */ - public FBASettingPanel getFBASettingPanel() { - return settings; - } - - - /** - * @return the gibbsFile - */ - public File getGibbsFile() { - return gibbsFile; - } - - - /** - * @return the vod - */ - public VODPanel getVODPanel() { - return vod; - } - - /** - * Initialize the whole FBA frame. - */ - private void init() { - JSplitPane jsp = new JSplitPane(); - vod.setBorder(BorderFactory.createLoweredBevelBorder()); - - // legend panel - LegendPanel legendPanel = new LegendPanel(originalDoc.getModel(), true); - legendPanel.addTableModelListener(this); - legendPanel.setBorder(BorderFactory.createLoweredBevelBorder()); - - // split left components - JSplitPane topDown = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true, - legendPanel, settings); - topDown.setDividerLocation(topDown.getDividerLocation() + 100); - - JTabbedPane tabs = new JTabbedPane(); - tabs.add("Visualization", vod); - tabs.add("Table Concentrations", chartConc); - tabs.add("Table Fluxes", chartFlux); - - // split all - jsp.setLeftComponent(topDown); - jsp.setRightComponent(tabs); - jsp.setDividerLocation(topDown.getDividerLocation() + 200); - - add(jsp); - } - - - /** - * @return true if all bounds are set, else false. - */ - private boolean isSetBounds() { - return FluxLowerBound != null && FluxUpperBound!= null && ConcLowerBound != null && ConcUpperBound != null; - } - - - /** - * @return the first call boolean - */ - public boolean isTheFirstCall() { - return theFirstCall; - } - - /** - * @param concFile the concFile to set - */ - public void setConcFile(File concFile) { - this.concFile = concFile; - } - - - /** - * @param currentDoc the currentDoc to set - */ - public void setCurrentDoc(SBMLDocument currentDoc) { - this.originalDoc = currentDoc; - } - - - /** - * @param settings the settings to set - */ - public void setFBASettingPanel(FBASettingPanel settings) { - this.settings = settings; - } - - - /** - * @param gibbsFile the gibbsFile to set - * @throws Exception - */ - public void setGibbsFile(File gibbsFile) throws Exception { - this.gibbsFile = gibbsFile; - startFBA(); - } - - - /** - * @param simPanel - */ - public void setSimulatorPanel(SimulationPanel simPanel) { - simultorPanel = simPanel; - init(); - } - - - /** - * @param firstCall set the boolean that contains true if - * this is the first call - */ - public void setTheFirstCall(boolean firstCall) { - theFirstCall = firstCall; - } - - - /** - * @param vod the vod to set - */ - public void setVODPanel(VODPanel vod) { - this.vod = vod; - } - - - /** - * start the flux balance analysis - * @throws Exception - */ - public void startFBA() throws Exception { - checkPreferences(); - try { - CSVDataConverter csvConverterSysBounds; - - if (systemBoundariesFile != null) { - csvConverterSysBounds = new CSVDataConverter(originalDoc, true); - csvConverterSysBounds.readSystemBoundariesFromFile(systemBoundariesFile); - } - else { - csvConverterSysBounds = new CSVDataConverter(originalDoc); - } - - while(csvConverterSysBounds.getSystemBoundariesArray() == null) { - //wait while reading - } - - double[] sysBounds = FluxMinimizationUtils.getCorrectedSystemBoundaries(originalDoc, csvConverterSysBounds.getSystemBoundariesArray()); - CSVDataConverter csvConverterConc = new CSVDataConverter(originalDoc, sysBounds); - if (concFile != null) { - csvConverterConc.readConcentrationsFromFile(concFile); - while(csvConverterConc.getConcentrationsArray() == null) { - //wait while reading - } - } - - CSVDataConverter csvConverterGibbs = new CSVDataConverter(originalDoc, sysBounds); - if (gibbsFile != null) { - csvConverterGibbs.readGibbsFromFile(gibbsFile); - while(csvConverterGibbs.getGibbsArray() == null) { - //wait while reading - } - } - - Constraints c = new Constraints(originalDoc, csvConverterGibbs.getGibbsArray(), csvConverterConc.getConcentrationsArray(), sysBounds, true); - fba = new FluxBalanceAnalysis(originalDoc, c, targetFluxes); - - //set constraints and iterations - fba.setConstraintError(Error_constraint); - fba.setConstraintJG(JG_less_than_0); - fba.setConstraintJ_rmaxG(J_rmax_G_less_than_0); - fba.setCplexIterations(iterations); - fba.setConstraintJ0(J_greater_0); - - //set lambdas - fba.setLambda1(lambda1); - fba.setLambda2(lambda2); - fba.setLambda3(lambda3); - fba.setLambda4(lambda4); - - //set bounds - if (isSetBounds() && settings.isBoundsAreChanged()) { - fba.setLbOfConcentrations(ConcLowerBound); - fba.setLbOfReactions(FluxLowerBound); - fba.setUbOfConcentrations(ConcUpperBound); - fba.setUbOfReactions(FluxUpperBound); - } - - //solve - try{ - fba.solve(); - } catch (ilog.cplex.CpxException cplexExc) { - cplexExc.printStackTrace(); - JOptionPane.showMessageDialog(this, - new String("Only the null vector solution found."), - "available solutions", - JOptionPane.ERROR_MESSAGE); - } - } catch (Exception e) { - e.printStackTrace(); - JOptionPane.showMessageDialog(this, - e, - "Running FBA failed", - JOptionPane.ERROR_MESSAGE); - } - - //visualize fba - simultorPanel.getDynamicGraphView().addFluxbalance(fba.fluxesForVisualization); - - if (theFirstCall) { - vod.setDocument(FluxMinimizationUtils.getExpandedDocument(originalDoc)); - vod.setFluxes(fba.solutionFluxVector); - vod.setConcentrations(fba.solutionConcentrations); - vod.init(); - chartFlux.setFluxes(fba.solutionFluxVector); - chartConc.setConcentrations(fba.solutionConcentrations); - chartFlux.init(); - chartConc.init(); - settings.setFBA(fba); - this.repaint(); - } else { - vod.setDocument(FluxMinimizationUtils.getExpandedDocument(originalDoc)); - vod.setFluxes(fba.solutionFluxVector); - vod.setConcentrations(fba.solutionConcentrations); - vod.updateUI(); - chartFlux.setFluxes(fba.solutionFluxVector); - chartConc.setConcentrations(fba.solutionConcentrations); - chartFlux.getTableFluxes().revalidate(); - chartFlux.getTableFluxes().repaint(); - chartFlux.getTableFluxes().updateUI(); - chartConc.getTableConc().repaint(); - settings.setFBA(fba); - this.repaint(); - } - } - - - /* - * (non-Javadoc) - * @see javax.swing.event.TableModelListener#tableChanged(javax.swing.event.TableModelEvent) - */ - @Override - public void tableChanged(TableModelEvent arg0) { - // TODO Auto-generated method stub - } + /** + * The tab with the chart of concentrations + */ + private ChartPanel chartConc; + + /** + * The tab with the chart of fluxes + */ + private ChartPanel chartFlux; + + /** + * The concentration file + */ + private File concFile; + + /** + * The concentration lower bounds + */ + private double[] ConcLowerBound; + + /** + * The concentration upper bounds + */ + private double[] ConcUpperBound; + + /** + * The current opened {@link SBMLDocument} + */ + private SBMLDocument originalDoc; + + /** + * Constraint compute Error is on, when this variable is set true. + */ + private boolean Error_constraint; + + /** + * The current computed {@link FluxBalanceAnalysis} + */ + private FluxBalanceAnalysis fba; + + /** + * The fluxes lower bounds + */ + private double[] FluxLowerBound; + + /** + * The fluxes upper bounds + */ + private double[] FluxUpperBound; + + /** + * the Gibbs energy file + */ + private File gibbsFile; + + /** + * Number of iterations for CPLEX + */ + private int iterations; + + /** + * Constraint J*G < 0 is on, when this variable is set true. + */ + private boolean JG_less_than_0; + + /** + * Constraint J > 0 is on, when this variable is set true. + */ + private boolean J_greater_0; + + /** + * Constraint |J| - r_max*|G| < 0 is on, when this variable is set true + */ + private boolean J_rmax_G_less_than_0; + + /** + * weighted factor lambda1 to weight the concentrations + */ + private double lambda1; + + /** + * weighted factor lambda2 to weight the errors + */ + private double lambda2; + + /** + * weighted factor lambda3 to weight the L-Matrix + */ + private double lambda3; + + /** + * weighted factor lambda4 to weight the Gibbs energies + */ + private double lambda4; + + /** + * Contains the parent simulator panel. + */ + private SimulationPanel simultorPanel; + + /** + * serial version number + */ + private static final long serialVersionUID = 1L; + + /** + * The setting panel wich contains the upper and lower bounds of fluxes and concentrations + */ + private FBASettingPanel settings; + + /** + * Contains the system boundaries file. + */ + private File systemBoundariesFile; + + /** + * The target fluxes + */ + private String[] targetFluxes = null; + + /** + * Contains if this is the first call of FBA + */ + private boolean theFirstCall = true; + + /** + * Contains the visualization of data + */ + private VODPanel vod; + + /** + * Constructor that sets all the different panels + * @param document + */ + public FBAPanel (SBMLDocument document) { + super(new BorderLayout()); + originalDoc = document; + + //set the panels + this.chartConc = new ChartPanel(document); + this.chartFlux = new ChartPanel(document); + this.settings = new FBASettingPanel(this); + this.vod = new VODPanel(); + + //init the fba panel + init(); + setVisible(true); + } + + + /* + * (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + */ + @Override + public void actionPerformed(ActionEvent e) { + // TODO Auto-generated method stub + } + + /** + * Check if the options were changed. + */ + private void checkPreferences() { + //check files + SBPreferences sbPrefs = SBPreferences.getPreferencesFor(FBAOptions.class); + if (sbPrefs.getFile(FBAOptions.LOAD_CONCENTRATION_FILE) != null) { + concFile = sbPrefs.getFile(FBAOptions.LOAD_CONCENTRATION_FILE); + } + if (sbPrefs.getFile(FBAOptions.LOAD_GIBBS_FILE)!= null) { + gibbsFile = sbPrefs.getFile(FBAOptions.LOAD_GIBBS_FILE); + } + if (sbPrefs.getFile(FBAOptions.LOAD_SYSTEM_BOUNDARIES_FILE) != null) { + systemBoundariesFile = sbPrefs.getFile(FBAOptions.LOAD_SYSTEM_BOUNDARIES_FILE); + } + //check constraints and interations + Error_constraint = sbPrefs.getBoolean(FBAOptions.ACTIVATE_CONSTRAINT_ERROR); + JG_less_than_0 = sbPrefs.getBoolean(FBAOptions.ACTIVATE_CONSTRAINT_JG_LESS_THAN_0); + J_rmax_G_less_than_0 = sbPrefs.getBoolean(FBAOptions.ACTIVATE_CONSTRAINT_J_R_MAX_G_LESS_THAN_0); + J_greater_0 = sbPrefs.getBoolean(FBAOptions.ACTIVATE_CONSTRAINT_J_GREATER_THAN_0); + iterations = sbPrefs.getInt(FBAOptions.SET_ITERATIONS); + + //check lambdas + lambda1 = sbPrefs.getDouble(FBAOptions.LAMBDA1); + lambda2 = sbPrefs.getDouble(FBAOptions.LAMBDA2); + lambda3 = sbPrefs.getDouble(FBAOptions.LAMBDA3); + lambda4 = sbPrefs.getDouble(FBAOptions.LAMBDA4); + + //check upper and lower bounds + ConcLowerBound = settings.getConcLowerBoundValues(); + ConcUpperBound = settings.getConcUpperBoundValues(); + FluxLowerBound = settings.getFluxLowerBoundValues(); + FluxUpperBound = settings.getFluxUpperBoundValues(); + } + + + /** + * @return the concFile + */ + public File getConcFile() { + return concFile; + } + + + /** + * @return the currentDoc + */ + public SBMLDocument getCurrentDoc() { + return originalDoc; + } + + + /** + * @return the fba + */ + public FluxBalanceAnalysis getFba() { + return fba; + } + + + /** + * @return the settings + */ + public FBASettingPanel getFBASettingPanel() { + return settings; + } + + + /** + * @return the gibbsFile + */ + public File getGibbsFile() { + return gibbsFile; + } + + + /** + * @return the vod + */ + public VODPanel getVODPanel() { + return vod; + } + + /** + * Initialize the whole FBA frame. + */ + private void init() { + JSplitPane jsp = new JSplitPane(); + vod.setBorder(BorderFactory.createLoweredBevelBorder()); + + // legend panel + LegendPanel legendPanel = new LegendPanel(originalDoc.getModel(), true); + legendPanel.addTableModelListener(this); + legendPanel.setBorder(BorderFactory.createLoweredBevelBorder()); + + // split left components + JSplitPane topDown = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true, + legendPanel, settings); + topDown.setDividerLocation(topDown.getDividerLocation() + 100); + + JTabbedPane tabs = new JTabbedPane(); + tabs.add("Visualization", vod); + tabs.add("Table Concentrations", chartConc); + tabs.add("Table Fluxes", chartFlux); + + // split all + jsp.setLeftComponent(topDown); + jsp.setRightComponent(tabs); + jsp.setDividerLocation(topDown.getDividerLocation() + 200); + + add(jsp); + } + + + /** + * @return true if all bounds are set, else false. + */ + private boolean isSetBounds() { + return FluxLowerBound != null && FluxUpperBound!= null && ConcLowerBound != null && ConcUpperBound != null; + } + + + /** + * @return the first call boolean + */ + public boolean isTheFirstCall() { + return theFirstCall; + } + + /** + * @param concFile the concFile to set + */ + public void setConcFile(File concFile) { + this.concFile = concFile; + } + + + /** + * @param currentDoc the currentDoc to set + */ + public void setCurrentDoc(SBMLDocument currentDoc) { + this.originalDoc = currentDoc; + } + + + /** + * @param settings the settings to set + */ + public void setFBASettingPanel(FBASettingPanel settings) { + this.settings = settings; + } + + + /** + * @param gibbsFile the gibbsFile to set + * @throws Exception + */ + public void setGibbsFile(File gibbsFile) throws Exception { + this.gibbsFile = gibbsFile; + startFBA(); + } + + + /** + * @param simPanel + */ + public void setSimulatorPanel(SimulationPanel simPanel) { + simultorPanel = simPanel; + init(); + } + + + /** + * @param firstCall set the boolean that contains true if + * this is the first call + */ + public void setTheFirstCall(boolean firstCall) { + theFirstCall = firstCall; + } + + + /** + * @param vod the vod to set + */ + public void setVODPanel(VODPanel vod) { + this.vod = vod; + } + + + /** + * start the flux balance analysis + * @throws Exception + */ + public void startFBA() throws Exception { + checkPreferences(); + try { + CSVDataConverter csvConverterSysBounds; + + if (systemBoundariesFile != null) { + csvConverterSysBounds = new CSVDataConverter(originalDoc, true); + csvConverterSysBounds.readSystemBoundariesFromFile(systemBoundariesFile); + } + else { + csvConverterSysBounds = new CSVDataConverter(originalDoc); + } + + while(csvConverterSysBounds.getSystemBoundariesArray() == null) { + //wait while reading + } + + double[] sysBounds = FluxMinimizationUtils.getCorrectedSystemBoundaries(originalDoc, csvConverterSysBounds.getSystemBoundariesArray()); + CSVDataConverter csvConverterConc = new CSVDataConverter(originalDoc, sysBounds); + if (concFile != null) { + csvConverterConc.readConcentrationsFromFile(concFile); + while(csvConverterConc.getConcentrationsArray() == null) { + //wait while reading + } + } + + CSVDataConverter csvConverterGibbs = new CSVDataConverter(originalDoc, sysBounds); + if (gibbsFile != null) { + csvConverterGibbs.readGibbsFromFile(gibbsFile); + while(csvConverterGibbs.getGibbsArray() == null) { + //wait while reading + } + } + + Constraints c = new Constraints(originalDoc, csvConverterGibbs.getGibbsArray(), csvConverterConc.getConcentrationsArray(), sysBounds, true); + fba = new FluxBalanceAnalysis(originalDoc, c, targetFluxes); + + //set constraints and iterations + fba.setConstraintError(Error_constraint); + fba.setConstraintJG(JG_less_than_0); + fba.setConstraintJ_rmaxG(J_rmax_G_less_than_0); + fba.setCplexIterations(iterations); + fba.setConstraintJ0(J_greater_0); + + //set lambdas + fba.setLambda1(lambda1); + fba.setLambda2(lambda2); + fba.setLambda3(lambda3); + fba.setLambda4(lambda4); + + //set bounds + if (isSetBounds() && settings.isBoundsAreChanged()) { + fba.setLbOfConcentrations(ConcLowerBound); + fba.setLbOfReactions(FluxLowerBound); + fba.setUbOfConcentrations(ConcUpperBound); + fba.setUbOfReactions(FluxUpperBound); + } + + //solve + try{ + fba.solve(); + } catch (ilog.cplex.CpxException cplexExc) { + cplexExc.printStackTrace(); + JOptionPane.showMessageDialog(this, + new String("Only the null vector solution found."), + "available solutions", + JOptionPane.ERROR_MESSAGE); + } + } catch (Exception e) { + e.printStackTrace(); + JOptionPane.showMessageDialog(this, + e, + "Running FBA failed", + JOptionPane.ERROR_MESSAGE); + } + + //visualize fba + simultorPanel.getDynamicGraphView().addFluxbalance(fba.fluxesForVisualization); + + if (theFirstCall) { + vod.setDocument(FluxMinimizationUtils.getExpandedDocument(originalDoc)); + vod.setFluxes(fba.solutionFluxVector); + vod.setConcentrations(fba.solutionConcentrations); + vod.init(); + chartFlux.setFluxes(fba.solutionFluxVector); + chartConc.setConcentrations(fba.solutionConcentrations); + chartFlux.init(); + chartConc.init(); + settings.setFBA(fba); + this.repaint(); + } else { + vod.setDocument(FluxMinimizationUtils.getExpandedDocument(originalDoc)); + vod.setFluxes(fba.solutionFluxVector); + vod.setConcentrations(fba.solutionConcentrations); + vod.updateUI(); + chartFlux.setFluxes(fba.solutionFluxVector); + chartConc.setConcentrations(fba.solutionConcentrations); + chartFlux.getTableFluxes().revalidate(); + chartFlux.getTableFluxes().repaint(); + chartFlux.getTableFluxes().updateUI(); + chartConc.getTableConc().repaint(); + settings.setFBA(fba); + this.repaint(); + } + } + + + /* + * (non-Javadoc) + * @see javax.swing.event.TableModelListener#tableChanged(javax.swing.event.TableModelEvent) + */ + @Override + public void tableChanged(TableModelEvent arg0) { + // TODO Auto-generated method stub + } } diff --git a/src/org/sbml/simulator/fba/gui/FBASettingPanel.java b/src/org/sbml/simulator/fba/gui/FBASettingPanel.java index a0b665b..f950dbe 100644 --- a/src/org/sbml/simulator/fba/gui/FBASettingPanel.java +++ b/src/org/sbml/simulator/fba/gui/FBASettingPanel.java @@ -1,6 +1,4 @@ /* - * $Id: FBASettingPanel.java 16:54:53 Meike Aichele$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -42,421 +40,420 @@ /** * @author Meike Aichele - * @version $Rev$ * @date 07.05.2012 * @since 1.0 */ public class FBASettingPanel extends JPanel implements ActionListener, ChangeListener{ - /** - * User changed the bounds of fluxes or concentrations - */ - private boolean boundsAreChanged; - - /** - * button to reset the changes - */ - private JButton buttonReset; - - /** - * array of JSpinners for concentrations lower bounds - */ - private JSpinner[] concLowerBounds; - - /** - * array of JSpinners for concentrations upper bounds - */ - private JSpinner[] concUpperBounds; - - /** - * contains the current {@link SBMLDocument}. - */ - private SBMLDocument document; - - /** - * The corresponding FluxBalanceAnalysis-object - */ - private FluxBalanceAnalysis fba; - - /** - * array of JSpinners for fluxes lower bounds - */ - private JSpinner[] fluxLowerBounds; - - /** - * array of JSpinners for fluxes upper bounds - */ - private JSpinner[] fluxUpperBounds; - - /** - * Backup of the original values - */ - private double originalConcValues[][]; - - /** - * Backup of the original values - */ - private double originalFluxValues[][]; - - /** - * - */ - private static final long serialVersionUID = 1L; - - /** - * containing the tabs fluxes, species and general properties. - */ - private JTabbedPane tab; - - /** - * Default constructor - */ - public FBASettingPanel() { - super(new BorderLayout()); - tab = new JTabbedPane(); - init(); - } - - /** - * Constructor that gets the corresponding {@link FBAPanel} - * @param parent - */ - public FBASettingPanel(FBAPanel parent) { - super(new BorderLayout()); - fba = parent.getFba(); - tab = new JTabbedPane(); - document = parent.getCurrentDoc(); - init(); - } - - /* - * (non-Javadoc) - * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) - */ - @Override - public void actionPerformed(ActionEvent e) { - Object source = e.getSource(); - if (source.equals(buttonReset) && tab.getSelectedIndex() == 1) { - // its the flux tab - for (int i = 0; i < fluxLowerBounds.length; i++) { - fluxLowerBounds[i].setValue(originalFluxValues[i][0]); - fluxUpperBounds[i].setValue(originalFluxValues[i][1]); - fba.setLbOfReactionJ(originalFluxValues[i][0], i); - fba.setUbOfReactionJ(originalFluxValues[i][1], i); - } - } else if (source.equals(buttonReset) && tab.getSelectedIndex() == 0) { - // its the conc tab - for (int j = 0; j < concLowerBounds.length; j++) { - concLowerBounds[j].setValue(originalConcValues[j][0]); - concUpperBounds[j].setValue(originalConcValues[j][1]); - fba.setLbOfConcentrationI(originalConcValues[j][0], j); - fba.setUbOfConcentrationI(originalConcValues[j][1], j); - } - } - } - - /** - * @return the concLowerBounds - */ - public JSpinner[] getConcLowerBounds() { - return concLowerBounds; - } - - /** - * @return the concLowerBoundValues - */ - public double[] getConcLowerBoundValues() { - double[] concLBValues = new double[concLowerBounds.length]; - for (int i = 0; i < concLBValues.length; i++) { - if (concLowerBounds[i].getValue() instanceof Double) { - concLBValues[i] = (Double) concLowerBounds[i].getValue(); - } else if (concLowerBounds[i].getValue() instanceof Integer) { - concLBValues[i] = (Integer) concLowerBounds[i].getValue(); - } - } - return concLBValues; - } - - /** - * @return the concUpperBounds - */ - public JSpinner[] getConcUpperBounds() { - return concUpperBounds; - } - - /** - * @return the concUpperBoundValues - */ - public double[] getConcUpperBoundValues() { - double[] concUBValues = new double[concUpperBounds.length]; - for (int i = 0; i < concUBValues.length; i++) { - if (concUpperBounds[i].getValue() instanceof Double) { - concUBValues[i] = (Double) concUpperBounds[i].getValue(); - } else if (concUpperBounds[i].getValue() instanceof Integer) { - concUBValues[i] = (Integer) concUpperBounds[i].getValue(); - } - } - return concUBValues; - } - - /** - * @return the fluxLowerBounds - */ - public JSpinner[] getFluxLowerBounds() { - return fluxLowerBounds; - } - - /** - * @return the fluxLowerBoundValues - */ - public double[] getFluxLowerBoundValues() { - double[] fluxLBValues = new double[fluxLowerBounds.length]; - for (int i = 0; i < fluxLBValues.length; i++) { - if (fluxLowerBounds[i].getValue() instanceof Double) { - fluxLBValues[i] = (Double) fluxLowerBounds[i].getValue(); - } else if (fluxLowerBounds[i].getValue() instanceof Integer) { - fluxLBValues[i] = (Integer) fluxLowerBounds[i].getValue(); - } - } - return fluxLBValues; - } - - /** - * @return the fluxUpperBounds - */ - public JSpinner[] getFluxUpperBounds() { - return fluxUpperBounds; - } - - /** - * @return the fluxUpperBoundValues - */ - public double[] getFluxUpperBoundValues() { - double[] fluxUBValues = new double[fluxUpperBounds.length]; - for (int i = 0; i < fluxUBValues.length; i++) { - if (fluxUpperBounds[i].getValue() instanceof Double) { - fluxUBValues[i] = (Double) fluxUpperBounds[i].getValue(); - } else if (fluxUpperBounds[i].getValue() instanceof Integer) { - fluxUBValues[i] = (Integer) fluxUpperBounds[i].getValue(); - } - } - return fluxUBValues; - } - - /** - * Initialize the whole panel with the different tabs - */ - private void init() { - initTabs(document); - - JPanel foot = new JPanel(); - buttonReset = GUITools.createJButton(this, Command.RESET); - buttonReset.setEnabled(false); - foot.add(buttonReset); - - tab.setSize(500, 800); - JScrollPane sp = new JScrollPane(tab); - add(sp, BorderLayout.CENTER); - add(foot, BorderLayout.SOUTH); - - this.setVisible(true); - } - - /** - * initialize the components of the fluxes-/species-tab - * @param panel - * @param objects - */ - private void initSpecificTab(JPanel panel, Object[] objects) { - if (objects != null) { - if(objects[0] instanceof Species) { - concUpperBounds = new JSpinner[objects.length]; - concLowerBounds = new JSpinner[objects.length]; - originalConcValues = new double[objects.length][2]; - for(int i = 0; i < objects.length; i++) { - - //create components of this row - JPanel row_i = new JPanel(new BorderLayout()); - // upper bounds - concUpperBounds[i] = new JSpinner(); - concUpperBounds[i].setValue(0.1); - concUpperBounds[i].addChangeListener(this); - - // lower bounds - concLowerBounds[i] = new JSpinner(); - concLowerBounds[i].setValue(0.0); - concLowerBounds[i].addChangeListener(this); - - // original values - originalConcValues[i][0] = (Double) concLowerBounds[i].getValue(); - originalConcValues[i][1] = (Double) concUpperBounds[i].getValue(); - - Species currentSpec = (Species) objects[i]; - JLabel specLabel = new JLabel(currentSpec.isSetName() ? currentSpec.getName() : currentSpec.getId()); - - //add Components - LayoutHelper lh = new LayoutHelper(row_i); - lh.add(specLabel); - JPanel bounds = new JPanel(); - LayoutHelper lh2 = new LayoutHelper(bounds); - lh2.add(concLowerBounds[i], 2, i, 1, 1, 0, 0); - lh2.add(concUpperBounds[i], 4, i, 1, 1, 0, 0); - lh.add(bounds); - panel.add(row_i); - } - } else if (objects[0] instanceof Reaction) { - fluxUpperBounds = new JSpinner[objects.length]; - fluxLowerBounds = new JSpinner[objects.length]; - originalFluxValues = new double[objects.length][2]; - for(int i = 0; i < objects.length; i++) { - - //create components of this row - JPanel row_i = new JPanel(new BorderLayout()); - - //upper bounds - fluxUpperBounds[i] = new JSpinner(); - fluxUpperBounds[i].setValue(10000.0); - fluxUpperBounds[i].addChangeListener(this); - - //lower bounds - fluxLowerBounds[i] = new JSpinner(); - fluxLowerBounds[i].setValue(0.0); - fluxLowerBounds[i].addChangeListener(this); - - //original values - originalFluxValues[i][0] = (Double) fluxLowerBounds[i].getValue(); - originalFluxValues[i][1] = (Double) fluxUpperBounds[i].getValue(); - - Reaction currentReac = (Reaction) objects[i]; - JLabel reacLabel = new JLabel(currentReac.isSetName() ? currentReac.getName() : currentReac.getId()); - - //add Components - LayoutHelper lh = new LayoutHelper(row_i); - lh.add(reacLabel); - JPanel bounds = new JPanel(); - LayoutHelper lh2 = new LayoutHelper(bounds); - lh2.add(fluxLowerBounds[i], 2, i, 1, 1, 0, 0); - lh2.add(fluxUpperBounds[i], 4, i, 1, 1, 0, 0); - lh.add(bounds); - panel.add(row_i); - } - } - } - } - - /** - * Initialize the tabs - * @param document2 - */ - private void initTabs(SBMLDocument document2) { - if (document2 != null) { - // create the panel for the concentrations of species - JPanel speciesPanel = new JPanel(); - initSpecificTab(speciesPanel, document2.getModel().getListOfSpecies().toArray()); - tab.add("Concentrations", speciesPanel); - - // create the panel for the flux values - JPanel fluxPanel = new JPanel(); - try { - initSpecificTab(fluxPanel, document2.getModel().getListOfReactions().toArray()); - } catch (Exception e) { - LinkedList nullList = new LinkedList(); - for (int i = 0; i < document2.getModel().getListOfReactions().size(); i++) { - nullList.add(0); - } - initSpecificTab(fluxPanel, null); - e.printStackTrace(); - } - tab.add("Fluxes", fluxPanel); - } - } - - /** - * @return the boundsAreChanged - */ - public boolean isBoundsAreChanged() { - return boundsAreChanged; - } - - /** - * @param concLowerBounds the concLowerBounds to set - */ - public void setConcLowerBounds(JSpinner[] concLowerBounds) { - this.concLowerBounds = concLowerBounds; - } - - /** - * @param concUpperBounds the concUpperBounds to set - */ - public void setConcUpperBounds(JSpinner[] concUpperBounds) { - this.concUpperBounds = concUpperBounds; - } - - /** - * sets the fba object - * @param fba2 - */ - public void setFBA(FluxBalanceAnalysis fba2) { - this.fba = fba2; - } - - /** - * @param fluxLowerBounds the fluxLowerBounds to set - */ - public void setFluxLowerBounds(JSpinner[] fluxLowerBounds) { - this.fluxLowerBounds = fluxLowerBounds; - } - - /** - * @param fluxUpperBounds the fluxUpperBounds to set - */ - public void setFluxUpperBounds(JSpinner[] fluxUpperBounds) { - this.fluxUpperBounds = fluxUpperBounds; - } - - /* - * (non-Javadoc) - * @see javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent) - */ - @Override - public void stateChanged(ChangeEvent evt) { - JSpinner source = (JSpinner) evt.getSource(); - for (int i = 0; i < fluxLowerBounds.length; i++) { - if (source.equals(fluxLowerBounds[i])) { - // the source is a lb source of fluxes - if (source.getValue() instanceof Integer) { - fba.setLbOfReactionJ((Integer) source.getValue(), i); - } else if (source.getValue() instanceof Double) { - fba.setLbOfReactionJ((Double) source.getValue(), i); - } - } else if (source.equals(fluxUpperBounds[i])) { - // the source is a ub source of fluxes - if (source.getValue() instanceof Integer) { - fba.setUbOfReactionJ((Integer) source.getValue(), i); - } else if (source.getValue() instanceof Double) { - fba.setUbOfReactionJ((Double) source.getValue(), i); - } - } - } - for (int s = 0; s < concLowerBounds.length; s++) { - if (source.equals(concLowerBounds[s])) { - // the source is a lb source of concentrations - if (source.getValue() instanceof Integer) { - fba.setLbOfConcentrationI((Integer) source.getValue(), s); - } else if (source.getValue() instanceof Double) { - fba.setLbOfConcentrationI((Double) source.getValue(), s); - } - } else if (source.equals(concUpperBounds[s])) { - // the source is a ub source of concentrations - if (source.getValue() instanceof Integer) { - fba.setUbOfConcentrationI((Integer) source.getValue(), s); - } else if (source.getValue() instanceof Double) { - fba.setUbOfConcentrationI((Double) source.getValue(), s); - } - } - } - buttonReset.setEnabled(true); - boundsAreChanged = true; - } + /** + * User changed the bounds of fluxes or concentrations + */ + private boolean boundsAreChanged; + + /** + * button to reset the changes + */ + private JButton buttonReset; + + /** + * array of JSpinners for concentrations lower bounds + */ + private JSpinner[] concLowerBounds; + + /** + * array of JSpinners for concentrations upper bounds + */ + private JSpinner[] concUpperBounds; + + /** + * contains the current {@link SBMLDocument}. + */ + private SBMLDocument document; + + /** + * The corresponding FluxBalanceAnalysis-object + */ + private FluxBalanceAnalysis fba; + + /** + * array of JSpinners for fluxes lower bounds + */ + private JSpinner[] fluxLowerBounds; + + /** + * array of JSpinners for fluxes upper bounds + */ + private JSpinner[] fluxUpperBounds; + + /** + * Backup of the original values + */ + private double originalConcValues[][]; + + /** + * Backup of the original values + */ + private double originalFluxValues[][]; + + /** + * + */ + private static final long serialVersionUID = 1L; + + /** + * containing the tabs fluxes, species and general properties. + */ + private JTabbedPane tab; + + /** + * Default constructor + */ + public FBASettingPanel() { + super(new BorderLayout()); + tab = new JTabbedPane(); + init(); + } + + /** + * Constructor that gets the corresponding {@link FBAPanel} + * @param parent + */ + public FBASettingPanel(FBAPanel parent) { + super(new BorderLayout()); + fba = parent.getFba(); + tab = new JTabbedPane(); + document = parent.getCurrentDoc(); + init(); + } + + /* + * (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + */ + @Override + public void actionPerformed(ActionEvent e) { + Object source = e.getSource(); + if (source.equals(buttonReset) && tab.getSelectedIndex() == 1) { + // its the flux tab + for (int i = 0; i < fluxLowerBounds.length; i++) { + fluxLowerBounds[i].setValue(originalFluxValues[i][0]); + fluxUpperBounds[i].setValue(originalFluxValues[i][1]); + fba.setLbOfReactionJ(originalFluxValues[i][0], i); + fba.setUbOfReactionJ(originalFluxValues[i][1], i); + } + } else if (source.equals(buttonReset) && tab.getSelectedIndex() == 0) { + // its the conc tab + for (int j = 0; j < concLowerBounds.length; j++) { + concLowerBounds[j].setValue(originalConcValues[j][0]); + concUpperBounds[j].setValue(originalConcValues[j][1]); + fba.setLbOfConcentrationI(originalConcValues[j][0], j); + fba.setUbOfConcentrationI(originalConcValues[j][1], j); + } + } + } + + /** + * @return the concLowerBounds + */ + public JSpinner[] getConcLowerBounds() { + return concLowerBounds; + } + + /** + * @return the concLowerBoundValues + */ + public double[] getConcLowerBoundValues() { + double[] concLBValues = new double[concLowerBounds.length]; + for (int i = 0; i < concLBValues.length; i++) { + if (concLowerBounds[i].getValue() instanceof Double) { + concLBValues[i] = (Double) concLowerBounds[i].getValue(); + } else if (concLowerBounds[i].getValue() instanceof Integer) { + concLBValues[i] = (Integer) concLowerBounds[i].getValue(); + } + } + return concLBValues; + } + + /** + * @return the concUpperBounds + */ + public JSpinner[] getConcUpperBounds() { + return concUpperBounds; + } + + /** + * @return the concUpperBoundValues + */ + public double[] getConcUpperBoundValues() { + double[] concUBValues = new double[concUpperBounds.length]; + for (int i = 0; i < concUBValues.length; i++) { + if (concUpperBounds[i].getValue() instanceof Double) { + concUBValues[i] = (Double) concUpperBounds[i].getValue(); + } else if (concUpperBounds[i].getValue() instanceof Integer) { + concUBValues[i] = (Integer) concUpperBounds[i].getValue(); + } + } + return concUBValues; + } + + /** + * @return the fluxLowerBounds + */ + public JSpinner[] getFluxLowerBounds() { + return fluxLowerBounds; + } + + /** + * @return the fluxLowerBoundValues + */ + public double[] getFluxLowerBoundValues() { + double[] fluxLBValues = new double[fluxLowerBounds.length]; + for (int i = 0; i < fluxLBValues.length; i++) { + if (fluxLowerBounds[i].getValue() instanceof Double) { + fluxLBValues[i] = (Double) fluxLowerBounds[i].getValue(); + } else if (fluxLowerBounds[i].getValue() instanceof Integer) { + fluxLBValues[i] = (Integer) fluxLowerBounds[i].getValue(); + } + } + return fluxLBValues; + } + + /** + * @return the fluxUpperBounds + */ + public JSpinner[] getFluxUpperBounds() { + return fluxUpperBounds; + } + + /** + * @return the fluxUpperBoundValues + */ + public double[] getFluxUpperBoundValues() { + double[] fluxUBValues = new double[fluxUpperBounds.length]; + for (int i = 0; i < fluxUBValues.length; i++) { + if (fluxUpperBounds[i].getValue() instanceof Double) { + fluxUBValues[i] = (Double) fluxUpperBounds[i].getValue(); + } else if (fluxUpperBounds[i].getValue() instanceof Integer) { + fluxUBValues[i] = (Integer) fluxUpperBounds[i].getValue(); + } + } + return fluxUBValues; + } + + /** + * Initialize the whole panel with the different tabs + */ + private void init() { + initTabs(document); + + JPanel foot = new JPanel(); + buttonReset = GUITools.createJButton(this, Command.RESET); + buttonReset.setEnabled(false); + foot.add(buttonReset); + + tab.setSize(500, 800); + JScrollPane sp = new JScrollPane(tab); + add(sp, BorderLayout.CENTER); + add(foot, BorderLayout.SOUTH); + + this.setVisible(true); + } + + /** + * initialize the components of the fluxes-/species-tab + * @param panel + * @param objects + */ + private void initSpecificTab(JPanel panel, Object[] objects) { + if (objects != null) { + if(objects[0] instanceof Species) { + concUpperBounds = new JSpinner[objects.length]; + concLowerBounds = new JSpinner[objects.length]; + originalConcValues = new double[objects.length][2]; + for(int i = 0; i < objects.length; i++) { + + //create components of this row + JPanel row_i = new JPanel(new BorderLayout()); + // upper bounds + concUpperBounds[i] = new JSpinner(); + concUpperBounds[i].setValue(0.1); + concUpperBounds[i].addChangeListener(this); + + // lower bounds + concLowerBounds[i] = new JSpinner(); + concLowerBounds[i].setValue(0.0); + concLowerBounds[i].addChangeListener(this); + + // original values + originalConcValues[i][0] = (Double) concLowerBounds[i].getValue(); + originalConcValues[i][1] = (Double) concUpperBounds[i].getValue(); + + Species currentSpec = (Species) objects[i]; + JLabel specLabel = new JLabel(currentSpec.isSetName() ? currentSpec.getName() : currentSpec.getId()); + + //add Components + LayoutHelper lh = new LayoutHelper(row_i); + lh.add(specLabel); + JPanel bounds = new JPanel(); + LayoutHelper lh2 = new LayoutHelper(bounds); + lh2.add(concLowerBounds[i], 2, i, 1, 1, 0, 0); + lh2.add(concUpperBounds[i], 4, i, 1, 1, 0, 0); + lh.add(bounds); + panel.add(row_i); + } + } else if (objects[0] instanceof Reaction) { + fluxUpperBounds = new JSpinner[objects.length]; + fluxLowerBounds = new JSpinner[objects.length]; + originalFluxValues = new double[objects.length][2]; + for(int i = 0; i < objects.length; i++) { + + //create components of this row + JPanel row_i = new JPanel(new BorderLayout()); + + //upper bounds + fluxUpperBounds[i] = new JSpinner(); + fluxUpperBounds[i].setValue(10000.0); + fluxUpperBounds[i].addChangeListener(this); + + //lower bounds + fluxLowerBounds[i] = new JSpinner(); + fluxLowerBounds[i].setValue(0.0); + fluxLowerBounds[i].addChangeListener(this); + + //original values + originalFluxValues[i][0] = (Double) fluxLowerBounds[i].getValue(); + originalFluxValues[i][1] = (Double) fluxUpperBounds[i].getValue(); + + Reaction currentReac = (Reaction) objects[i]; + JLabel reacLabel = new JLabel(currentReac.isSetName() ? currentReac.getName() : currentReac.getId()); + + //add Components + LayoutHelper lh = new LayoutHelper(row_i); + lh.add(reacLabel); + JPanel bounds = new JPanel(); + LayoutHelper lh2 = new LayoutHelper(bounds); + lh2.add(fluxLowerBounds[i], 2, i, 1, 1, 0, 0); + lh2.add(fluxUpperBounds[i], 4, i, 1, 1, 0, 0); + lh.add(bounds); + panel.add(row_i); + } + } + } + } + + /** + * Initialize the tabs + * @param document2 + */ + private void initTabs(SBMLDocument document2) { + if (document2 != null) { + // create the panel for the concentrations of species + JPanel speciesPanel = new JPanel(); + initSpecificTab(speciesPanel, document2.getModel().getListOfSpecies().toArray()); + tab.add("Concentrations", speciesPanel); + + // create the panel for the flux values + JPanel fluxPanel = new JPanel(); + try { + initSpecificTab(fluxPanel, document2.getModel().getListOfReactions().toArray()); + } catch (Exception e) { + LinkedList nullList = new LinkedList(); + for (int i = 0; i < document2.getModel().getListOfReactions().size(); i++) { + nullList.add(0); + } + initSpecificTab(fluxPanel, null); + e.printStackTrace(); + } + tab.add("Fluxes", fluxPanel); + } + } + + /** + * @return the boundsAreChanged + */ + public boolean isBoundsAreChanged() { + return boundsAreChanged; + } + + /** + * @param concLowerBounds the concLowerBounds to set + */ + public void setConcLowerBounds(JSpinner[] concLowerBounds) { + this.concLowerBounds = concLowerBounds; + } + + /** + * @param concUpperBounds the concUpperBounds to set + */ + public void setConcUpperBounds(JSpinner[] concUpperBounds) { + this.concUpperBounds = concUpperBounds; + } + + /** + * sets the fba object + * @param fba2 + */ + public void setFBA(FluxBalanceAnalysis fba2) { + this.fba = fba2; + } + + /** + * @param fluxLowerBounds the fluxLowerBounds to set + */ + public void setFluxLowerBounds(JSpinner[] fluxLowerBounds) { + this.fluxLowerBounds = fluxLowerBounds; + } + + /** + * @param fluxUpperBounds the fluxUpperBounds to set + */ + public void setFluxUpperBounds(JSpinner[] fluxUpperBounds) { + this.fluxUpperBounds = fluxUpperBounds; + } + + /* + * (non-Javadoc) + * @see javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent) + */ + @Override + public void stateChanged(ChangeEvent evt) { + JSpinner source = (JSpinner) evt.getSource(); + for (int i = 0; i < fluxLowerBounds.length; i++) { + if (source.equals(fluxLowerBounds[i])) { + // the source is a lb source of fluxes + if (source.getValue() instanceof Integer) { + fba.setLbOfReactionJ((Integer) source.getValue(), i); + } else if (source.getValue() instanceof Double) { + fba.setLbOfReactionJ((Double) source.getValue(), i); + } + } else if (source.equals(fluxUpperBounds[i])) { + // the source is a ub source of fluxes + if (source.getValue() instanceof Integer) { + fba.setUbOfReactionJ((Integer) source.getValue(), i); + } else if (source.getValue() instanceof Double) { + fba.setUbOfReactionJ((Double) source.getValue(), i); + } + } + } + for (int s = 0; s < concLowerBounds.length; s++) { + if (source.equals(concLowerBounds[s])) { + // the source is a lb source of concentrations + if (source.getValue() instanceof Integer) { + fba.setLbOfConcentrationI((Integer) source.getValue(), s); + } else if (source.getValue() instanceof Double) { + fba.setLbOfConcentrationI((Double) source.getValue(), s); + } + } else if (source.equals(concUpperBounds[s])) { + // the source is a ub source of concentrations + if (source.getValue() instanceof Integer) { + fba.setUbOfConcentrationI((Integer) source.getValue(), s); + } else if (source.getValue() instanceof Double) { + fba.setUbOfConcentrationI((Double) source.getValue(), s); + } + } + } + buttonReset.setEnabled(true); + boundsAreChanged = true; + } } diff --git a/src/org/sbml/simulator/fba/gui/VODPanel.java b/src/org/sbml/simulator/fba/gui/VODPanel.java index 0408498..7499a4b 100644 --- a/src/org/sbml/simulator/fba/gui/VODPanel.java +++ b/src/org/sbml/simulator/fba/gui/VODPanel.java @@ -1,6 +1,4 @@ /* - * $Id: VODPanel.java 16:43:13 Meike Aichele$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -38,9 +36,8 @@ /** * This class represents a panel for the Visualization Of Datasets (VOD) * of the computed datasets of fba. - * + * * @author Meike Aichele - * @version $Rev$ * @date 07.05.2012 * @since 1.0 */ @@ -128,7 +125,7 @@ public double[] getFluxes() { } /** - * Sets the bar-plot + * Sets the bar-plot */ public void init() { DefaultCategoryDataset underlying = new DefaultCategoryDataset(); @@ -146,7 +143,7 @@ public void init() { // JButton switchButton = new JButton("Change to dynamic View"); // switchButton.addActionListener(this); // changePlotPanel.add(switchButton, BorderLayout.EAST); - // + // // add(changePlotPanel, BorderLayout.SOUTH); setVisible(true); } @@ -169,5 +166,4 @@ public void setDocument(SBMLDocument expandedDocument) { modDoc = expandedDocument; } - } diff --git a/src/org/sbml/simulator/fba/gui/package-info.java b/src/org/sbml/simulator/fba/gui/package-info.java index b616561..b8e92dc 100644 --- a/src/org/sbml/simulator/fba/gui/package-info.java +++ b/src/org/sbml/simulator/fba/gui/package-info.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -20,7 +18,6 @@ * * * @author - * @version $Rev$ * @since */ package org.sbml.simulator.fba.gui; diff --git a/src/org/sbml/simulator/gui/InteractiveScanPanel.java b/src/org/sbml/simulator/gui/InteractiveScanPanel.java index 702fcb0..dbb952c 100644 --- a/src/org/sbml/simulator/gui/InteractiveScanPanel.java +++ b/src/org/sbml/simulator/gui/InteractiveScanPanel.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -76,7 +74,6 @@ * * @author Andreas Dräger * @date 2010-09-17 - * @version $Rev$ * @since 1.0 */ public class InteractiveScanPanel extends JPanel implements ActionListener, diff --git a/src/org/sbml/simulator/gui/LegendPanel.java b/src/org/sbml/simulator/gui/LegendPanel.java index 16755b9..e26406b 100644 --- a/src/org/sbml/simulator/gui/LegendPanel.java +++ b/src/org/sbml/simulator/gui/LegendPanel.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -66,7 +64,6 @@ * * @author Andreas Dräger * @date 2010-09-17 - * @version $Rev$ * @since 1.0 */ public class LegendPanel extends JPanel implements TableModelListener, @@ -80,7 +77,6 @@ public class LegendPanel extends JPanel implements TableModelListener, /** * * @author Andreas Dräger - * @version $Rev$ * @since 1.0 */ public static enum COMPONENT implements ActionCommand { diff --git a/src/org/sbml/simulator/gui/QuantitySelectionPanel.java b/src/org/sbml/simulator/gui/QuantitySelectionPanel.java index 3de9a72..0828f41 100644 --- a/src/org/sbml/simulator/gui/QuantitySelectionPanel.java +++ b/src/org/sbml/simulator/gui/QuantitySelectionPanel.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -83,7 +81,6 @@ * * @author Andreas Dräger * @date 2010-09-08 - * @version $Rev$ * @since 1.0 */ public class QuantitySelectionPanel extends JPanel implements ActionListener { @@ -92,7 +89,6 @@ public class QuantitySelectionPanel extends JPanel implements ActionListener { * A helpful class to filter the content of a {@link TableModel}. * * @author Andreas Dräger - * @version $Rev$ * @since 1.0 */ private class DocumentFilterListener extends AbstractDocumentFilterListener { @@ -121,7 +117,6 @@ protected RowFilter createFilter(String text) throws Exception { * A wrapper for {@link QuantityRange} to an {@link AbstractTableModel}. * * @author Andreas Dräger - * @version $Rev$ * @since 1.0 */ private class QuantityRangeModel extends AbstractTableModel { @@ -356,7 +351,6 @@ public void setValueAt(Object aValue, int rowIndex, int columnIndex) { /** * @author Andreas Dräger * @date 2010-09-08 - * @version $Rev$ * @since 1.0 */ public static enum SelectionCommand implements ActionCommand { diff --git a/src/org/sbml/simulator/gui/SimulationPanel.java b/src/org/sbml/simulator/gui/SimulationPanel.java index dffef88..8d46604 100644 --- a/src/org/sbml/simulator/gui/SimulationPanel.java +++ b/src/org/sbml/simulator/gui/SimulationPanel.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -48,6 +46,7 @@ import org.jfree.chart.ChartUtilities; import org.jfree.chart.JFreeChart; import org.sbml.jsbml.Model; +import org.sbml.jsbml.Quantity; import org.sbml.jsbml.SBMLDocument; import org.sbml.jsbml.SBMLWriter; import org.sbml.optimization.problem.EstimationOptions; @@ -90,11 +89,10 @@ * content of the simulation is displayed to the user. It includes the plot * area ({@link Plot}), the legend overview ({@link LegendPanel}), the * simulation tool panel ({@link SimulationToolPanel}). - * + * * @author Andreas Dräger * @author Clemens Wrzodek * @date 2010-04-06 - * @version $Rev$ * @since 1.0 */ public class SimulationPanel extends JPanel implements @@ -115,32 +113,32 @@ public class SimulationPanel extends JPanel implements private static final long serialVersionUID = -7278034514446047207L; /** - * + * */ private static final int TAB_FBA_INDEX = 5; /** - * + * */ private static final int TAB_EXPERIMENT_INDEX = 2; /** - * + * */ private static final int TAB_IN_SILICO_DATA_INDEX = 1; /** - * + * */ private static final int TAB_MODEL_VIEW_INDEX = 3; /** - * + * */ private static final int TAB_GRAPH_VIEW_INDEX = 4; /** - * + * */ private static final int TAB_SIMULATION_INDEX = 0; @@ -150,7 +148,7 @@ public class SimulationPanel extends JPanel implements private MultipleTableView dataTableView; /** - * + * */ private List listeners; @@ -182,7 +180,7 @@ public class SimulationPanel extends JPanel implements private SimulationManager simulationManager; /** - * + * */ private JToolBar simulationToolPanel; @@ -192,12 +190,12 @@ public class SimulationPanel extends JPanel implements private JTabbedPane tabbedPane; /** - * + * */ private SimulationVisualizationPanel visualizationPanel; /** - * + * */ private DynamicView dynamicGraphView; @@ -246,7 +244,7 @@ public SimulationPanel(Model model) { } /** - * + * * @param title * @param data */ @@ -269,7 +267,7 @@ public void addPropertyChangedListener(PropertyChangeListener listener) { } } /** - * + * */ public void closeAllExperimentalData() { for (int i = dataTableView.getTableCount() - 1; i >= 0; i--) { @@ -278,7 +276,7 @@ public void closeAllExperimentalData() { } /** - * + * * @param index */ public void closeExpermentalData(int index) { @@ -320,7 +318,7 @@ public QualityMeasure getDistance() { } /** - * + * * @return */ public List getExperimentalData() { @@ -335,7 +333,7 @@ public MultiTable getExperimentalData(int index) { } /** - * + * * @return */ public int getExperimentalDataCount() { @@ -601,7 +599,7 @@ public void propertyChange(PropertyChangeEvent evt) { } /** - * + * */ public void refreshStepSize() { getSolver().setStepSize(simulationManager.getSimulationConfiguration().getStepSize()); @@ -617,7 +615,7 @@ public void removePropertyChangedListener(PropertyChangeListener listener) { } /** - * + * * @param saveDir * @return */ @@ -638,7 +636,7 @@ private File saveModel(String saveDir) { } /** - * + * * @param saveDir * @return */ @@ -666,7 +664,7 @@ private File savePlotImage(String saveDir) { } /** - * + * */ private File saveTable(MultiTable tableModel, String noDataAvailableMessage) { try { @@ -791,7 +789,7 @@ private void setSimulationData(MultiTable data) { /** * Conducts the simulation. - * + * * @throws Exception */ public void simulate() throws Exception { diff --git a/src/org/sbml/simulator/gui/SimulationToolPanel.java b/src/org/sbml/simulator/gui/SimulationToolPanel.java index 8eae0f4..6ed4883 100644 --- a/src/org/sbml/simulator/gui/SimulationToolPanel.java +++ b/src/org/sbml/simulator/gui/SimulationToolPanel.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -68,7 +66,6 @@ * * @author Andreas Dräger * @date 2010-09-16 - * @version $Rev$ * @since 1.0 */ public class SimulationToolPanel extends JPanel implements ItemListener, @@ -450,7 +447,9 @@ public void preferenceChange(PreferenceChangeEvent evt) { } else { logger.fine(key + "=" + evt.getNewValue()); for (PreferenceChangeListener listener : listOfPreferenceChangeListeners) { - listener.preferenceChange(evt); + if(listener != null) { + listener.preferenceChange(evt); + } } } diff --git a/src/org/sbml/simulator/gui/SimulationVisualizationPanel.java b/src/org/sbml/simulator/gui/SimulationVisualizationPanel.java index f194386..bb18808 100644 --- a/src/org/sbml/simulator/gui/SimulationVisualizationPanel.java +++ b/src/org/sbml/simulator/gui/SimulationVisualizationPanel.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -60,7 +58,6 @@ * * @author Andreas Dräger * @date 2010-09-20 - * @version $Rev$ * @since 1.0 */ public class SimulationVisualizationPanel extends JSplitPane implements @@ -266,7 +263,7 @@ private void plot(List data, boolean connected, boolean clearFirst) infos[i] = null; } } - if (clearFirst) { + if (clearFirst && plot != null) { plot.clearAll(); } plot.plot(d, connected, plotColors, infos); @@ -396,6 +393,20 @@ public void setSimulationData(MultiTable simData) { //selectLegendItems(simData); plot(); } + + /** + * + */ + public void setLegendPanel (LegendPanel legend) { + legendPanel = legend; + } + + /** + * + */ + public void setPlot(Plot plot) { + this.plot = plot; + } /* (non-Javadoc) * @seejavax.swing.event.TableModelListener#tableChanged(javax.swing.event.TableModelEvent) @@ -427,6 +438,7 @@ public void tableChanged(TableModelEvent e) { } else if (e.getSource() instanceof MultiTable) { setSimulationData((MultiTable) e.getSource()); } + } /** diff --git a/src/org/sbml/simulator/gui/SimulationWorker.java b/src/org/sbml/simulator/gui/SimulationWorker.java index dadb777..a8028a9 100644 --- a/src/org/sbml/simulator/gui/SimulationWorker.java +++ b/src/org/sbml/simulator/gui/SimulationWorker.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -49,7 +47,6 @@ * @author Philip Stevens * @author Max Zwießele * @date 2010-09-17 - * @version $Rev$ * @since 1.0 */ public class SimulationWorker extends SwingWorker implements PropertyChangeListener { diff --git a/src/org/sbml/simulator/gui/SimulatorUI.java b/src/org/sbml/simulator/gui/SimulatorUI.java index 242093a..481b7d1 100644 --- a/src/org/sbml/simulator/gui/SimulatorUI.java +++ b/src/org/sbml/simulator/gui/SimulatorUI.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -109,12 +107,11 @@ * The main graphical user interface for {@link SBMLsimulator}. This window * provides all functions of the program through its menu bar and organizes the * display of model and experimental data. - * + * * @author Andreas Dräger * @author Philip Stevens * @author Max Zwießele * @date 2010-04-15 - * @version $Rev$ * @since 1.0 */ public class SimulatorUI extends BaseFrame implements CSVOptions, ItemListener, @@ -122,7 +119,7 @@ public class SimulatorUI extends BaseFrame implements CSVOptions, ItemListener, /** * Commands that can be understood by this dialog. - * + * * @author Andreas Dräger */ public static enum Command implements ActionCommand { @@ -231,14 +228,14 @@ public String getToolTip() { private GarudaSoftwareBackend garudaBackend; /** - * + * */ public SimulatorUI() { this((AppConf) null); } /** - * + * * @param appConf */ public SimulatorUI(AppConf appConf) { @@ -266,7 +263,7 @@ public SimulatorUI(AppConf appConf) { } /** - * + * * @param obj */ @SuppressWarnings("unchecked") @@ -281,7 +278,7 @@ public void addExperimentalData(Object obj) { /** - * + * * @param title * @param data */ @@ -373,7 +370,7 @@ protected JMenuItem[] additionalEditMenuItems() { } /** - * + * */ public void sendToGaruda() { if (simPanel != null) { @@ -456,7 +453,7 @@ protected JMenuItem[] additionalViewMenuItems() { /** * Cancels a running simulation. - * + * * @return */ public boolean stopSimulation() { @@ -477,9 +474,9 @@ public boolean closeFile() { } /** - * + * * @param onlyClosing whether or not this method is called with the purpose to open another model right afterwards. - * + * * @return */ private boolean closeFile(boolean onlyClosing) { @@ -566,7 +563,7 @@ protected Map getAlternativeBaseActionNames() { } /** - * + * * @return */ public Model getModel() { @@ -623,13 +620,14 @@ public File[] open(File... files) { } /** - * + * */ public File[] openFile() { SBPreferences prefs = SBPreferences.getPreferencesFor(getClass()); File[] modelFiles = GUITools.openFileDialog(this, prefs.get(GUIOptions.OPEN_DIR).toString(), false, false, JFileChooser.FILES_ONLY, SBFileFilter.createSBMLFileFilterList()); + return openFile(modelFiles); } @@ -641,6 +639,7 @@ protected File[] openFile(File... files) { File[] modelFiles = null; File[] dataFiles = null; + /* * Investigate the given files or let the user open a model and some data: */ @@ -688,6 +687,7 @@ protected File[] openFile(File... files) { EventHandler.create(PropertyChangeListener.class, this, "setSBMLDocument", "newValue")); worker.add(task1); + } catch (Exception exc) { GUITools.showErrorMessage(this, exc); } @@ -717,14 +717,14 @@ protected File[] openFile(File... files) { /** * Called when the EvA2 client is closing. - * + * * @param evaClient */ public void optimizationFinished(Object evaClient) { if (evaClient instanceof JFrame) { JFrame frame = (JFrame) evaClient; if ((frame.getName() != null) && !frame.isVisible() - && ((frame.getName().equals(Main.class.getSimpleName())) || (frame.getName().startsWith("frame")))) { + && (frame.getName().equals(Main.class.getSimpleName()))) { setSimulationAndOptimizationEnabled(true); } } @@ -842,7 +842,7 @@ public void optimize() { new Thread(new Runnable() { /* * (non-Javadoc) - * + * * @see java.lang.Runnable#run() */ @Override @@ -925,7 +925,7 @@ public File saveFileAs() { } /** - * + * * @param obj must be an instance of {@link SBMLDocument}. */ @SuppressWarnings("unchecked") @@ -1016,7 +1016,7 @@ public void setSelectedQuantities(String... ids) { /** * Small helper method that enables or disables all buttons and user * interfaces to launch optimization or simulation. - * + * * @param enabled */ private void setSimulationAndOptimizationEnabled(boolean enabled) { @@ -1027,7 +1027,7 @@ private void setSimulationAndOptimizationEnabled(boolean enabled) { } /** - * + * */ public void simulate() { try { diff --git a/src/org/sbml/simulator/gui/graph/AGraphManipulator.java b/src/org/sbml/simulator/gui/graph/AGraphManipulator.java index 5f7c6e7..2ad783c 100644 --- a/src/org/sbml/simulator/gui/graph/AGraphManipulator.java +++ b/src/org/sbml/simulator/gui/graph/AGraphManipulator.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -28,562 +26,603 @@ import org.sbml.jsbml.Reaction; import org.sbml.jsbml.SBMLDocument; +import de.zbit.graph.io.SBML2GraphML; +import de.zbit.graph.sbgn.FillLevelNodeRealizer; +import de.zbit.graph.sbgn.ReactionNodeRealizer; +import de.zbit.sbml.layout.y.ILayoutGraph; import y.base.Edge; import y.base.Node; import y.view.EdgeRealizer; import y.view.LineType; import y.view.NodeLabel; import y.view.NodeRealizer; -import de.zbit.graph.io.SBML2GraphML; -import de.zbit.graph.sbgn.ReactionNodeRealizer; -import de.zbit.sbml.layout.y.ILayoutGraph; /** * This class is an abstract graph manipulator, that provides some basic * functions and constants. Each {@link IGraphManipulator} should be derived * from this class. - * + * * @author Fabian Schwarzkopf - * @version $Rev$ */ public abstract class AGraphManipulator implements IGraphManipulator { - /** - * A {@link Logger} for this class. - */ - private static final transient Logger logger = Logger.getLogger(AGraphManipulator.class.getName()); - - /** - * Pointer to the graph. - */ - protected ILayoutGraph graph; - - /** - * Default node size to revert changes of nodes. Can be changed by derived - * classes. - */ - protected double REVERT_NODE_SIZE = 8; - - /** - * Default min/max node size for species. - */ - public static final double DEFAULT_MIN_NODE_SIZE = 8, DEFAULT_MAX_NODE_SIZE = 50; - - /** - * Default min/max line width for {@link Reaction}s. - */ - public static final float DEFAULT_MIN_LINEWIDTH = 1, DEFAULT_MAX_LINEWIDTH = 6; - - /** - * Saves mapping from reactionIDs to related reaction nodes. - */ - protected Map> reactionID2reactionNode; - - /** - * Saves mapping from species node to reaction node - */ - protected Map hiddenNodesForReaction; - protected Map> hiddenEdgesForSpecies; - - /** - * Saves mapping from speciesID to related species nodes. - */ - protected Map> id2speciesNode; - - /** - * Saves the used {@link SBMLDocument}. - */ - protected SBMLDocument document; - - /** - * Saves the used {@link DynamicCore}. - */ - protected DynamicCore core; - - /** - * Saves a mapping from every core element to it's specific min and max - * value. - */ - protected Map id2minMaxData; - - /** - * Saves minimum and maximum value of selected {@link Reaction}s to save - * computation time. - */ - protected double[] minMaxOfselectedReactions; - - /** - * Used line width for dynamic visualization of {@link Reaction}s. - */ - private float minLineWidth = DEFAULT_MIN_LINEWIDTH, - maxLineWidth = DEFAULT_MAX_LINEWIDTH; - - /** - * Constructs an abstract graph manipulator. - * @param layoutGraph - * @param document - * @param core - */ - public AGraphManipulator(ILayoutGraph layoutGraph, SBMLDocument document, DynamicCore core) { - this.graph = layoutGraph; - reactionID2reactionNode = new HashMap>(); - id2speciesNode = new HashMap>(); - hiddenEdgesForSpecies = new HashMap>(); - hiddenNodesForReaction = new HashMap(); - if (document.isSetModel()) { - id2speciesNode.putAll(layoutGraph.getSpeciesId2nodes()); - reactionID2reactionNode.putAll(layoutGraph.getReactionId2nodes()); - } - this.document = document; - this.core = core; - id2minMaxData = core.getId2minMaxData(); - } - - /** - * Constructs an abstract graph manipulator on the given - * {@link SBML2GraphML} and {@link SBMLDocument}. Additionally, this - * constructor provides a basic implementation of - * {@link #dynamicChangeOfReaction(String, double, boolean)} method with the - * given parameters. - * - * @param isbmlLayoutGraph - * @param document - * @param core - * @param selectedReactions - * @param reactionsMinLineWidth - * @param reactionsMaxLineWidth - */ - public AGraphManipulator(ILayoutGraph isbmlLayoutGraph, SBMLDocument document, - DynamicCore core, String[] selectedReactions, - float reactionsMinLineWidth, float reactionsMaxLineWidth) { - this(isbmlLayoutGraph, document, core); - - minMaxOfselectedReactions = core.getMinMaxOfIDs(selectedReactions); - this.minLineWidth = reactionsMinLineWidth; - this.maxLineWidth = reactionsMaxLineWidth; - } - - /** - * Maps the given value which has to be within [x1, x2] to codomain [y1, - * y2]. This is done implicit by a linear regression through the points (x1, - * y1) and (x2, y2). If x2 <= x1 (e.g., only one timepoint given) than a - * point in the middle of y1 and y2 will be returned. - * - * @param x1 - * @param x2 - * @param y1 - * @param y2 - * @param v - * @return - */ - protected double adjustValue(double x1, double x2, double y1, double y2, - double v) { - if (x2 <= x1) { - /* - * No proper limits given, return value inbetween codomain. - */ - return (y1 + y2) / 2.0d; - } - - return ((y2 - y1) / (x2 - x1)) * (v - x1) + y1; - } - - /* (non-Javadoc) - * @see org.sbml.simulator.gui.graph.IGraphManipulator#dynamicChangeOfReaction(java.lang.String, double) - */ - @Override - public void dynamicChangeOfReaction(String id, double value, boolean labels) { - Set processNodes = reactionID2reactionNode.get(id); - if ((processNodes != null) && (value != 0d)) { - float lineWidth = 1f; - for (Node pNode : processNodes) { - lineWidth = manipulateProcessNode(id, value, labels, pNode); - } - // edges line width - Set> edgeSets = graph.getReactionId2edges().get(id); - for (List edgeList : edgeSets) { - manipulateEdges(id, value, processNodes, lineWidth, edgeList); - } - graph.getGraph2D().updateViews(); - } else if ((processNodes != null) && (value == 0d)) { - revertChanges(id); - - logger.finer(MessageFormat.format( - "ReactionID: {0} value=0. Reverting id.", - new Object[] { id })); - - /* - * If labels are enable show them anyway. - */ - if (labels) { - for (Node pNode : reactionID2reactionNode.get(id)) { - ReactionNodeRealizer nr = (ReactionNodeRealizer) graph.getGraph2D().getRealizer(pNode); - labelNode(nr, id, value); - } - graph.getGraph2D().updateViews(); - } - } else if (processNodes == null) { - logger.finer(MessageFormat.format( - "No ReactionNodeRealizer for ReactionID: {0}", - new Object[] { id })); - } - } - - /** - * @param reactionID - * @param value - * @param processNodes - * @param lineWidth - * @param edgeList - */ - private void manipulateEdges(String reactionID, double value, Set processNodes, - float lineWidth, List edgeList) { - for (Edge edge : edgeList) { - EdgeRealizer edgeRealizer = graph.getGraph2D().getRealizer(edge); - - /* - * adjust lineWidth only if regression was computed, else use - * standard line width. - */ - // only line-width is supposed to change - LineType currLinetype = edgeRealizer.getLineType(); - LineType newLineType = LineType.createLineType(lineWidth, - currLinetype.getEndCap(), currLinetype.getLineJoin(), - currLinetype.getMiterLimit(), - currLinetype.getDashArray(), - currLinetype.getDashPhase()); - - edgeRealizer.setLineType(newLineType); - - /* - * determine arrow direction - */ - // TODO: This must depend on the original reaction! -// Reaction reaction = document.getModel().getReaction(reactionID); -// if (value > 0d) { // (!= 0), because simulation data at time point -// // 0.0 = 0 -// if (processNodes == edge.target()) { -// // reactants -// edgeRealizer.setSourceArrow(Arrow.NONE); -// // TODO own arrow for reversible -// // if (document.getModel().getReaction(id).isReversible()) { -// // er.setSourceArrow(Arrow.PLAIN); -// // } else { -// // er.setSourceArrow(Arrow.NONE); -// // } -// } else { -// // TODO: These can also be modifiers! -// // products -// edgeRealizer.setTargetArrow(Arrow.DELTA); -// } -// } else { -// if (processNodes == edge.target()) { -// // TODO: These can also be modifiers! -// // products -// edgeRealizer.setSourceArrow(Arrow.DELTA); -// } else { -// // reactants -// edgeRealizer.setTargetArrow(Arrow.NONE); -// // TODO own arrow for reversible -// // if (document.getModel().getReaction(id).isReversible()) { -// // er.setTargetArrow(Arrow.PLAIN); -// // } else { -// // er.setTargetArrow(Arrow.NONE); -// // } -// } -// } - } - } - - /** - * @param id - * @param value - * @param labels - * @param pNode - * @return used linewidth - */ - private float manipulateProcessNode(String id, double value, boolean labels, - Node pNode) { - ReactionNodeRealizer nr = (ReactionNodeRealizer) graph.getGraph2D().getRealizer(pNode); - // line width - double absvalue = Math.abs(value); - - /* - * Take absolute higher limit as xMax and 0 as xLow for regression. - * Eventually reactions will end up in equillibrium. - */ - double xHigh = - Math.abs(minMaxOfselectedReactions[0]) > Math.abs(minMaxOfselectedReactions[1]) ? - Math.abs(minMaxOfselectedReactions[0]) : - Math.abs(minMaxOfselectedReactions[1]); - float lineWidth = (float) adjustValue(0, xHigh, minLineWidth, maxLineWidth, absvalue); - logger.finer(MessageFormat - .format("Reaction {0}: Abs. value={1}, computes to line width={2}", - new Object[] { id, absvalue, lineWidth })); - - // ReactionNode line width - nr.setLineWidth(lineWidth); - /* - * Label Node with ID and real value at this timepoint. Last label - * will be treated as dynamic label - */ - if (labels) { - labelNode(nr, id, value); - } else if (nr.labelCount() > 1) { - // labels switched off, therefore remove them, if there are any - nr.removeLabel(nr.getLabel(nr.labelCount() - 1)); - } - return lineWidth; - } - - - /** - * Labels the given node of this {@link NodeRealizer} with the given ID and value. - * @param nr - * @param id - * @param value - */ - protected void labelNode(NodeRealizer nr, String id, double value) { - String name = ""; - if (document.getModel().getSpecies(id) != null) { - name = document.getModel().getSpecies(id).isSetName() ? document - .getModel().getSpecies(id).getName() : id; - } else if (document.getModel().getReaction(id) != null) { - name = document.getModel().getReaction(id).isSetName() ? document - .getModel().getReaction(id).getName() : id; - } - - String label = MessageFormat.format("{0}: {1,number,0.0000}", - new Object[] { name , value }); - - if (nr.labelCount() > 1) { - nr.getLabel(nr.labelCount() - 1).setText(label); - } else { - nr.addLabel(new NodeLabel(label)); - NodeLabel nl = nr.getLabel(nr.labelCount() - 1); - nl.setModel(NodeLabel.SIDES); - nl.setPosition(NodeLabel.S); // South of node - nl.setDistance(-3); - } - } - - /** - * Linear interpolation over two given colors. - * - * @param percent [0,1] - * @param RGBcolor1 low concentration (percent -> 0) - * @param RGBcolor2 high concentration (percent -> 1) - * @return - */ - protected int[] linearColorInterpolation(double percent, int[] RGBcolor1, - int[] RGBcolor2) { - - int[] outcolor = {0, 0, 0}; - if ((percent >= 0d) && (percent <= 1d)) { - for (int i = 0; i < outcolor.length; i++) { - outcolor[i] = (int) (RGBcolor1[i] * percent + RGBcolor2[i] - * (1 - percent)); - } - return outcolor; - } else if (percent > 1d) { - //maybe round-off error - return RGBcolor1; - } else { - //maybe round-off error - return RGBcolor2; - } - } - - - /** - * Linear interpolation over three given colors. - * - * @param percent [0,1] - * @param RGBcolor1 low concentration (percent -> 0) - * @param RGBcolor2 mid concentration - * @param RGBcolor3 high concentration (percent -> 1) - * @return - */ - protected int[] linearColorInterpolationForThree(double percent, - int[] RGBcolor1, int[] RGBcolor2, int[] RGBcolor3) { - - if ((percent >= 0d) && (percent <= 0.5d)) { - // color interpolation between color2 (mid concentration) and color3 - // (low concentration) - double resPercent = adjustValue(0, 0.5, 0, 1, percent); - return linearColorInterpolation(resPercent, RGBcolor2, RGBcolor3); - } else if ((percent > 0.5d) && (percent <= 1.0d)) { - //color interpolation between color1 (high concentration) and color2 (mid concentration) - double resPercent = adjustValue(0.5, 1, 0, 1, percent); - return linearColorInterpolation(resPercent, RGBcolor1, RGBcolor2); - } else if (percent > 1) { - // maybe round-off error - return RGBcolor1; - } else { - // maybe round-off error - return RGBcolor3; - } - } - - /* (non-Javadoc) - * @see org.sbml.simulator.gui.graph.IGraphManipulator#revertChanges(java.lang.String) - */ - @Override - public void revertChanges(String id) { - //revert nodes - if (id2speciesNode.get(id) != null) { - for (Node node : graph.getSpeciesId2nodes().get(id)) { - NodeRealizer nr = graph.getGraph2D().getRealizer(node); - double ratio = nr.getHeight() / nr.getWidth(); //keep ratio in case of elliptic nodes - nr.setSize(REVERT_NODE_SIZE, REVERT_NODE_SIZE*ratio); - nr.setFillColor(Color.LIGHT_GRAY); - - if (nr.labelCount() > 1) { - // if not selected disable label - nr.removeLabel(nr.getLabel(nr.labelCount() - 1)); - } - } - } - //revert reactions (lines and pseudonode) - if (graph.getReactionId2edges().get(id) != null) { - for (List listOfEdges : graph.getReactionId2edges().get(id)) { - for (Edge edge : listOfEdges) { - EdgeRealizer er = graph.getGraph2D().getRealizer(edge); - er.setLineType(LineType.LINE_1); - // TODO: This must depend on the original reaction! -// if (document.getModel().getReaction(id).isReversible()) { -// if (reactionID2reactionNode.get(id) == edge.target()) { -// er.setSourceArrow(Arrow.DELTA); -// } else { -// er.setTargetArrow(Arrow.DELTA); -// } -// } else { -// if (reactionID2reactionNode.get(id) == edge.target()) { -// er.setSourceArrow(Arrow.NONE); -// } else { -// er.setTargetArrow(Arrow.DELTA); -// } -// } - } - - if (reactionID2reactionNode.get(id) != null) { - for (Node pNode : reactionID2reactionNode.get(id)) { - ReactionNodeRealizer nr = (ReactionNodeRealizer) graph - .getGraph2D().getRealizer(pNode); - nr.setLineWidth(1); - if (nr.labelCount() > 1) { - // if not selected disable label - nr.removeLabel(nr.getLabel(nr.labelCount() - 1)); - } - } - } else { - logger.finer(MessageFormat.format( - "No ReactionNodeRealizer for ReactionID: {0}", - new Object[] { id })); - } - } - graph.getGraph2D().updateViews(); - } - } - - /* (non-Javadoc) - * @see org.sbml.simulator.gui.graph.IGraphManipulator#hide(y.base.Node, boolean) - */ - @Override - public void hide(String id, Node node, boolean b) { - // TODO! -// Graph2D graph2D = graph.getGraph2D(); -// assert node != null; -// if (b) { -// if (hiddenEdgesForSpecies.get(id) != null) return; //species already hidden -// logger.info("hiding " + id); -// // get reactions where id is necessary participant in -// // increase the hidden nodes count for this reactions -// // if the count is > 2 the reaction must be already hidden -// // save removed reaction-edges for later -// // remove process node -// // save out-edges of node for later -// // remove node -// Set hiddenEdges = new HashSet(); -// for (String reaction : graph.getSpeciesId2reactions().get(id)) { -// int count = incrementHiddenNodesCountFor(reaction); -// if (count < 2) { -// for (Node pNode : reactionID2reactionNode.get(reaction)) { -// for (EdgeCursor e = pNode.outEdges(); e.ok(); e.next()) { -// hiddenEdges.add((Edge) e.current()); -// } -// graph2D.removeNode(pNode); -// } -// } -// } -// for (EdgeCursor e = node.outEdges(); e.ok(); e.next()) { -// hiddenEdges.add((Edge) e.current()); -// } -// hiddenEdgesForSpecies.put(id, hiddenEdges); -// graph2D.removeNode(node); -// } -// else { -// if (hiddenEdgesForSpecies.get(id) == null) { -// return; //species wasn't hidden -// } -// logger.info("unhiding " + id); -// // retrieve node -// // decrement hiddenNodesForReaction count -// // traverse reactions for counts == 0 -// // retrieve pNode and Edges -// // reinsert node, pNode and Edges to graph -// // TODO Not tested because no matching model is available -// for (String reaction : graph.getSpeciesId2reactions().get(id)) { -// int count = decrementHiddenNodesCountFor(reaction); -// if (count == 0) { -// for (Node pNode : graph.getReactionId2nodes().get(reaction)) { -// graph2D.reInsertNode(pNode); -// } -// } -// } -// for (Node n : id2speciesNode.get(id)) { -// graph2D.reInsertNode(n); -// } -// for (Edge e : hiddenEdgesForSpecies.remove(id)) { -// graph2D.reInsertEdge(e); -// } -// } - } - - /** - * @param reaction - */ - private int incrementHiddenNodesCountFor(String reaction) { - if (hiddenNodesForReaction.get(reaction) == null) { - hiddenNodesForReaction.put(reaction, new Integer(1)); - return 1; - } - else { - int i = hiddenNodesForReaction.get(reaction) + 1; - hiddenNodesForReaction.put(reaction, i); - return i; - } - } - - /** - * @param reaction - */ - private int decrementHiddenNodesCountFor(String reaction) { - assert hiddenNodesForReaction.get(reaction) != null; - int i = hiddenNodesForReaction.get(reaction) - 1; - hiddenNodesForReaction.put(reaction, i); - return i; - } - - /** - * - * @param value - * @return - */ - protected boolean isInvisible(double value) { - return Math.abs(value) < 1e-7d; - } + /** + * A {@link Logger} for this class. + */ + private static final transient Logger logger = Logger.getLogger(AGraphManipulator.class.getName()); + + /** + * Pointer to the graph. + */ + protected ILayoutGraph graph; + + /** + * Default node size to revert changes of nodes. Can be changed by derived + * classes. + */ + protected double REVERT_NODE_SIZE = 30; + + /** + * Default min/max node size for species. + */ + public static final double DEFAULT_MIN_NODE_SIZE = 8, DEFAULT_MAX_NODE_SIZE = 50; + + /** + * Default min/max line width for {@link Reaction}s. + */ + public static final float DEFAULT_MIN_LINEWIDTH = 1, DEFAULT_MAX_LINEWIDTH = 6; + + /** + * Saves mapping from reactionIDs to related reaction nodes. + */ + protected Map> reactionID2reactionNode; + + /** + * Saves mapping from species node to reaction node + */ + protected Map hiddenNodesForReaction; + protected Map> hiddenEdgesForSpecies; + + /** + * Saves mapping from speciesID to related species nodes. + */ + protected Map> id2speciesNode; + + /* + * Remembers the 2 different Realizers to each node + */ + protected static final Map node2Realizer = new HashMap(); + protected static final Map node2FillRealizer = new HashMap(); + + /** + * Saves the used {@link SBMLDocument}. + */ + protected SBMLDocument document; + + /** + * Saves the used {@link DynamicCore}. + */ + protected DynamicCore core; + + /** + * Saves a mapping from every core element to it's specific min and max + * value. + */ + protected Map id2minMaxData; + + /** + * Saves minimum and maximum value of selected {@link Reaction}s to save + * computation time. + */ + protected double[] minMaxOfselectedReactions; + + /** + * Used line width for dynamic visualization of {@link Reaction}s. + */ + private float minLineWidth = DEFAULT_MIN_LINEWIDTH, + maxLineWidth = DEFAULT_MAX_LINEWIDTH; + + /** + * Constructs an abstract graph manipulator. + * @param layoutGraph + * @param document + * @param core + */ + public AGraphManipulator(ILayoutGraph layoutGraph, SBMLDocument document, DynamicCore core) { + this.graph = layoutGraph; + reactionID2reactionNode = new HashMap>(); + id2speciesNode = new HashMap>(); + hiddenEdgesForSpecies = new HashMap>(); + hiddenNodesForReaction = new HashMap(); + if (document.isSetModel()) { + id2speciesNode.putAll(layoutGraph.getSpeciesId2nodes()); + reactionID2reactionNode.putAll(layoutGraph.getReactionId2nodes()); + } + this.document = document; + this.core = core; + id2minMaxData = core.getId2minMaxData(); + } + + /** + * Constructs an abstract graph manipulator on the given + * {@link SBML2GraphML} and {@link SBMLDocument}. Additionally, this + * constructor provides a basic implementation of + * {@link #dynamicChangeOfReaction(String, double, boolean)} method with the + * given parameters. + * + * @param isbmlLayoutGraph + * @param document + * @param core + * @param selectedReactions + * @param reactionsMinLineWidth + * @param reactionsMaxLineWidth + */ + public AGraphManipulator(ILayoutGraph isbmlLayoutGraph, SBMLDocument document, + DynamicCore core, String[] selectedReactions, + float reactionsMinLineWidth, float reactionsMaxLineWidth) { + this(isbmlLayoutGraph, document, core); + + minMaxOfselectedReactions = core.getMinMaxOfIDs(selectedReactions); + this.minLineWidth = reactionsMinLineWidth; + this.maxLineWidth = reactionsMaxLineWidth; + } + + /** + * Maps the given value which has to be within [x1, x2] to codomain [y1, + * y2]. This is done implicit by a linear regression through the points (x1, + * y1) and (x2, y2). If x2 <= x1 (e.g., only one timepoint given) than a + * point in the middle of y1 and y2 will be returned. + * + * @param x1 + * @param x2 + * @param y1 + * @param y2 + * @param v + * @return + */ + protected double adjustValue(double x1, double x2, double y1, double y2, + double v) { + if (x2 <= x1) { + /* + * No proper limits given, return value inbetween codomain. + */ + return (y1 + y2) / 2.0d; + } + + return (((y2 - y1) / (x2 - x1)) * (v - x1)) + y1; + } + + /* (non-Javadoc) + * @see org.sbml.simulator.gui.graph.IGraphManipulator#dynamicChangeOfReaction(java.lang.String, double) + */ + @Override + public void dynamicChangeOfReaction(String id, double value, boolean labels) { + Set processNodes = reactionID2reactionNode.get(id); + if ((processNodes != null) && (value != 0d)) { + float lineWidth = 1f; + for (Node pNode : processNodes) { + lineWidth = manipulateProcessNode(id, value, labels, pNode); + } + // edges line width + Set> edgeSets = graph.getReactionId2edges().get(id); + for (List edgeList : edgeSets) { + manipulateEdges(id, value, processNodes, lineWidth, edgeList); + } + graph.getGraph2D().updateViews(); + } else if ((processNodes != null) && (value == 0d)) { + revertChanges(id); + + logger.finer(MessageFormat.format( + "ReactionID: {0} value=0. Reverting id.", + new Object[] { id })); + + /* + * If labels are enable show them anyway. + */ + if (labels) { + for (Node pNode : reactionID2reactionNode.get(id)) { + ReactionNodeRealizer nr = (ReactionNodeRealizer) graph.getGraph2D().getRealizer(pNode); + labelNode(nr, id, value); + } + graph.getGraph2D().updateViews(); + } + } else if (processNodes == null) { + logger.finer(MessageFormat.format( + "No ReactionNodeRealizer for ReactionID: {0}", + new Object[] { id })); + } + } + + /** + * @param reactionID + * @param value + * @param processNodes + * @param lineWidth + * @param edgeList + */ + private void manipulateEdges(String reactionID, double value, Set processNodes, + float lineWidth, List edgeList) { + for (Edge edge : edgeList) { + EdgeRealizer edgeRealizer = graph.getGraph2D().getRealizer(edge); + + /* + * adjust lineWidth only if regression was computed, else use + * standard line width. + */ + // only line-width is supposed to change + LineType currLinetype = edgeRealizer.getLineType(); + LineType newLineType = LineType.createLineType(lineWidth, + currLinetype.getEndCap(), currLinetype.getLineJoin(), + currLinetype.getMiterLimit(), + currLinetype.getDashArray(), + currLinetype.getDashPhase()); + + edgeRealizer.setLineType(newLineType); + + /* + * determine arrow direction + */ + // TODO: This must depend on the original reaction! + // Reaction reaction = document.getModel().getReaction(reactionID); + // if (value > 0d) { // (!= 0), because simulation data at time point + // // 0.0 = 0 + // if (processNodes == edge.target()) { + // // reactants + // edgeRealizer.setSourceArrow(Arrow.NONE); + // // TODO own arrow for reversible + // // if (document.getModel().getReaction(id).isReversible()) { + // // er.setSourceArrow(Arrow.PLAIN); + // // } else { + // // er.setSourceArrow(Arrow.NONE); + // // } + // } else { + // // TODO: These can also be modifiers! + // // products + // edgeRealizer.setTargetArrow(Arrow.DELTA); + // } + // } else { + // if (processNodes == edge.target()) { + // // TODO: These can also be modifiers! + // // products + // edgeRealizer.setSourceArrow(Arrow.DELTA); + // } else { + // // reactants + // edgeRealizer.setTargetArrow(Arrow.NONE); + // // TODO own arrow for reversible + // // if (document.getModel().getReaction(id).isReversible()) { + // // er.setTargetArrow(Arrow.PLAIN); + // // } else { + // // er.setTargetArrow(Arrow.NONE); + // // } + // } + // } + } + } + + /** + * @param id + * @param value + * @param labels + * @param pNode + * @return used linewidth + */ + private float manipulateProcessNode(String id, double value, boolean labels, + Node pNode) { + ReactionNodeRealizer nr = (ReactionNodeRealizer) graph.getGraph2D().getRealizer(pNode); + // line width + double absvalue = Math.abs(value); + + /* + * Take absolute higher limit as xMax and 0 as xLow for regression. + * Eventually reactions will end up in equillibrium. + */ + double xHigh = + Math.abs(minMaxOfselectedReactions[0]) > Math.abs(minMaxOfselectedReactions[1]) ? + Math.abs(minMaxOfselectedReactions[0]) : + Math.abs(minMaxOfselectedReactions[1]); + float lineWidth = (float) adjustValue(0, xHigh, minLineWidth, maxLineWidth, absvalue); + logger.finer(MessageFormat + .format("Reaction {0}: Abs. value={1}, computes to line width={2}", + new Object[] { id, absvalue, lineWidth })); + + // ReactionNode line width + nr.setLineWidth(lineWidth); + /* + * Label Node with ID and real value at this timepoint. Last label + * will be treated as dynamic label + */ + if (labels) { + labelNode(nr, id, value); + } else if (nr.labelCount() > 1) { + // labels switched off, therefore remove them, if there are any + nr.removeLabel(nr.getLabel(nr.labelCount() - 1)); + } + return lineWidth; + } + + + /** + * Labels the given node of this {@link NodeRealizer} with the given ID and value. + * @param nr + * @param id + * @param value + */ + protected void labelNode(NodeRealizer nr, String id, double value) { + String name = ""; + if (document.getModel().getSpecies(id) != null) { + name = document.getModel().getSpecies(id).isSetName() ? document + .getModel().getSpecies(id).getName() : id; + } else if (document.getModel().getReaction(id) != null) { + name = document.getModel().getReaction(id).isSetName() ? document + .getModel().getReaction(id).getName() : id; + } + + String label = MessageFormat.format("{0}: {1,number,0.0000}", + new Object[] { name , value }); + + if (nr.labelCount() > 1) { + nr.getLabel(nr.labelCount() - 1).setText(label); + } else { + nr.addLabel(new NodeLabel(label)); + NodeLabel nl = nr.getLabel(nr.labelCount() - 1); + nl.setModel(NodeLabel.SIDES); + nl.setPosition(NodeLabel.S); // South of node + nl.setDistance(-3); + } + } + + /** + * Linear interpolation over two given colors. + * + * @param percent [0,1] + * @param RGBcolor1 low concentration (percent -> 0) + * @param RGBcolor2 high concentration (percent -> 1) + * @return + */ + protected int[] linearColorInterpolation(double percent, int[] RGBcolor1, + int[] RGBcolor2) { + + int[] outcolor = {0, 0, 0}; + if ((percent >= 0d) && (percent <= 1d)) { + for (int i = 0; i < outcolor.length; i++) { + outcolor[i] = (int) ((RGBcolor1[i] * percent) + (RGBcolor2[i] + * (1 - percent))); + } + return outcolor; + } else if (percent > 1d) { + //maybe round-off error + return RGBcolor1; + } else { + //maybe round-off error + return RGBcolor2; + } + } + + + /** + * Linear interpolation over three given colors. + * + * @param percent [0,1] + * @param RGBcolor1 low concentration (percent -> 0) + * @param RGBcolor2 mid concentration + * @param RGBcolor3 high concentration (percent -> 1) + * @return + */ + protected int[] linearColorInterpolationForThree(double percent, + int[] RGBcolor1, int[] RGBcolor2, int[] RGBcolor3) { + + if ((percent >= 0d) && (percent <= 0.5d)) { + // color interpolation between color2 (mid concentration) and color3 + // (low concentration) + double resPercent = adjustValue(0, 0.5, 0, 1, percent); + return linearColorInterpolation(resPercent, RGBcolor2, RGBcolor3); + } else if ((percent > 0.5d) && (percent <= 1.0d)) { + //color interpolation between color1 (high concentration) and color2 (mid concentration) + double resPercent = adjustValue(0.5, 1, 0, 1, percent); + return linearColorInterpolation(resPercent, RGBcolor1, RGBcolor2); + } else if (percent > 1) { + // maybe round-off error + return RGBcolor1; + } else { + // maybe round-off error + return RGBcolor3; + } + } + + /** + * Calculates the correct starting degree and the range of degrees for the arc + */ + protected int[] degreeInterpolationForFillingLevel(double percent) { + if (percent == 0) { + return new int[] { 270 , 360 }; // concentration is 0 + } else if (percent == 1) { + return new int[] { 90 , 0 }; // concentration is 1 + } else if ((percent > 0) && (percent <= 0.5)) { + double degreeStart = adjustValue(0, 0.5, 0, 90, percent); + int start = (int) (360-(90-Math.round(degreeStart))); + int howBig = (int) (360-(2*Math.round(degreeStart))); + return new int[] { start, howBig }; + } else if ((percent < 1) && (percent > 0.5)) { + double degreeStart = adjustValue(0.5, 1, 0, 90, percent); + int start = (int) Math.round(degreeStart); + int howBig = (int) (2*(90-Math.round(degreeStart))); + return new int[] { start, howBig }; + } + return null; + } + + public Color[] calculateColorsFromDefault(Color color2) { + int r3 = (int) (((255 - color2.getRed()) * 0.4) + color2.getRed()); + int g3 = (int) (((255 - color2.getGreen()) * 0.4) + color2.getGreen()); + int b3 = (int) (((255 - color2.getBlue()) * 0.4) + color2.getBlue()); + Color color3 = new Color( r3, g3, b3 ); + // adds 50% grey to the color (high concentration) + int r1 = (int) (((0 - color2.getRed()) * 0.4) + color2.getRed()); + int g1 = (int) (((0 - color2.getGreen()) * 0.4) + color2.getGreen()); + int b1 = (int) (((0 - color2.getBlue()) * 0.4) + color2.getBlue()); + Color color1 = new Color( r1 , g1 , b1 ); + return new Color[] { color3 , color1 }; + } + + /* (non-Javadoc) + * @see org.sbml.simulator.gui.graph.IGraphManipulator#revertChanges(java.lang.String) + */ + @Override + public void revertChanges(String id) { + //revert nodes + if (id2speciesNode.get(id) != null) { + for (Node node : graph.getSpeciesId2nodes().get(id)) { + NodeRealizer nr = graph.getGraph2D().getRealizer(node); + double ratio = nr.getHeight() / nr.getWidth(); //keep ratio in case of elliptic nodes + nr.setSize(REVERT_NODE_SIZE, REVERT_NODE_SIZE*ratio); + nr.setFillColor(Color.LIGHT_GRAY); + + if (nr.labelCount() > 1) { + // if not selected disable label + nr.removeLabel(nr.getLabel(nr.labelCount() - 1)); + } + } + } + //revert reactions (lines and pseudonode) + if (graph.getReactionId2edges().get(id) != null) { + for (List listOfEdges : graph.getReactionId2edges().get(id)) { + for (Edge edge : listOfEdges) { + EdgeRealizer er = graph.getGraph2D().getRealizer(edge); + er.setLineType(LineType.LINE_1); + // TODO: This must depend on the original reaction! + // if (document.getModel().getReaction(id).isReversible()) { + // if (reactionID2reactionNode.get(id) == edge.target()) { + // er.setSourceArrow(Arrow.DELTA); + // } else { + // er.setTargetArrow(Arrow.DELTA); + // } + // } else { + // if (reactionID2reactionNode.get(id) == edge.target()) { + // er.setSourceArrow(Arrow.NONE); + // } else { + // er.setTargetArrow(Arrow.DELTA); + // } + // } + } + + if (reactionID2reactionNode.get(id) != null) { + for (Node pNode : reactionID2reactionNode.get(id)) { + ReactionNodeRealizer nr = (ReactionNodeRealizer) graph + .getGraph2D().getRealizer(pNode); + nr.setLineWidth(1); + if (nr.labelCount() > 1) { + // if not selected disable label + nr.removeLabel(nr.getLabel(nr.labelCount() - 1)); + } + } + } else { + logger.finer(MessageFormat.format( + "No ReactionNodeRealizer for ReactionID: {0}", + new Object[] { id })); + } + } + graph.getGraph2D().updateViews(); + } + } + + /* (non-Javadoc) + * @see org.sbml.simulator.gui.graph.IGraphManipulator#hide(y.base.Node, boolean) + */ + @Override + public void hide(String id, Node node, boolean b) { + // TODO! + // Graph2D graph2D = graph.getGraph2D(); + // assert node != null; + // if (b) { + // if (hiddenEdgesForSpecies.get(id) != null) return; //species already hidden + // logger.info("hiding " + id); + // // get reactions where id is necessary participant in + // // increase the hidden nodes count for this reactions + // // if the count is > 2 the reaction must be already hidden + // // save removed reaction-edges for later + // // remove process node + // // save out-edges of node for later + // // remove node + // Set hiddenEdges = new HashSet(); + // for (String reaction : graph.getSpeciesId2reactions().get(id)) { + // int count = incrementHiddenNodesCountFor(reaction); + // if (count < 2) { + // for (Node pNode : reactionID2reactionNode.get(reaction)) { + // for (EdgeCursor e = pNode.outEdges(); e.ok(); e.next()) { + // hiddenEdges.add((Edge) e.current()); + // } + // graph2D.removeNode(pNode); + // } + // } + // } + // for (EdgeCursor e = node.outEdges(); e.ok(); e.next()) { + // hiddenEdges.add((Edge) e.current()); + // } + // hiddenEdgesForSpecies.put(id, hiddenEdges); + // graph2D.removeNode(node); + // } + // else { + // if (hiddenEdgesForSpecies.get(id) == null) { + // return; //species wasn't hidden + // } + // logger.info("unhiding " + id); + // // retrieve node + // // decrement hiddenNodesForReaction count + // // traverse reactions for counts == 0 + // // retrieve pNode and Edges + // // reinsert node, pNode and Edges to graph + // // TODO Not tested because no matching model is available + // for (String reaction : graph.getSpeciesId2reactions().get(id)) { + // int count = decrementHiddenNodesCountFor(reaction); + // if (count == 0) { + // for (Node pNode : graph.getReactionId2nodes().get(reaction)) { + // graph2D.reInsertNode(pNode); + // } + // } + // } + // for (Node n : id2speciesNode.get(id)) { + // graph2D.reInsertNode(n); + // } + // for (Edge e : hiddenEdgesForSpecies.remove(id)) { + // graph2D.reInsertEdge(e); + // } + // } + } + + /** + * @param reaction + */ + private int incrementHiddenNodesCountFor(String reaction) { + if (hiddenNodesForReaction.get(reaction) == null) { + hiddenNodesForReaction.put(reaction, new Integer(1)); + return 1; + } + else { + int i = hiddenNodesForReaction.get(reaction) + 1; + hiddenNodesForReaction.put(reaction, i); + return i; + } + } + + /** + * @param reaction + */ + private int decrementHiddenNodesCountFor(String reaction) { + assert hiddenNodesForReaction.get(reaction) != null; + int i = hiddenNodesForReaction.get(reaction) - 1; + hiddenNodesForReaction.put(reaction, i); + return i; + } + + /** + * + * @param value + * @return + */ + protected boolean isInvisible(double value) { + return Math.abs(value) < 1e-7d; + } } diff --git a/src/org/sbml/simulator/gui/graph/ButtonPressed.java b/src/org/sbml/simulator/gui/graph/ButtonPressed.java new file mode 100644 index 0000000..4d9ffbf --- /dev/null +++ b/src/org/sbml/simulator/gui/graph/ButtonPressed.java @@ -0,0 +1,53 @@ +package org.sbml.simulator.gui.graph; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; + +import javax.swing.JFileChooser; + +/** + * This class deals with the Buttons of the GUI of {@link TestCycleArranging}. The given Inputs are .txt files of + * ReactionGlyphs and SpeciesGlyphs + * + * @author Lea Buchweitz + */ +public class ButtonPressed implements ActionListener { + + public List elements = new LinkedList(); + public File file; + + @Override + public void actionPerformed(ActionEvent e) + { + JFileChooser fileChooser = new JFileChooser(); + FileReader fr; + BufferedReader br; + + if(fileChooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) + { + file = fileChooser.getSelectedFile(); + try { + fr = new FileReader(file); + br = new BufferedReader(fr); + + String line; + while((line = br.readLine()) != null) + { + elements.add(line); + } + } catch (IOException e2) + { + e2.printStackTrace(); + } + + TestCycleArranging.allInfos++; + } + } + +} diff --git a/src/org/sbml/simulator/gui/graph/CameraAnimationView.java b/src/org/sbml/simulator/gui/graph/CameraAnimationView.java new file mode 100644 index 0000000..b967e98 --- /dev/null +++ b/src/org/sbml/simulator/gui/graph/CameraAnimationView.java @@ -0,0 +1,396 @@ +package org.sbml.simulator.gui.graph; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileNotFoundException; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Scanner; +import java.util.logging.Logger; + +import org.sbml.jsbml.ext.layout.Point; +import org.sbml.simulator.gui.graph.DynamicView.Manipulators; +import org.simulator.math.odes.MultiTable; + +import de.zbit.graph.sbgn.FillLevelNodeRealizer; +import de.zbit.graph.sbgn.ShapeNodeRealizerSupportingCloneMarker; +import de.zbit.io.filefilter.SBFileFilter; +import de.zbit.util.prefs.SBPreferences; +import y.base.Node; +import y.view.Graph2D; +import y.view.Graph2DView; +import y.view.NodeRealizer; +import y.view.ShapeNodeRealizer; + +/** + * class that reads out the {@link GraphOptions.CAMERA_WAY_FILE} .csv file with the animation data for the + * camera and calculates the animation for the next simulation or export of a video + * + * @author Lea Buchweitz + * + */ + +/* + * .csv File: Coordinates in one line, coordinates separated by "," elements separated by tab + * 1) Zoom of camera + * 2) Start point of animation + * 3)... All points on the animation way + * last: End point of animation + */ +public class CameraAnimationView implements IDynamicGraph { + + /** + * A {@link Logger} for this class. + */ + private static final transient Logger logger = Logger.getLogger(CameraAnimationView.class.getName()); + + /** + * Displayed 2D graph which is set in {@link DynamicCore} when camera animation should be displayed + */ + private static Graph2D graph; + + /** + * saves all points for camera animation way + */ + private List points = new LinkedList(); + + /** + * core to unset this view + */ + protected DynamicCore core; + + /** + * current .csv file to check if a new one was loaded + */ + private String currentCSV; + + /** + * zoom amount to set back + */ + private double DEFAULT_ZOOM = 0.060361216730038025; + + /** + * zoom level of the .csv file + */ + private double ZOOM_FROM_FILE; + + /** + * position in the beginning of the simulation to set back + */ + private java.awt.Point DEFAULT_POSITION; + + /** + * number of timesteps for one point to another, dependent on the number of points of the camera animation + */ + private double timeFromPointToPoint; + + /** + * maxTime of simulation + */ + private double maxTime; + + /** + * counter for the correct points + */ + private int counter = 0; + + /** + * to which pixel size the nodes are changed during the overview animation + */ + protected int overviewSize = 155; + + /** + * list with all timesteps when the way of the camera animation changes to another point + */ + private List moveTowardsNextPoint = new LinkedList(); + + private static List activeRealizerList = new LinkedList(); + + /** + * prefs to get all infos about what to display (i.e. loop {@link DynamicCore} for longer simulation) + */ + private SBPreferences prefs = SBPreferences.getPreferencesFor(GraphOptions.class); + + public CameraAnimationView() { + + currentCSV = GraphOptions.CAMERA_WAY_FILE.getValue( + SBPreferences.getPreferencesFor(GraphOptions.class)).toString(); + + if(!currentCSV.equals(GraphOptions.CAMERA_WAY_FILE.getDefaultValue().toString())) + { + points.clear(); + points = getPointsFromCSV(prefs.getFile(GraphOptions.CAMERA_WAY_FILE)); + } + } + + @Override + public void donePlay() { + } + + // Does not exist for this view, just for animation + @Override + public BufferedImage takeGraphshot(int width, int height) { + return null; + } + + @Override + public void updateGraph(double timepoint, MultiTable updateThem) { + + if(!core.playAgain) { + + if (graph.getViews().current() instanceof Graph2DView) { + + if(((Graph2DView) graph.getViews().current()).getZoom() != ZOOM_FROM_FILE) { + ((Graph2DView) graph.getViews().current()).setZoom(ZOOM_FROM_FILE); + } + + if(timepoint >= moveTowardsNextPoint.get(counter)) { + if(moveTowardsNextPoint.size() >= (counter+2)) { + counter++; + } else { + setCounterBack(); + return; + } + } + + Point newPos = interpolatePosition(timepoint, points.get(counter), points.get(counter+1)); + ((Graph2DView) graph.getViews().current()).setViewPoint((int)newPos.x(), (int)newPos.y()); + } + } + } + + public void setGraph(Graph2D graph) { + this.graph = graph; + } + + public Graph2D getGraph() { + return graph; + } + + /** + * sets the view of the camera animation to the given parameter in the csv + */ + public void setZoom() { + //System.out.println(((Graph2DView) graph.getViews().current()).getZoom()); + ((Graph2DView) graph.getViews().current()).setZoom(ZOOM_FROM_FILE); + } + + public void setTimeLine(double maxTime) { + this.maxTime = maxTime; + moveTowardsNextPoint = calculateWindowPositions(maxTime, points); + } + + public void setCore(DynamicCore core) { + this.core = core; + } + + public void setDefaultPosition(Graph2D graph) { + DEFAULT_POSITION = ((Graph2DView) graph.getViews().current()).getViewPoint(); + DEFAULT_ZOOM = ((Graph2DView) graph.getViews().current()).getZoom(); + } + + public void setCounterBack() { + counter = 0; + } + + /** + * gets all timeSteps which will be fired from {@link DynamicCore} and calculates which point has to be + * reached at what timeStep in the camera animation + * + * @param timePoint + * @param points + */ + private List calculateWindowPositions(double maxTime, List points) { + timeFromPointToPoint = maxTime / (points.size()-1); + + List timePoints = new LinkedList(); + while(maxTime > 0) { + timePoints.add(maxTime); + maxTime -= timeFromPointToPoint; + } + + Collections.reverse(timePoints); + + return timePoints; + } + + /** + * calulates the position of the window of each timepoint, given a start and an end point to interpolate + * between + * + * @param currentStep + * @param start + * @param end + * @return + */ + private Point interpolatePosition(double currentStep, Point start, Point end) { + Point direction = new Point(end.x()-start.x(),end.y()-start.y()); + return new Point(Math.round(start.x()+(((currentStep%timeFromPointToPoint)/ + timeFromPointToPoint)*direction.x())), + Math.round(start.y()+(((currentStep%timeFromPointToPoint)/ + timeFromPointToPoint)*direction.y()))); + } + + /** + * checks if another csv file was loaded and gets the point from it + */ + public void checkForNewFile() { + // if csv file is not the one loaded and not the default value + if(!GraphOptions.CAMERA_WAY_FILE.getValue(SBPreferences.getPreferencesFor(GraphOptions.class)). + toString().equals(currentCSV) + && !GraphOptions.CAMERA_WAY_FILE.getValue(SBPreferences.getPreferencesFor(GraphOptions.class)). + toString().equals(GraphOptions.CAMERA_WAY_FILE.getDefaultValue().toString())) + { + points.clear(); + points = getPointsFromCSV(prefs.getFile(GraphOptions.CAMERA_WAY_FILE)); + setTimeLine(maxTime); + counter = 0; + currentCSV = GraphOptions.CAMERA_WAY_FILE.getValue( + SBPreferences.getPreferencesFor(GraphOptions.class)).toString(); + } + } + + /** + * gets the zoom factor and the points of the given csv file + * @param csv + * @return + */ + public List getPointsFromCSV(File csv) { + LinkedList tmpCSVData = new LinkedList(); + if(SBFileFilter.isCSVFile(csv)) { + try { + Scanner inputStream = new Scanner(csv); + while(inputStream.hasNext()) { + tmpCSVData.add(inputStream.next()); + } + inputStream.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + return null; + } + } + + if(!tmpCSVData.isEmpty()) { + ZOOM_FROM_FILE = Double.parseDouble(tmpCSVData.removeFirst()); + + while(!tmpCSVData.isEmpty()) { + String[] parts = tmpCSVData.removeFirst().split(","); + points.add(new Point(Double.parseDouble(parts[0]), Double.parseDouble(parts[1]))); + } + } + return points; + } + + + private double[] resetMinMaxSize; + private static double[] resetSize = new double[] { -1 , -1}; + private static List listOfResetSizes = new LinkedList(); + private Collection collection; + private Collection collectionFillLevel; + + /** + * shows the first loop of simulation just as an overview which metabolites are included + * and where they are + */ + protected void showOverviewAnimation() { + + activeRealizerList.clear(); + listOfResetSizes.clear(); + + graph.fitGraph2DView(); + + String visualizationMode = SBPreferences.getPreferencesFor(GraphOptions.class).get(GraphOptions.VISUALIZATION_STYLE); + Manipulators currentManipulator = Manipulators.getManipulator(visualizationMode); + + collection = null; + collectionFillLevel = null; + + if (currentManipulator.name().equals("FILL_LEVEL")) { + Map node2FillRealizerClone = AGraphManipulator.node2FillRealizer; + ((HashMap) node2FillRealizerClone).clone(); + collectionFillLevel = node2FillRealizerClone.values(); + } else { + Map node2RealizerClone = AGraphManipulator.node2Realizer; + ((HashMap) node2RealizerClone).clone(); + collection = node2RealizerClone.values(); + } + + if(collectionFillLevel != null) { + for(NodeRealizer nr : collectionFillLevel) { + if(nr instanceof FillLevelNodeRealizer) { + activeRealizerList.add((ShapeNodeRealizer)nr); + if((resetSize[0] == -1) && (resetSize[1] == -1)) { + resetSize = ((FillLevelNodeRealizer) nr).getSize(); + } + } + nr.setSize(overviewSize, overviewSize); + } + } else { + for(NodeRealizer nr : collection) { + if(nr instanceof ShapeNodeRealizerSupportingCloneMarker) { + activeRealizerList.add((ShapeNodeRealizer)nr); + + if(currentManipulator.name().equals("NODECOLOR_AND_SIZE") || + currentManipulator.name().equals("NODESIZE") || + currentManipulator.name().equals("NODESIZE_AND_COLOR")) { + listOfResetSizes.add(((ShapeNodeRealizerSupportingCloneMarker) nr).getSize()); + } else { + if((resetSize[0] == -1) && (resetSize[1] == -1)) { + resetSize = ((ShapeNodeRealizerSupportingCloneMarker) nr).getSize(); + } + } + } + nr.setSize(overviewSize, overviewSize); + } + } + graph.updateViews(); + } + + /** + * resizes the nodes for the second loop of simulation + */ + public static void resizeNodes() { + + if(listOfResetSizes.isEmpty()) { + for(ShapeNodeRealizer nr : activeRealizerList) { + nr.setSize(resetSize[0],resetSize[1]); + } + } else { + for(int i = 0 ; i < activeRealizerList.size() ; i++) { + activeRealizerList.get(i).setSize(listOfResetSizes.get(i)[0], listOfResetSizes.get(i)[1]); + } + } + graph.updateViews(); + } + + /** + * resets the simulation to another loop start + */ + public void resetToNextSimulationLoop() { + + core.playAgain = true; + } + + /** + * resets all values back so that the animation can start again + */ + protected void resetCameraAnimation() { + counter = 0; + + if(!prefs.getBoolean(GraphOptions.CYCLE_SIMULATION)) { + ((Graph2DView) graph.getViews().current()).setZoom(DEFAULT_ZOOM); + if(DEFAULT_POSITION == null) { + graph.fitGraph2DView(); + } else { + ((Graph2DView) graph.getViews().current()).setViewPoint((int)DEFAULT_POSITION.getX(), (int)DEFAULT_POSITION.getY()); + } + } + + graph.updateViews(); + } + +} diff --git a/src/org/sbml/simulator/gui/graph/ConcentrationGraphUI.java b/src/org/sbml/simulator/gui/graph/ConcentrationGraphUI.java new file mode 100644 index 0000000..3014e63 --- /dev/null +++ b/src/org/sbml/simulator/gui/graph/ConcentrationGraphUI.java @@ -0,0 +1,136 @@ +package org.sbml.simulator.gui.graph; + +import java.awt.BasicStroke; +import java.awt.BorderLayout; +import java.awt.Color; +import java.util.Arrays; +import java.util.List; +import java.util.ResourceBundle; + +import javax.swing.ImageIcon; +import javax.swing.JFrame; +import javax.swing.JPanel; + +import org.jfree.chart.axis.LogarithmicAxis; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.plot.ValueMarker; +import org.jfree.chart.plot.XYPlot; +import org.sbml.simulator.gui.LegendPanel; +import org.sbml.simulator.gui.SimulatorUI; +import org.sbml.simulator.gui.plot.BoxPlotDataset; +import org.sbml.simulator.gui.plot.MetaDataset; +import org.sbml.simulator.gui.plot.Plot; +import org.sbml.simulator.gui.plot.XYDatasetAdapter; +import org.sbml.simulator.gui.table.LegendTableModel; +import org.simulator.math.odes.MultiTable; + +import de.zbit.sbml.util.HTMLtools; +import de.zbit.util.ResourceManager; + +/** + * This class opens a small window where all the concentrations of all species are shown. A red line is + * passing the timepoints to give a better overvier over the different concentrations at a time. + * It's opened by clicking an imagebutton in the graph view. + * + * @author Lea Buchweitz + */ + +public class ConcentrationGraphUI extends JFrame { + + private List graphData; + + private Plot concentrationGraph; + + private JPanel graphPanel = new JPanel(); + + private double timepoint = 0; + + private XYPlot plot; + + /** + * Localization support. + */ + private static final transient ResourceBundle bundle = ResourceManager + .getBundle("org.sbml.simulator.gui.graph.DynamicGraph"); + + + public ConcentrationGraphUI(MultiTable data, LegendPanel legend, double[] minMax, double maxTime) { + super(); + + setResizable(true); + setSize(400,400); + setLocation(5,10); + setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + + setTitle(bundle.getString("CONCENTRATION_GRAPH_TITLE")); + setIconImage(new ImageIcon(SimulatorUI.class.getResource("img/SBMLsimulator_32.png")).getImage()); + + setVisible(true); + + concentrationGraph = new Plot("", bundle.getString("X_AXIS"), bundle.getString("Y_AXIS")); + + if ((data != null) && (data.getRowCount() > 0)) { + graphData = Arrays.asList(new MultiTable[] {data}); + } + + if (graphData.size() > 0) { + + MetaDataset d; + if (graphData.size() == 1) { + d = new XYDatasetAdapter(graphData.get(0)); + } else { + d = new BoxPlotDataset(graphData); + } + String id; + int seriesCount = d.getSeriesCount(); + Color plotColors[] = new Color[seriesCount]; + String infos[] = new String[seriesCount]; + LegendTableModel tableModel = legend.getLegendTableModel(); + for (int i = 0; i < seriesCount; i++) { + id = d.getSeriesIdentifier(i); + if (tableModel.isSelected(id)) { + plotColors[i] = tableModel.getColorFor(id); + infos[i] = HTMLtools.createTooltip(tableModel.getSBase(i)); + } else { + plotColors[i] = null; + infos[i] = null; + } + } + concentrationGraph.plot(d, true, plotColors, infos); + concentrationGraph.setGridVisible(true); + concentrationGraph.setLegendVisible(false); + } + + graphPanel.add(concentrationGraph); + + plot = concentrationGraph.getChart().getXYPlot(); + ValueMarker marker = new ValueMarker(0); + marker.setPaint(Color.red); + plot.addDomainMarker(marker); + + NumberAxis yAxis = new LogarithmicAxis(bundle.getString("Y_AXIS")); + yAxis.setLowerBound(minMax[0]); + yAxis.setUpperBound(minMax[1]+40); + NumberAxis xAxis = new NumberAxis(bundle.getString("X_AXIS")); + xAxis.setLowerBound(1E-1); + xAxis.setUpperBound(maxTime); + plot.setRangeAxis(yAxis); + plot.setDomainAxis(xAxis); + + add(graphPanel, BorderLayout.WEST); + this.pack(); + + setFocusableWindowState(false); + setAlwaysOnTop(true); + } + + public void setTimepoint(double timepoint) { + plot = concentrationGraph.getChart().getXYPlot(); + plot.clearDomainMarkers(); + ValueMarker marker = new ValueMarker(timepoint); + marker.setPaint(Color.red); + marker.setStroke(new BasicStroke ( 1.5f )); + plot.addDomainMarker(marker); + } + +} diff --git a/src/org/sbml/simulator/gui/graph/DynamicControlPanel.java b/src/org/sbml/simulator/gui/graph/DynamicControlPanel.java index c292b1f..406df4a 100644 --- a/src/org/sbml/simulator/gui/graph/DynamicControlPanel.java +++ b/src/org/sbml/simulator/gui/graph/DynamicControlPanel.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -49,556 +47,634 @@ /** * This panel holds all elements to control the dynamic visualization. * It is a module of the view in MVC-pattern. - * + * * @author Fabian Schwarzkopf - * @version $Rev$ */ public class DynamicControlPanel extends JPanel { - - /** - * List of action commands. - * @author Fabian Schwarzkopf - * @version $Rev$ - */ - public enum Buttons implements ActionCommand { - /** - * - */ - PLAY, - /** - * - */ - PAUSE, - /** - * - */ - STOP, - /** - * - */ - TO_VIDEO, - /** - * - */ - GRAPHSHOT; - - /* (non-Javadoc) - * @see de.zbit.gui.actioncommand.ActionCommand#getName() - */ - @Override - public String getName() { - return bundle.getString(this.toString()); - } - - /* (non-Javadoc) - * @see de.zbit.gui.actioncommand.ActionCommand#getToolTip() - */ - @Override - public String getToolTip() { - return bundle.getString(this.toString() + "_TOOLTIP"); - } - } - - /** - * List of Controlpanel objects. - * @author Fabian Schwarzkopf - * @version $Rev$ - */ - public enum Items { - /** - * - */ - FAST, - /** - * - */ - NORMAL, - /** - * - */ - SLOW; - - /** - * Play speeds. - */ - private static int FAST_SPEED = (int) SBPreferences.getPreferencesFor( - GraphOptions.class).getDouble(GraphOptions.SIM_SPEED_FAST); - private static int NORMAL_SPEED = (int) SBPreferences - .getPreferencesFor(GraphOptions.class).getDouble( - GraphOptions.SIM_SPEED_NORMAL); - private static int SLOW_SPEED = (int) SBPreferences.getPreferencesFor( - GraphOptions.class).getDouble(GraphOptions.SIM_SPEED_SLOW); - - /** - * Returns a string array of all speed items. - * @return - */ - public static String[] getAllSpeedItems() { - return new String[] { Items.FAST.getName(), Items.NORMAL.getName(), - Items.SLOW.getName() }; - } - - /** - * Returns item for given string. - * @param item - * @return - */ - public static Items getItem(String item) { - assert item != null; - if (item.equals(bundle.getString(FAST.toString()))) { - return FAST; - } else if (item.equals(bundle.getString(NORMAL.toString()))) { - return NORMAL; - } else if (item.equals(bundle.getString(SLOW.toString()))) { - return SLOW; - } - return NORMAL; - } - - /** - * Sets speed of different items. - * @param item - * @param speed - */ - public static void setSpeed(Items item, int speed) { - if (item == FAST) { - FAST_SPEED = speed; - } else if (item == NORMAL) { - NORMAL_SPEED = speed; - } else if (item == SLOW) { - SLOW_SPEED = speed; - } - } - - /** - * Returns localized name of this Item. - * @return - */ - public String getName() { - return bundle.getString(this.toString()); - } - - /** - * Returns speed setting for given item. - * @param item - * @return - */ - public static int getSpeed(Items item) { - if (item == FAST) { - return FAST_SPEED; - } else if (item == NORMAL) { - return NORMAL_SPEED; - } else if (item == SLOW) { - return SLOW_SPEED; - } - return NORMAL_SPEED; - } - } - + + /** + * List of action commands. + * @author Fabian Schwarzkopf + */ + public enum Buttons implements ActionCommand { /** - * - */ - private static final long serialVersionUID = 6692563909762370732L; - - /** - * A {@link Logger} for this class. - */ - private static final transient Logger logger = Logger.getLogger(DynamicControlPanel.class.getName()); - - /** - * Localization support. + * */ - private static final transient ResourceBundle bundle = ResourceManager - .getBundle("org.sbml.simulator.gui.graph.DynamicGraph"); - - /** - * Pointer to related {@link DynamicCore}. - */ - private DynamicCore core; - - /** - * Registered {@link DynamicController}. - */ - private DynamicController controller; - - /** - * Saves the maximum time for the timelbl. - * (To save some computing time). - */ - private double maxTime; - + PLAY, /** - * Field for the activation status of panel elements. + * */ - private boolean panelActivationStatus; - - /** - * Refers to {@link JComboBox} name of available manipulators. - */ - public final String MANIPULATORS_LIST = GraphOptions.VISUALIZATION_STYLE.toString(); - - /** - * Refers to {@link JComboBox} name of available data. - */ - public final String DATA_LIST = bundle.getString("VISUALIZATION_DATA"); - - /* - * GUI elements - */ - private JLabel timelbl; - private JSlider searchBar; - private JLabel status; - private JButton play; - private JButton pause; - private JButton stop; - private JButton video; - private JButton graphShot; - private JLabel simVelolbl; - private JComboBox simVeloCombo; - private JComboBox manipulatorsCombo; - private JComboBox dataCombo; - private JSpinner simVeloSpin; - private JCheckBox nodeLabelsCB; - private JCheckBox reactionLabelsCB; - - /** - * Constructs a new control panel. - * @param controller - */ - public DynamicControlPanel(DynamicController controller) { - this.controller = controller; - this.controller.setControlPanel(this); - init(); - } - - /** - * Helper to layout components. - * @param gbl - * @param c - * @param x - * @param y - * @param width - * @param height - * @param anchor - * @param fill - * @param weightx - * @param weighty - * @param insets - */ - private void addComponent(GridBagLayout gbl, Component c, int x, int y, - int width, int height, int anchor, int fill, double weightx, double weighty, Insets insets) { - GridBagConstraints gbc = new GridBagConstraints(); - gbc.fill = fill; - gbc.gridx = x; gbc.gridy = y; - gbc.gridwidth = width; - gbc.gridheight = height; - gbc.weightx = weightx; - gbc.weighty = weighty; - gbc.insets = insets; - gbc.anchor = anchor; - gbl.setConstraints(c, gbc); - add(c); - } - - /** - * Adds an item to the data-list. - * @param item - */ - public void addToDataList(String item) { - dataCombo.addItem(item); - } - - /** - * Returns the activation status of this {@link DynamicControlPanel}. - * @return - */ - public boolean getPanelActivationStatus() { - return panelActivationStatus; - } - + PAUSE, /** - * Returns the current selected manipulator. - * @return - */ - public String getSelectedManipulator() { - return manipulatorsCombo.getSelectedItem().toString(); - } - - /** - * Returns selection state of nodelabels-checkbox. - * @return selections state of nodelabels-checkbox - */ - public boolean getSelectionStateOfNodeLabels() { - return nodeLabelsCB.isSelected(); - } - - /** - * Returns selection state of reactionlabels-checkbox. - * @return selections state of reactionlabels-checkbox + * + */ + STOP, + /** + * + */ + TO_VIDEO, + /** + * + */ + GRAPHSHOT, + /** + * + */ + CONCENTRATIONGRAPH; + + /* (non-Javadoc) + * @see de.zbit.gui.actioncommand.ActionCommand#getName() */ - public boolean getSelectionStateOfReactionLabels() { - return reactionLabelsCB.isSelected(); + @Override + public String getName() { + return bundle.getString(this.toString()); } - - /** - * Get the playspeed of the simulation as chosen by the user. - * @return value of the velocity {@link JSpinner}. - */ - public int getSimulationSpeed() { - try { - return Items.getSpeed(Items.getItem(simVeloCombo.getSelectedItem().toString())); - } catch (Exception e) { - logger.warning(bundle.getString("FALSE_INPUT")); - return 25; //playspeed per default - } - } - - /** - * Initialize this panel. - */ - private void init() { - logger.fine("Entering init method"); - GridBagLayout gbl = new GridBagLayout(); - setLayout(gbl); - SBPreferences prefs = SBPreferences.getPreferencesFor(GraphOptions.class); - - //init icons - ImageIcon playIcon = new ImageIcon(SimulatorUI.class.getResource("graph/GPL_PLAY_16.png")); - UIManager.put("GPL_PLAY_16", playIcon); - ImageIcon pauseIcon = new ImageIcon(SimulatorUI.class.getResource("graph/GPL_PAUSE_16.png")); - UIManager.put("GPL_PLAY_16", pauseIcon); - ImageIcon stopIcon = new ImageIcon(SimulatorUI.class.getResource("graph/GPL_STOP_16.png")); - UIManager.put("GPL_STOP_16", stopIcon); - ImageIcon toVideoIcon = new ImageIcon(SimulatorUI.class.getResource("graph/GPL_VIDEO_16.png")); - UIManager.put("GPL_VIDEO_16", toVideoIcon); - ImageIcon toImageIcon = new ImageIcon(SimulatorUI.class.getResource("graph/GPL_IMAGE_16.png")); - UIManager.put("GPL_IMAGE_16", toImageIcon); - - //init searchbar - searchBar = new JSlider(); - searchBar.setMajorTickSpacing(1); - searchBar.setPaintTicks(true); - searchBar.setValue(0); - searchBar.setToolTipText(bundle.getString("SEARCHBAR_TOOLTIP")); - searchBar.addChangeListener(controller); - - //init checkboxes - nodeLabelsCB = GUITools.createJCheckBox(GraphOptions.SHOW_NODE_LABELS, prefs, controller); - nodeLabelsCB.addActionListener(controller); - reactionLabelsCB = GUITools.createJCheckBox(GraphOptions.SHOW_REACTION_LABELS, prefs, controller); - reactionLabelsCB.addActionListener(controller); - - timelbl = new JLabel(MessageFormat.format("{0}: {1}", new Object[]{bundle.getString("TIMEPOINT"), "N/A"})); - status = new JLabel(); - - //init buttons - play = GUITools.createButton(playIcon, controller, Buttons.PLAY, Buttons.PLAY.getToolTip()); - pause = GUITools.createButton(pauseIcon, controller, Buttons.PAUSE, Buttons.PAUSE.getToolTip()); - stop = GUITools.createButton(stopIcon, controller, Buttons.STOP, Buttons.STOP.getToolTip()); - video = GUITools.createButton(toVideoIcon, controller, Buttons.TO_VIDEO, Buttons.TO_VIDEO.getToolTip()); - graphShot = GUITools.createButton(toImageIcon, controller, Buttons.GRAPHSHOT, Buttons.GRAPHSHOT.getToolTip()); - - //init speedcontrol - simVelolbl = new JLabel(GraphOptions.SIM_SPEED_CHOOSER.getDisplayName()); - simVeloCombo = new JComboBox(); - simVeloCombo.setName(GraphOptions.SIM_SPEED_CHOOSER.toString()); - simVeloCombo.setToolTipText(bundle.getString("SIM_SPEED_CHOOSER_TOOLTIP")); - simVeloCombo.addItem(Items.FAST.getName()); - simVeloCombo.addItem(Items.NORMAL.getName()); - simVeloCombo.addItem(Items.SLOW.getName()); - simVeloCombo.addItemListener(controller); - simVeloSpin = new JSpinner(); - simVeloSpin.setToolTipText(bundle.getString("SIMULATIONSPEED_SPINNER_TOOLTIP")); -// FIXME prefs are not loaded correctly -// String pref = prefs.getString(GraphOptions.SIM_SPEED_CHOOSER); -// assert pref != null; -// Items item = Items.getItem(pref); -// assert item != null; -// setSimVeloCombo(item); - - //init visualizer control - manipulatorsCombo = new JComboBox(Manipulators.getAllManipulators()); - manipulatorsCombo.setName(MANIPULATORS_LIST); - manipulatorsCombo.setToolTipText(bundle.getString("VISUALIZATION_STYLE_TOOLTIP")); - manipulatorsCombo.addItemListener(controller); - manipulatorsCombo.setSelectedItem(prefs.getString(GraphOptions.VISUALIZATION_STYLE)); - dataCombo = new JComboBox(); - dataCombo.setName(DATA_LIST); - dataCombo.setToolTipText(bundle.getString("VISUALIZATION_DATA_TOOLTIP")); - dataCombo.addItemListener(controller); - JPanel manipulatorsPane = new JPanel(); - manipulatorsPane.setToolTipText(bundle.getString("VISUALIZATION_TOOLTIP")); - LayoutHelper lh = new LayoutHelper(manipulatorsPane); - lh.add(manipulatorsCombo, true); - lh.add(dataCombo); - manipulatorsPane.setBorder(BorderFactory.createTitledBorder(bundle.getString("GROUP_VISUALIZATION"))); - manipulatorsPane.setMinimumSize(new Dimension(80, 20)); - - //layout components - addComponent(gbl, searchBar, 0, 0, 7, 1, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, 1, 0, new Insets(0,0,0,0)); - addComponent(gbl, play, 0, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); - addComponent(gbl, pause, 1, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); - addComponent(gbl, stop, 2, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); - addComponent(gbl, video, 3, 1, 1, 1, GridBagConstraints.EAST, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); - addComponent(gbl, graphShot, 4, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); - addComponent(gbl, timelbl, 5, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); - addComponent(gbl, simVelolbl, 0, 2, 3, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); - addComponent(gbl, simVeloCombo, 3, 2, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); - addComponent(gbl, simVeloSpin, 4, 2, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); - addComponent(gbl, status, 5, 2, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, 1, 0, new Insets(2,2,2,2)); - addComponent(gbl, reactionLabelsCB, 6, 2, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); - addComponent(gbl, nodeLabelsCB, 6, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); - addComponent(gbl, manipulatorsPane, 7, 0, 3, 3, GridBagConstraints.CENTER, GridBagConstraints.BOTH, 0, 0, new Insets(2,2,2,2)); - - //disable components as long as there is no data core - Component[] elements = { play, pause, stop, video, graphShot, - searchBar, simVeloCombo, simVeloSpin, nodeLabelsCB, - reactionLabelsCB, manipulatorsCombo, dataCombo }; - GUITools.setEnabledForAll(false, elements); - panelActivationStatus = false; - logger.fine("DynamicControlPanel initialized."); - } - + + /* (non-Javadoc) + * @see de.zbit.gui.actioncommand.ActionCommand#getToolTip() + */ + @Override + public String getToolTip() { + return bundle.getString(this.toString() + "_TOOLTIP"); + } + } + + /** + * List of Controlpanel objects. + * @author Fabian Schwarzkopf + * @version $Rev: 1178 $ + */ + public enum Items { + /** + * + */ + FAST, + /** + * + */ + NORMAL, + /** + * + */ + SLOW, + /** + * + */ + NO_CAMERA_ANIMATION; + /** - * Sets the related {@link DynamicCore} to this control panel and activates - * all corresponding elements. - * - * @param core - * {@link DynamicCore} + * Play speeds. */ - public void setCore(DynamicCore core) { - this.core = core; - double[] timepointsOfSimulation = core.getTimepoints(); - /* - * Bugfix: controller has to be unassigned to change boundries of - * JSlider, otherwise boundrie changing will invoke change of JSlider - * stateChange thus invoking timepointchange in core. Maybe timepoint of - * that core is set to 0 if timepoint doesn't exist. - */ - controller.setCore(null); - searchBar.setMinimum(0); - searchBar.setMaximum(timepointsOfSimulation.length-1); - maxTime = core.getMaxTime(); - - /* - * Controller needs to be assigned after setting the boundries of JSlider. - * Otherwise the current JSlider-value will change, thus invoking a change of the - * current saved timepoint of the core (same as above). - */ - controller.setCore(core); - setSearchbarValue(core.getCurrTimepoint()); - Component[] elements = { play, pause, stop, video, graphShot, - searchBar, simVeloCombo, nodeLabelsCB, reactionLabelsCB, - manipulatorsCombo, dataCombo }; - GUITools.setEnabledForAll(true, elements); - panelActivationStatus = true; - } - + private static int FAST_SPEED = (int) SBPreferences.getPreferencesFor( + GraphOptions.class).getDouble(GraphOptions.SIM_SPEED_FAST); + private static int NORMAL_SPEED = (int) SBPreferences + .getPreferencesFor(GraphOptions.class).getDouble( + GraphOptions.SIM_SPEED_NORMAL); + private static int SLOW_SPEED = (int) SBPreferences.getPreferencesFor( + GraphOptions.class).getDouble(GraphOptions.SIM_SPEED_SLOW); + /** - * Enables {@link DynamicControlPanel} elements accordant to pause status. + * Returns a string array of all speed items. + * @return */ - public void setPauseStatus() { - play.setEnabled(true); - searchBar.setEnabled(true); - pause.setEnabled(true); - simVeloCombo.setEnabled(true); - video.setEnabled(true); - graphShot.setEnabled(true); + public static String[] getAllSpeedItems() { + return new String[] { Items.FAST.getName(), Items.NORMAL.getName(), + Items.SLOW.getName() }; } - + /** - * Enables {@link DynamicControlPanel} elements accordant to play status. + * Returns a string array of all speed items and no camera animation. + * @return */ - public void setPlayStatus() { - play.setEnabled(false); - searchBar.setEnabled(false); - pause.setEnabled(true); - stop.setEnabled(true); - simVeloCombo.setEnabled(false); - video.setEnabled(false); - graphShot.setEnabled(false); + public static String[] getAllCameraAnimationItems() { + return new String[] { Items.FAST.getName(), Items.NORMAL.getName(), + Items.SLOW.getName(), Items.NO_CAMERA_ANIMATION.getName() }; } - + /** - * Sets the {@link JSlider} to the given timepoint and updates the time label. - * @param timepoint - */ - public void setSearchbarValue(double timepoint) { - if (core != null) { - searchBar.setValue(core.getIndexOfTimepoint(timepoint)); - timelbl.setText(MessageFormat.format("{0}: {1,number,0.00} / {2,number,0.00}", new Object[]{bundle.getString("TIMEPOINT"), timepoint, maxTime})); - } - } - - /** - * Sets selected manipulator in {@link JComboBox}. - * @param manipulator - */ - public void setSelectedManipulator(Manipulators manipulator) { - manipulatorsCombo.setSelectedItem(manipulator.getName()); - } - - /** - * Sets {@link JComboBox} containing visualization data to given dataName. - * Ensure that {@link JComboBox} listener changes visualized data - * respectively. - * - * @param dataName + * Returns item for given string. + * @param item + * @return */ - public void setSelectedVisualizationData(String dataName) { - dataCombo.setSelectedItem(dataName); - } - - /** - * Sets selection state of nodelabels-checkbox. - * @param bool - */ - public void setSelectionStateOfNodeLabels(boolean bool) { - nodeLabelsCB.setSelected(bool); - } - + public static Items getItem(String item) { + assert item != null; + if (item.equals(bundle.getString(FAST.toString()))) { + return FAST; + } else if (item.equals(bundle.getString(NORMAL.toString()))) { + return NORMAL; + } else if (item.equals(bundle.getString(SLOW.toString()))) { + return SLOW; + } else if (item.equals(bundle.getString(NO_CAMERA_ANIMATION.toString()))) { + return NO_CAMERA_ANIMATION; + } + return NORMAL; + } + /** - * Sets selection state of reactionlabels-checkbox. - * @param bool + * Sets speed of different items. + * @param item + * @param speed */ - public void setSelectionStateOfReactionLabels(boolean bool) { - reactionLabelsCB.setSelected(bool); + public static void setSpeed(Items item, int speed) { + if (item == FAST) { + FAST_SPEED = speed; + } else if (item == NORMAL) { + NORMAL_SPEED = speed; + } else if (item == SLOW) { + SLOW_SPEED = speed; + } } - - /** - * Setting the simulation speed by {@link JComboBox} items. - * @param item - */ - public void setSimVeloCombo(Items item) { - simVeloCombo.setSelectedItem(item.getName()); - simVeloSpin.setValue(Items.getSpeed(item)); - } - + /** - * Displays a given string on the {@link DynamicControlPanel}. - * @param label + * Returns localized name of this Item. + * @return */ - public void setStatusString(String label) { - status.setText(label); - } - - /** - * Enables {@link DynamicControlPanel} elements accordant to stop status. + public String getName() { + return bundle.getString(this.toString()); + } + + /** + * Returns speed setting for given item. + * @param item + * @return */ - public void setStopStatus() { - Component[] elements = { play, pause, stop, video, graphShot, - searchBar, simVeloCombo, nodeLabelsCB, reactionLabelsCB, - manipulatorsCombo, dataCombo }; - GUITools.setEnabledForAll(true, elements); + public static int getSpeed(Items item) { + if (item == FAST) { + return FAST_SPEED; + } else if (item == NORMAL) { + return NORMAL_SPEED; + } else if (item == SLOW) { + return SLOW_SPEED; + } + return NORMAL_SPEED; + } + } + + /** + * + */ + private static final long serialVersionUID = 6692563909762370732L; + + /** + * A {@link Logger} for this class. + */ + private static final transient Logger logger = Logger.getLogger(DynamicControlPanel.class.getName()); + + /** + * Localization support. + */ + private static final transient ResourceBundle bundle = ResourceManager + .getBundle("org.sbml.simulator.gui.graph.DynamicGraph"); + + /** + * Pointer to related {@link DynamicCore}. + */ + private DynamicCore core; + + /** + * Registered {@link DynamicController}. + */ + private DynamicController controller; + + /** + * Saves the maximum time for the timelbl. + * (To save some computing time). + */ + private double maxTime; + + /** + * Field for the activation status of panel elements. + */ + private boolean panelActivationStatus; + + /** + * Refers to {@link JComboBox} name of available manipulators. + */ + public final String MANIPULATORS_LIST = GraphOptions.VISUALIZATION_STYLE.toString(); + + /** + * Refers to {@link JComboBox} name of available data. + */ + public final String DATA_LIST = bundle.getString("VISUALIZATION_DATA"); + + /* + * GUI elements + */ + private JSlider searchBar; + private JLabel timelbl; + private JLabel status; + private JLabel simVelolbl; + private JLabel cameraAnimationbl; + private JButton play; + private JButton pause; + private JButton stop; + private JButton video; + private JButton graphShot; + private JButton concentrationGraph; + private JComboBox simVeloCombo; + private JComboBox manipulatorsCombo; + private JComboBox dataCombo; + private JComboBox cameraAnimationCombo; + private JSpinner simVeloSpin; + private JCheckBox nodeLabelsCB; + private JCheckBox reactionLabelsCB; + private JCheckBox cycleSimulationCB; + + /** + * Constructs a new control panel. + * @param controller + */ + public DynamicControlPanel(DynamicController controller) { + this.controller = controller; + this.controller.setControlPanel(this); + init(); + } + + /** + * Helper to layout components. + * @param gbl + * @param c + * @param x + * @param y + * @param width + * @param height + * @param anchor + * @param fill + * @param weightx + * @param weighty + * @param insets + */ + private void addComponent(GridBagLayout gbl, Component c, int x, int y, + int width, int height, int anchor, int fill, double weightx, double weighty, Insets insets) { + GridBagConstraints gbc = new GridBagConstraints(); + gbc.fill = fill; + gbc.gridx = x; gbc.gridy = y; + gbc.gridwidth = width; + gbc.gridheight = height; + gbc.weightx = weightx; + gbc.weighty = weighty; + gbc.insets = insets; + gbc.anchor = anchor; + gbl.setConstraints(c, gbc); + add(c); + } + + /** + * Adds an item to the data-list. + * @param item + */ + public void addToDataList(String item) { + dataCombo.addItem(item); + } + + /** + * Returns the activation status of this {@link DynamicControlPanel}. + * @return + */ + public boolean getPanelActivationStatus() { + return panelActivationStatus; + } + + /** + * Returns the current selected manipulator. + * @return + */ + public String getSelectedManipulator() { + return manipulatorsCombo.getSelectedItem().toString(); + } + + /** + * Returns selection state of nodelabels-checkbox. + * @return selections state of nodelabels-checkbox + */ + public boolean getSelectionStateOfNodeLabels() { + return nodeLabelsCB.isSelected(); + } + + /** + * Returns selection state of reactionlabels-checkbox. + * @return selections state of reactionlabels-checkbox + */ + public boolean getSelectionStateOfReactionLabels() { + return reactionLabelsCB.isSelected(); + } + + /** + * Get the playspeed of the simulation as chosen by the user. + * @return value of the velocity {@link JSpinner}. + */ + public int getSimulationSpeed() { + try { + return Items.getSpeed(Items.getItem(simVeloCombo.getSelectedItem().toString())); + } catch (Exception e) { + logger.warning(bundle.getString("FALSE_INPUT")); + return 25; //playspeed per default } - - /** - * Enables {@link DynamicControlPanel} elements accordant to video status. + } + + public String getCameraAnimationMode() { + return cameraAnimationCombo.getSelectedItem().toString(); + } + + /** + * Initialize this panel. + */ + private void init() { + logger.fine("Entering init method"); + GridBagLayout gbl = new GridBagLayout(); + setLayout(gbl); + SBPreferences prefs = SBPreferences.getPreferencesFor(GraphOptions.class); + + //init icons + ImageIcon playIcon = new ImageIcon(SimulatorUI.class.getResource("graph/GPL_PLAY_16.png")); + UIManager.put("GPL_PLAY_16", playIcon); + ImageIcon pauseIcon = new ImageIcon(SimulatorUI.class.getResource("graph/GPL_PAUSE_16.png")); + UIManager.put("GPL_PLAY_16", pauseIcon); + ImageIcon stopIcon = new ImageIcon(SimulatorUI.class.getResource("graph/GPL_STOP_16.png")); + UIManager.put("GPL_STOP_16", stopIcon); + ImageIcon toVideoIcon = new ImageIcon(SimulatorUI.class.getResource("graph/GPL_VIDEO_16.png")); + UIManager.put("GPL_VIDEO_16", toVideoIcon); + ImageIcon toImageIcon = new ImageIcon(SimulatorUI.class.getResource("graph/GPL_IMAGE_16.png")); + UIManager.put("GPL_IMAGE_16", toImageIcon); + ImageIcon concentrationIcon = new ImageIcon(SimulatorUI.class.getResource("graph/GPL_CONCENTRATION.png")); + UIManager.put("GLP_CONCENTRATION", concentrationIcon); + + //init searchbar + searchBar = new JSlider(); + searchBar.setMajorTickSpacing(1); + searchBar.setPaintTicks(true); + searchBar.setValue(0); + searchBar.setToolTipText(bundle.getString("SEARCHBAR_TOOLTIP")); + searchBar.addChangeListener(controller); + + //init checkboxes + nodeLabelsCB = GUITools.createJCheckBox(GraphOptions.SHOW_NODE_LABELS, prefs, controller); + nodeLabelsCB.addActionListener(controller); + reactionLabelsCB = GUITools.createJCheckBox(GraphOptions.SHOW_REACTION_LABELS, prefs, controller); + reactionLabelsCB.addActionListener(controller); + cycleSimulationCB = GUITools.createJCheckBox(GraphOptions.CYCLE_SIMULATION, prefs, controller); + cycleSimulationCB.addActionListener(controller); + + timelbl = new JLabel(MessageFormat.format("{0}: {1}", new Object[]{bundle.getString("TIMEPOINT"), "N/A"})); + status = new JLabel(); + + //init buttons + play = GUITools.createButton(playIcon, controller, Buttons.PLAY, Buttons.PLAY.getToolTip()); + pause = GUITools.createButton(pauseIcon, controller, Buttons.PAUSE, Buttons.PAUSE.getToolTip()); + stop = GUITools.createButton(stopIcon, controller, Buttons.STOP, Buttons.STOP.getToolTip()); + video = GUITools.createButton(toVideoIcon, controller, Buttons.TO_VIDEO, Buttons.TO_VIDEO.getToolTip()); + graphShot = GUITools.createButton(toImageIcon, controller, Buttons.GRAPHSHOT, Buttons.GRAPHSHOT.getToolTip()); + concentrationGraph = GUITools.createButton(concentrationIcon, controller, Buttons.CONCENTRATIONGRAPH, Buttons.CONCENTRATIONGRAPH.getToolTip()); + + //init speedcontrol + simVelolbl = new JLabel(GraphOptions.SIM_SPEED_CHOOSER.getDisplayName()); + simVeloCombo = new JComboBox(); + simVeloCombo.setName(GraphOptions.SIM_SPEED_CHOOSER.toString()); + simVeloCombo.setToolTipText(bundle.getString("SIM_SPEED_CHOOSER_TOOLTIP")); + simVeloCombo.addItem(Items.FAST.getName()); + simVeloCombo.addItem(Items.NORMAL.getName()); + simVeloCombo.addItem(Items.SLOW.getName()); + simVeloCombo.addItemListener(controller); + simVeloSpin = new JSpinner(); + simVeloSpin.setToolTipText(bundle.getString("SIMULATIONSPEED_SPINNER_TOOLTIP")); + // FIXME prefs are not loaded correctly + // String pref = prefs.getString(GraphOptions.SIM_SPEED_CHOOSER); + // assert pref != null; + // Items item = Items.getItem(pref); + // assert item != null; + // setSimVeloCombo(item); + + cameraAnimationbl = new JLabel(GraphOptions.SHOW_CAMERA_ANIMATION.getDisplayName()); + cameraAnimationCombo = new JComboBox(); + cameraAnimationCombo.setName(GraphOptions.SHOW_CAMERA_ANIMATION.toString()); + cameraAnimationCombo.setToolTipText(bundle.getString("SHOW_CAMERA_ANIMATION_TOOLTIP")); + cameraAnimationCombo.addItem(Items.FAST.getName()); + cameraAnimationCombo.addItem(Items.NORMAL.getName()); + cameraAnimationCombo.addItem(Items.SLOW.getName()); + cameraAnimationCombo.addItem(Items.NO_CAMERA_ANIMATION.getName()); + cameraAnimationCombo.setSelectedItem(prefs.getString(GraphOptions.SHOW_CAMERA_ANIMATION)); + cameraAnimationCombo.addItemListener(controller); + + //init visualizer control + manipulatorsCombo = new JComboBox(Manipulators.getAllManipulators()); + manipulatorsCombo.setName(MANIPULATORS_LIST); + manipulatorsCombo.setToolTipText(bundle.getString("VISUALIZATION_STYLE_TOOLTIP")); + manipulatorsCombo.addItemListener(controller); + manipulatorsCombo.setSelectedItem(prefs.getString(GraphOptions.VISUALIZATION_STYLE)); + dataCombo = new JComboBox(); + dataCombo.setName(DATA_LIST); + dataCombo.setToolTipText(bundle.getString("VISUALIZATION_DATA_TOOLTIP")); + dataCombo.addItemListener(controller); + JPanel manipulatorsPane = new JPanel(); + manipulatorsPane.setToolTipText(bundle.getString("VISUALIZATION_TOOLTIP")); + LayoutHelper lh = new LayoutHelper(manipulatorsPane); + lh.add(manipulatorsCombo, true); + lh.add(dataCombo); + manipulatorsPane.setBorder(BorderFactory.createTitledBorder(bundle.getString("GROUP_VISUALIZATION"))); + manipulatorsPane.setMinimumSize(new Dimension(80, 20)); + + //layout components + addComponent(gbl, searchBar, 0, 0, 7, 1, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, 1, 0, new Insets(0,0,0,0)); + addComponent(gbl, play, 0, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); + addComponent(gbl, pause, 1, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); + addComponent(gbl, stop, 2, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); + addComponent(gbl, video, 3, 1, 1, 1, GridBagConstraints.EAST, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); + addComponent(gbl, graphShot, 4, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); + addComponent(gbl, cameraAnimationbl, 5, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); + addComponent(gbl, cameraAnimationCombo,6, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); + addComponent(gbl, timelbl, 6, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); + addComponent(gbl, simVelolbl, 0, 2, 3, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); + addComponent(gbl, simVeloCombo, 3, 2, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); + addComponent(gbl, simVeloSpin, 4, 2, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); + addComponent(gbl, status, 6, 2, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, 1, 0, new Insets(2,2,2,2)); + addComponent(gbl, reactionLabelsCB, 8, 2, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); + addComponent(gbl, nodeLabelsCB, 8, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); + addComponent(gbl, cycleSimulationCB, 7, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); + addComponent(gbl, manipulatorsPane, 10, 0, 3, 3, GridBagConstraints.CENTER, GridBagConstraints.BOTH, 0, 0, new Insets(2,2,2,2)); + addComponent(gbl, concentrationGraph, 9, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.NONE, 0, 0, new Insets(2,2,2,2)); + + //disable components as long as there is no data core + Component[] elements = { play, pause, stop, video, graphShot, + searchBar, simVeloCombo, simVeloSpin, nodeLabelsCB, cameraAnimationCombo, cycleSimulationCB, + concentrationGraph, reactionLabelsCB, manipulatorsCombo, dataCombo }; + GUITools.setEnabledForAll(false, elements); + panelActivationStatus = false; + + logger.fine("DynamicControlPanel initialized."); + } + + /** + * Sets the related {@link DynamicCore} to this control panel and activates + * all corresponding elements. + * + * @param core + * {@link DynamicCore} + */ + public void setCore(DynamicCore core) { + this.core = core; + double[] timepointsOfSimulation = core.getTimepoints(); + /* + * Bugfix: controller has to be unassigned to change boundries of + * JSlider, otherwise boundrie changing will invoke change of JSlider + * stateChange thus invoking timepointchange in core. Maybe timepoint of + * that core is set to 0 if timepoint doesn't exist. */ - public void setVideoStatus() { - Component[] elements = { play, pause, video, graphShot, - searchBar, simVeloCombo, nodeLabelsCB, reactionLabelsCB, - manipulatorsCombo, dataCombo }; - GUITools.setEnabledForAll(false, elements); + controller.setCore(null); + searchBar.setMinimum(0); + searchBar.setMaximum(timepointsOfSimulation.length-1); + maxTime = core.getMaxTime(); + + /* + * Controller needs to be assigned after setting the boundries of JSlider. + * Otherwise the current JSlider-value will change, thus invoking a change of the + * current saved timepoint of the core (same as above). + */ + controller.setCore(core); + setSearchbarValue(core.getCurrTimepoint()); + Component[] elements = { play, pause, stop, video, graphShot, + searchBar, simVeloCombo, nodeLabelsCB, cycleSimulationCB, + concentrationGraph, reactionLabelsCB, manipulatorsCombo, dataCombo }; + GUITools.setEnabledForAll(true, elements); + + core.cameraAnimation = !cameraAnimationCombo.getSelectedItem().toString().equals(bundle.getString("NO_CAMERA_ANIMATION")); + core.playAgain = core.cameraAnimation; + + if(!GraphOptions.CAMERA_WAY_FILE.getValue(SBPreferences.getPreferencesFor(GraphOptions.class)).toString(). + equals(GraphOptions.CAMERA_WAY_FILE.getDefaultValue().toString())) { + cameraAnimationCombo.setEnabled(true); + + if(core.cameraAnimation && (core.getAnotherObserver() == null)) { + core.setAnotherObserver(new CameraAnimationView()); + } + } + + panelActivationStatus = true; + } + + /** + * Enables {@link DynamicControlPanel} elements accordant to pause status. + */ + public void setPauseStatus() { + play.setEnabled(true); + searchBar.setEnabled(true); + pause.setEnabled(true); + simVeloCombo.setEnabled(true); + video.setEnabled(true); + graphShot.setEnabled(true); + cycleSimulationCB.setEnabled(true); + if(!GraphOptions.CAMERA_WAY_FILE.getValue(SBPreferences.getPreferencesFor(GraphOptions.class)).toString(). + equals(GraphOptions.CAMERA_WAY_FILE.getDefaultValue().toString())) { + cameraAnimationCombo.setEnabled(true); + } + } + + /** + * Enables {@link DynamicControlPanel} elements accordant to play status. + */ + public void setPlayStatus() { + play.setEnabled(false); + searchBar.setEnabled(false); + pause.setEnabled(true); + stop.setEnabled(true); + simVeloCombo.setEnabled(false); + cameraAnimationCombo.setEnabled(false); + video.setEnabled(false); + graphShot.setEnabled(false); + } + + /** + * Sets the {@link JSlider} to the given timepoint and updates the time label. + * @param timepoint + */ + public void setSearchbarValue(double timepoint) { + if (core != null) { + searchBar.setValue(core.getIndexOfTimepoint(timepoint)); + timelbl.setText(MessageFormat.format("{0}: {1,number,0.00} / {2,number,0.00}", new Object[]{bundle.getString("TIMEPOINT"), timepoint, maxTime})); } + } + + /** + * Sets selected manipulator in {@link JComboBox}. + * @param manipulator + */ + public void setSelectedManipulator(Manipulators manipulator) { + manipulatorsCombo.setSelectedItem(manipulator.getName()); + } + + /** + * Sets {@link JComboBox} containing visualization data to given dataName. + * Ensure that {@link JComboBox} listener changes visualized data + * respectively. + * + * @param dataName + */ + public void setSelectedVisualizationData(String dataName) { + dataCombo.setSelectedItem(dataName); + } + + /** + * Sets selection state of nodelabels-checkbox. + * @param bool + */ + public void setSelectionStateOfNodeLabels(boolean bool) { + nodeLabelsCB.setSelected(bool); + } + + /** + * Sets selection state of reactionlabels-checkbox. + * @param bool + */ + public void setSelectionStateOfReactionLabels(boolean bool) { + reactionLabelsCB.setSelected(bool); + } + + /** + * Setting the simulation speed by {@link JComboBox} items. + * @param item + */ + public void setSimVeloCombo(Items item) { + simVeloCombo.setSelectedItem(item.getName()); + simVeloSpin.setValue(Items.getSpeed(item)); + } + + /** + * Setting the camera animation speed by {@link JComboBox} items + * @param item + */ + public void setCameraAnimationCombo(Items item) { + cameraAnimationCombo.setSelectedItem(item.getName()); + } + + /** + * Displays a given string on the {@link DynamicControlPanel}. + * @param label + */ + public void setStatusString(String label) { + status.setText(label); + } + + /** + * Enables {@link DynamicControlPanel} elements accordant to stop status. + */ + public void setStopStatus() { + Component[] elements = { play, pause, stop, video, graphShot, + searchBar, simVeloCombo, nodeLabelsCB, cycleSimulationCB, concentrationGraph, reactionLabelsCB, + manipulatorsCombo, dataCombo }; + GUITools.setEnabledForAll(true, elements); + + if(!GraphOptions.CAMERA_WAY_FILE.getValue(SBPreferences.getPreferencesFor(GraphOptions.class)).toString(). + equals(GraphOptions.CAMERA_WAY_FILE.getDefaultValue().toString())) { + cameraAnimationCombo.setEnabled(true); + } + } + + /** + * Enables {@link DynamicControlPanel} elements accordant to video status. + */ + public void setVideoStatus() { + Component[] elements = { play, pause, video, graphShot, + searchBar, simVeloCombo, nodeLabelsCB, cameraAnimationCombo, cycleSimulationCB, + concentrationGraph, reactionLabelsCB, manipulatorsCombo, dataCombo }; + GUITools.setEnabledForAll(false, elements); + } } diff --git a/src/org/sbml/simulator/gui/graph/DynamicController.java b/src/org/sbml/simulator/gui/graph/DynamicController.java index cfcc042..ab02492 100644 --- a/src/org/sbml/simulator/gui/graph/DynamicController.java +++ b/src/org/sbml/simulator/gui/graph/DynamicController.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -27,6 +25,7 @@ import java.io.File; import java.io.IOException; import java.text.MessageFormat; +import java.util.Map; import java.util.ResourceBundle; import java.util.logging.Logger; import java.util.prefs.BackingStoreException; @@ -39,19 +38,23 @@ import javax.swing.JComboBox; import javax.swing.JFileChooser; import javax.swing.JSlider; +import javax.swing.SwingWorker; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import javax.swing.filechooser.FileFilter; +import org.sbml.simulator.gui.LegendPanel; import org.sbml.simulator.gui.graph.DynamicControlPanel.Items; import org.sbml.simulator.gui.graph.DynamicView.Manipulators; import org.sbml.simulator.gui.table.LegendTableModel; +import org.simulator.math.odes.MultiTable; import de.zbit.gui.GUIOptions; import de.zbit.gui.GUITools; import de.zbit.io.filefilter.SBFileFilter; +import de.zbit.sbml.layout.y.YImageTools; import de.zbit.util.ResourceManager; import de.zbit.util.prefs.KeyProvider; import de.zbit.util.prefs.Option; @@ -63,7 +66,6 @@ * control panel. * * @author Fabian Schwarzkopf - * @version $Rev$ */ public class DynamicController implements ChangeListener, ActionListener, ItemListener, TableModelListener, PreferenceChangeListener { @@ -94,6 +96,16 @@ public class DynamicController implements ChangeListener, ActionListener, */ private DynamicView view; + /** + * Pointer to associated {@link CameraAnimationView} + */ + private CameraAnimationView camView; + + /** + * opens new window with all metabolic concentrations + */ + private ConcentrationGraphUI graphWindow; + /** * Constructs a new {@link DynamicController} with the corresponding * {@link DynamicView}. @@ -128,6 +140,9 @@ public void actionPerformed(ActionEvent e) { case GRAPHSHOT: graphShot(); break; + case CONCENTRATIONGRAPH: + concentrationGraph(); + break; default: break; } @@ -142,8 +157,16 @@ public void actionPerformed(ActionEvent e) { * */ private void stop() { + if(!controlPanel.getCameraAnimationMode().equals(bundle.getString("NO_CAMERA_ANIMATION"))) { + if(camView == null && core.cameraWay != null) { + camView = (CameraAnimationView) core.cameraWay; + } + camView.setCounterBack(); + } + core.stopPlay(); - controlPanel.setStopStatus(); + controlPanel.setStopStatus(); + setNewTimepoint(0); } /** @@ -158,6 +181,16 @@ private void pause() { * */ private void play() { + if(!controlPanel.getCameraAnimationMode().equals(bundle.getString("NO_CAMERA_ANIMATION"))) { + if(camView == null && core.cameraWay != null) { + camView = (CameraAnimationView) core.getAnotherObserver(); + } + camView.checkForNewFile(); + //camView.showOverviewAnimation(); + } + + setNewMinMaxNodeSize(); + controlPanel.setPlayStatus(); core.setPlayspeed(controlPanel.getSimulationSpeed()); core.play(); @@ -185,13 +218,15 @@ private void toVideo() { // determine output resolution if (prefs.getBoolean(GraphOptions.VIDEO_FORCE_RESOLUTION_MULTIPLIER) || (width < 1000) || (height < 1000)) { - int resolutionMultiplier = (int) prefs.getDouble(GraphOptions.VIDEO_RESOLUTION_MULTIPLIER); + double resolutionMultiplier = prefs.getDouble(GraphOptions.VIDEO_RESOLUTION_MULTIPLIER); /* * if resolution multiplier is forced by the user or if * resolution is too small than scale it */ width *= resolutionMultiplier; height *= resolutionMultiplier; + width = Math.round(width); + height = Math.round(height); } //determine fixpoint to prevent pixel jumping @@ -224,14 +259,19 @@ private void toVideo() { int timestamp = (controlPanel.getSimulationSpeed() + 3) * captureStepSize; //warning if computation could take very long - int numScreenshots = (core.getTimepoints().length-1) / captureStepSize; + int numScreenshots = (core.getTimepoints().length-1) / captureStepSize; + + if(core.cameraAnimation) { + numScreenshots *= 2; + } + if ((width > 2500) || (height > 2500) || (numScreenshots > 150)) { GUITools.showMessage( MessageFormat.format( bundle.getString("VIDEO_LONG_COMPUTATION_TIME"), new Object[] { width, height, numScreenshots }), bundle - .getString("INFO_COMP")); + .getString("INFO_COMP")); } /* @@ -325,45 +365,102 @@ private void graphShot() { // determine raw graph size int[] size = imggen.getScreenshotResolution(); - int width = size[0] * resolutionMultiplier; - int height = size[1] * resolutionMultiplier; + final int width = size[0] * resolutionMultiplier; + final int height = size[1] * resolutionMultiplier; + + SBFileFilter svgFilter = SBFileFilter.createSVGFileFilter(); + SBFileFilter pngFilter = SBFileFilter.createPNGFileFilter(); File destinationFile = GUITools.saveFileDialog(view, guiPrefs.get(GUIOptions.SAVE_DIR), false, false, JFileChooser.FILES_ONLY, - SBFileFilter.createPNGFileFilter()); + pngFilter, svgFilter); if (destinationFile != null) { + SBFileFilter filter; + if (svgFilter.accept(destinationFile)) { + filter = svgFilter; + } else { + filter = pngFilter; + } - // add extenion if missing - if (!destinationFile.getName().toLowerCase() - .endsWith(".png")) { + // add extension if missing + String fileNameLC = destinationFile.getName().toLowerCase(); + if (!fileNameLC.endsWith('.' + filter.getExtension())) { destinationFile = new File( - destinationFile.getAbsolutePath() + ".png"); + destinationFile.getAbsolutePath() + '.' + filter.getExtension()); } try { - if (!destinationFile.getName().toLowerCase() - .endsWith(".png")) { + if (!fileNameLC.endsWith('.' + filter.getExtension())) { destinationFile = new File( - destinationFile.getAbsolutePath() - + ".png"); + destinationFile.getAbsolutePath() + '.' + pngFilter.getExtension()); + } + if (filter == pngFilter) { + ImageIO.write(view.takeGraphshot(width, height), + pngFilter.getExtension(), destinationFile); + } else { + final String outFilePath = destinationFile.getAbsolutePath(); + new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + YImageTools.writeSVGImage(view.getSBMLDocument().getModel(), view.getGraph().getGraph2D(), outFilePath, width, height); + return null; + } + }.execute(); } - ImageIO.write(view.takeGraphshot(width, height), - "png", destinationFile); - guiPrefs.put(GUIOptions.SAVE_DIR, - destinationFile.getParent()); + guiPrefs.put(GUIOptions.SAVE_DIR, destinationFile.getParent()); guiPrefs.flush(); logger.info(bundle.getString("SCREENSHOT_DONE")); } catch (IOException ioe) { - logger.warning(bundle - .getString("COULD_NOT_WRITE_SCREENSHOT")); + logger.warning(bundle.getString("COULD_NOT_WRITE_SCREENSHOT")); } catch (BackingStoreException exc) { logger.warning(getMessage(exc)); } } } + /** + * Opens window with the dynamic graph of metabolic concentrations + */ + public void concentrationGraph() { + Map minMaxValues = core.getId2minMaxData(); + Object[] helpIds = (Object[]) minMaxValues.keySet().toArray(); + String[] ids = new String[helpIds.length]; + for(int i = 0; i < helpIds.length; i++) { + ids[i] = (String) helpIds[i]; + } + double[] minMax = core.getMinMaxOfIDsForConcentrationGraph(ids); + double maxTime = core.getMaxTime(); + + MultiTable data = core.getData(); + LegendPanel legend = view.getLegendPanel(); + + graphWindow = new ConcentrationGraphUI(data, legend, minMax, maxTime); + } + + /** + * Sets a new timepoint for the cursor + * @param timepoint + */ + public void setNewTimepoint(double timepoint) { + if(graphWindow != null) { + graphWindow.setTimepoint(timepoint); + } + } + + /** + * checks if min max node size was changed and sets new node sizes + */ + public void setNewMinMaxNodeSize() { + IGraphManipulator currentManipulator = getSelectedGraphManipulator(); + String m = currentManipulator.toString(); + //if(currentManipulator.toString().equals("")) + currentManipulator.setNewMinMaxNodeSize(SBPreferences.getPreferencesFor(GraphOptions.class). + getDouble(GraphOptions.MIN_NODE_SIZE), SBPreferences.getPreferencesFor(GraphOptions.class). + getDouble(GraphOptions.MAX_NODE_SIZE)); + } + /** * Returns user selected {@link IGraphManipulator} with selected options. If * there isn't yet a {@link DynamicCore} assigned, return is null. @@ -394,6 +491,15 @@ public IGraphManipulator getSelectedGraphManipulator() { double maxNodeSize = prefs .getDouble(GraphOptions.MAX_NODE_SIZE); + double addSizeForOverview = 0; + if(!controlPanel.getCameraAnimationMode().equals(Items.NO_CAMERA_ANIMATION.getName()) + && core.getAnotherObserver() != null) { + if(camView == null) { + camView = (CameraAnimationView) core.getAnotherObserver(); + } + addSizeForOverview = camView.overviewSize; + } + if (prefs.getBoolean(GraphOptions.USE_UNIFORM_NODE_COLOR)) { return new ManipulatorOfNodeSize( view.getGraph(), @@ -401,80 +507,166 @@ public IGraphManipulator getSelectedGraphManipulator() { core, Option.parseOrCast(Color.class, prefs.get(GraphOptions.UNIFORM_NODE_COLOR)), - view.getSelectedSpecies(), view - .getSelectedReactions(), minNodeSize, - maxNodeSize, relativeConcentrations, - reactionsMinLineWidth, reactionsMaxLineWidth); + view.getSelectedSpecies(), view + .getSelectedReactions(), minNodeSize, + maxNodeSize, addSizeForOverview, true, + reactionsMinLineWidth, reactionsMaxLineWidth); } else { return new ManipulatorOfNodeSize(view.getGraph(), view.getSBMLDocument(), core, view.getLegendPanel() .getLegendTableModel(), view.getSelectedSpecies(), view.getSelectedReactions(), minNodeSize, - maxNodeSize, relativeConcentrations, + maxNodeSize, addSizeForOverview, true, reactionsMinLineWidth, reactionsMaxLineWidth); } } else if (controlPanel.getSelectedManipulator().equals(Manipulators.NODECOLOR.getName())) { - // get current options - Color color1 = Option.parseOrCast(Color.class, - prefs.get(GraphOptions.COLOR1)); + // this is needed for if and else case Color color2 = Option.parseOrCast(Color.class, prefs.get(GraphOptions.COLOR2)); - Color color3 = Option.parseOrCast(Color.class, - prefs.get(GraphOptions.COLOR3)); + double nodeSize = prefs.getDouble(GraphOptions.COLOR_NODE_SIZE); - return new ManipulatorOfNodeColor(view.getGraph(), - view.getSBMLDocument(), core, - view.getSelectedSpecies(), view.getSelectedReactions(), - relativeConcentrations, nodeSize, color1, color2, - color3, reactionsMinLineWidth, reactionsMaxLineWidth); + double addSizeForOverview = 0; + if(!controlPanel.getCameraAnimationMode().equals(Items.NO_CAMERA_ANIMATION.getName()) + && core.getAnotherObserver() != null) { + if(camView == null) { + camView = (CameraAnimationView) core.getAnotherObserver(); + } + addSizeForOverview = camView.overviewSize; + } + + if (prefs.getBoolean(GraphOptions.CHOOSE_OWN_NODE_COLORS)) { + // get current options + Color color1 = Option.parseOrCast(Color.class, + prefs.get(GraphOptions.COLOR1)); + Color color3 = Option.parseOrCast(Color.class, + prefs.get(GraphOptions.COLOR3)); + + return new ManipulatorOfNodeColor(view.getGraph(), + view.getSBMLDocument(), core, + view.getSelectedSpecies(), view.getSelectedReactions(), + relativeConcentrations, nodeSize, addSizeForOverview, color1, color2, + color3, reactionsMinLineWidth, reactionsMaxLineWidth); + } else { + return new ManipulatorOfNodeColor(view.getGraph(), + view.getSBMLDocument(), core, + view.getSelectedSpecies(), view.getSelectedReactions(), + true, nodeSize, addSizeForOverview, color2, reactionsMinLineWidth, + reactionsMaxLineWidth); + } } else if (controlPanel.getSelectedManipulator().equals(Manipulators.NODESIZE_AND_COLOR.getName())) { - // get current options - Color color1 = Option.parseOrCast(Color.class, - prefs.get(GraphOptions.COLOR1)); - Color color2 = Option.parseOrCast(Color.class, - prefs.get(GraphOptions.COLOR2)); - Color color3 = Option.parseOrCast(Color.class, - prefs.get(GraphOptions.COLOR3)); double minNodeSize = prefs .getDouble(GraphOptions.MIN_NODE_SIZE); double maxNodeSize = prefs .getDouble(GraphOptions.MAX_NODE_SIZE); - return new ManipulatorOfNodeSizeAndColor(view.getGraph(), - view.getSBMLDocument(), core, - view.getSelectedSpecies(), view.getSelectedReactions(), - minNodeSize, maxNodeSize, color1, color2, color3, - reactionsMinLineWidth, reactionsMaxLineWidth); - } else if (controlPanel.getSelectedManipulator().equals(Manipulators.NODECOLOR_AND_SIZE.getName())) { + double addSizeForOverview = 0; + if(!controlPanel.getCameraAnimationMode().equals(Items.NO_CAMERA_ANIMATION.getName()) + && core.getAnotherObserver() != null) { + if(camView == null) { + camView = (CameraAnimationView) core.getAnotherObserver(); + } + addSizeForOverview = camView.overviewSize; + } // get current options - Color color1 = Option.parseOrCast(Color.class, - prefs.get(GraphOptions.COLOR1)); Color color2 = Option.parseOrCast(Color.class, prefs.get(GraphOptions.COLOR2)); - Color color3 = Option.parseOrCast(Color.class, - prefs.get(GraphOptions.COLOR3)); + + if (prefs.getBoolean(GraphOptions.CHOOSE_OWN_NODE_COLORS)) { + Color color1 = Option.parseOrCast(Color.class, + prefs.get(GraphOptions.COLOR1)); + Color color3 = Option.parseOrCast(Color.class, + prefs.get(GraphOptions.COLOR3)); + + return new ManipulatorOfNodeSizeAndColor(view.getGraph(), + view.getSBMLDocument(), core, + view.getSelectedSpecies(), view.getSelectedReactions(), + minNodeSize, maxNodeSize, addSizeForOverview, color1, color2, color3, + reactionsMinLineWidth, reactionsMaxLineWidth); + } else { + return new ManipulatorOfNodeSizeAndColor(view.getGraph(), + view.getSBMLDocument(), core, view.getSelectedSpecies(), view.getSelectedReactions(), + minNodeSize, maxNodeSize, addSizeForOverview, color2); + } + } else if (controlPanel.getSelectedManipulator().equals(Manipulators.NODECOLOR_AND_SIZE.getName())) { + double minNodeSize = prefs .getDouble(GraphOptions.MIN_NODE_SIZE); double maxNodeSize = prefs .getDouble(GraphOptions.MAX_NODE_SIZE); - return new ManipulatorOfNodeColorAndSize(view.getGraph(), - view.getSBMLDocument(), core, - view.getSelectedSpecies(), view.getSelectedReactions(), - minNodeSize, maxNodeSize, color1, color2, color3, - reactionsMinLineWidth, reactionsMaxLineWidth); + double addSizeForOverview = 0; + if(!controlPanel.getCameraAnimationMode().equals(Items.NO_CAMERA_ANIMATION.getName()) + && core.getAnotherObserver() != null) { + if(camView == null) { + camView = (CameraAnimationView) core.getAnotherObserver(); + } + addSizeForOverview = camView.overviewSize; + } + + // get current options + Color color2 = Option.parseOrCast(Color.class, + prefs.get(GraphOptions.COLOR2)); + + if (prefs.getBoolean(GraphOptions.CHOOSE_OWN_NODE_COLORS)) { + Color color1 = Option.parseOrCast(Color.class, + prefs.get(GraphOptions.COLOR1)); + Color color3 = Option.parseOrCast(Color.class, + prefs.get(GraphOptions.COLOR3)); + + return new ManipulatorOfNodeColorAndSize(view.getGraph(), + view.getSBMLDocument(), core, + view.getSelectedSpecies(), view.getSelectedReactions(), + minNodeSize, maxNodeSize, addSizeForOverview, color1, color2, color3, + reactionsMinLineWidth, reactionsMaxLineWidth); + } else { + return new ManipulatorOfNodeColorAndSize(view.getGraph(), + view.getSBMLDocument(), core, + view.getSelectedSpecies(), view.getSelectedReactions(), minNodeSize, + maxNodeSize, addSizeForOverview, color2); + } + } else if (controlPanel.getSelectedManipulator().equals(Manipulators.FILL_LEVEL.getName())) { + + // get current options + Color color2 = Option.parseOrCast(Color.class, + prefs.get(GraphOptions.COLOR2)); + + double nodeSize = prefs.getDouble(GraphOptions.COLOR_NODE_SIZE); + + double addSizeForOverview = 0; + if(!controlPanel.getCameraAnimationMode().equals(Items.NO_CAMERA_ANIMATION.getName()) + && core.getAnotherObserver() != null) { + if(camView == null) { + camView = (CameraAnimationView) core.getAnotherObserver(); + } + addSizeForOverview = camView.overviewSize; + } + + if (prefs.getBoolean(GraphOptions.CHOOSE_OWN_NODE_COLORS)) { + Color color1 = Option.parseOrCast(Color.class, + prefs.get(GraphOptions.COLOR1)); + Color color3 = Option.parseOrCast(Color.class, + prefs.get(GraphOptions.COLOR3)); + + return new ManipulatorOfFillLevel(view.getGraph(), view.getSBMLDocument(), core, + view.getSelectedSpecies(), nodeSize, addSizeForOverview, color1, color2, color3); + } else { + return new ManipulatorOfFillLevel(view.getGraph(), view.getSBMLDocument(), core, + view.getSelectedSpecies(), nodeSize, addSizeForOverview, color2); + } } // in any other case return nodesize manipulator per default. return new ManipulatorOfNodeSize(view.getGraph(), view.getSBMLDocument(), core, view.getSelectedSpecies(), view.getSelectedReactions()); + } + return null; // do nothing if core isn't set yet. } @@ -497,11 +689,38 @@ public void itemStateChanged(ItemEvent ie) { view.setGraphManipulator(getSelectedGraphManipulator()); //update preferences on change SBPreferences.getPreferencesFor(GraphOptions.class).put( - cb.getName(), - Manipulators.getManipulator(ie.getItem().toString()).getName()); + cb.getName(), Manipulators.getManipulator(ie.getItem().toString()).getName()); } else if (cb.getName().equals(controlPanel.DATA_LIST)){ view.visualizeData(ie.getItem().toString()); - } + } else if(cb.getName().equals(GraphOptions.SHOW_CAMERA_ANIMATION.toString())) { + controlPanel.setCameraAnimationCombo(Items.getItem(ie.getItem().toString())); + SBPreferences.getPreferencesFor(GraphOptions.class).put(cb.getName(), + Items.getItem(ie.getItem().toString()).getName()); + if(!ie.getItem().equals(Items.NO_CAMERA_ANIMATION.getName())) { + if(camView == null) { + if (core.getAnotherObserver() == null) { + camView = new CameraAnimationView(); + camView.setGraph(view.getGraph().getGraph2D()); + core.setAnotherObserver(camView); + } else { + camView = (CameraAnimationView) core.getAnotherObserver(); + } + } + camView.checkForNewFile(); + camView.setDefaultPosition(view.getGraph().getGraph2D()); + camView.showOverviewAnimation(); + IGraphManipulator currentManipulator = getSelectedGraphManipulator(); + currentManipulator.setAddSizeForOverview(camView.overviewSize); + core.cameraAnimation = !controlPanel.getCameraAnimationMode().equals(Items.NO_CAMERA_ANIMATION.getName()); + core.playAgain = core.cameraAnimation; + } else { + IGraphManipulator currentManipulator = getSelectedGraphManipulator(); + currentManipulator.setAddSizeForOverview(0); + camView.resetCameraAnimation(); + core.cameraAnimation = !controlPanel.getCameraAnimationMode().equals(Items.NO_CAMERA_ANIMATION.getName()); + core.playAgain = core.cameraAnimation; + } + } } else if (ie.getSource() instanceof JCheckBox) { JCheckBox cb = (JCheckBox) ie.getSource(); if (cb.getName() != null) { @@ -517,8 +736,11 @@ public void itemStateChanged(ItemEvent ie) { logger.fine(getMessage(exc)); } } + if(name.equals("CYCLE_SIMULATION") && !cb.isSelected()) { + core.setCycle(false); + } } - } + } } /* (non-Javadoc) @@ -540,7 +762,9 @@ public void preferenceChange(PreferenceChangeEvent evt) { || evt.getKey().equals("COLOR1") || evt.getKey().equals("COLOR2") || evt.getKey().equals("COLOR3") - || evt.getKey().equals("COLOR_NODE_SIZE")) { + || evt.getKey().equals("COLOR_NODE_SIZE") + || evt.getKey().equals("CYCLE_SIMULATION") + || evt.getKey().equals("SHOW_CAMERA_ANIMATION")) { //ensure correct user inputs if (prefs.getDouble(GraphOptions.MAX_NODE_SIZE) <= prefs @@ -609,6 +833,11 @@ public void preferenceChange(PreferenceChangeEvent evt) { .getString(GraphOptions.SIM_SPEED_CHOOSER))); } + if(evt.getKey().equals("SHOW_CAMERA_ANIMATION")) { + controlPanel.setCameraAnimationCombo(Items.getItem(prefs + .getString(GraphOptions.SHOW_CAMERA_ANIMATION))); + } + if (evt.getKey().equals("VISUALIZATION_STYLE")) { controlPanel.setSelectedManipulator(Manipulators .getManipulator(prefs diff --git a/src/org/sbml/simulator/gui/graph/DynamicCore.java b/src/org/sbml/simulator/gui/graph/DynamicCore.java index 0c1cd17..145453f 100644 --- a/src/org/sbml/simulator/gui/graph/DynamicCore.java +++ b/src/org/sbml/simulator/gui/graph/DynamicCore.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -28,6 +26,7 @@ import javax.swing.SwingWorker; import org.sbml.jsbml.SBMLDocument; +import org.sbml.simulator.gui.graph.DynamicControlPanel.Items; import org.simulator.math.odes.MultiTable; import com.xuggle.mediatool.IMediaWriter; @@ -35,617 +34,792 @@ import de.zbit.gui.GUITools; import de.zbit.util.ResourceManager; +import de.zbit.util.prefs.SBPreferences; /** * Represents the core of the dynamic visualization and therefore the model in * MVC-pattern. Holds all necessary data and logic to run the dynamic * visualization. - * + * * @author Fabian Schwarzkopf - * @version $Rev$ */ public class DynamicCore { - /** - * A {@link SwingWorker} to cycle through all timepoints or video-encoding - * in background. This class is highly related to the {@link DynamicCore} - * and is therefore a private inner class. - * - * @author Fabian Schwarzkopf - * @version $Rev$ - */ - private class PlayWorker extends SwingWorker { - /** - * Sleeptime while waiting for notification. - */ - private final long AWAITING_GRAPH_DRAWING = 20; - - /** - * Enable/Disable video encoding. - */ - private boolean generateVideo = false; - - /** - * Video encoder. - */ - private IMediaWriter encoder; - - /** - * Timestamp and step size to capture images. - */ - private int timestamp, captureStepSize; - - /** - * Some control elements for video encoding. - */ - private int width, height, frameTime, image, totalimages; - - /** - * Switch to wait for graph update to be completed in order to - * synchronize graphupdating and picture taking. - * (Graphupdate -> picture -> Graphupdate -> picture -> ...) - */ - private volatile boolean awaitUpdate; - - /** - * Construct {@link PlayWorker} without video encoding. - */ - public PlayWorker() { - } - - /** - * Construct {@link PlayWorker} with implicit video encoding. - * - * @param generateVideo - * @param width - * @param height - * @param captureStepSize - * @param destinationFile - */ - public PlayWorker(boolean generateVideo, int width, int height, - int timestamp, int captureEveryXStep, String destinationFile) { - this(); - this.generateVideo = generateVideo; - captureStepSize = captureEveryXStep; - this.timestamp = timestamp; - this.width = width; - this.height = height; - frameTime = 0; - image = 1; - totalimages = (data.getRowCount() - 1) / captureEveryXStep; - encoder = ToolFactory.makeWriter(destinationFile); - logger.info(MessageFormat.format( - bundle.getString("GENERATE_VIDEO"), new Object[] { width, - height })); - encoder.addVideoStream(0, 0, width, height); - } - - /* (non-Javadoc) - * @see javax.swing.SwingWorker#doInBackground() - */ - @Override - protected Void doInBackground() throws Exception { - // cycle through timepoints - for (int i = getIndexOfTimepoint(currTimepoint) + 1; i < timePoints.length; i++) { - //turn on synchronization - if (generateVideo) { - awaitUpdate = true; - } - - //process timepoint in EDT - publish(timePoints[i]); - - if (!generateVideo) { - //wait in case of playing - Thread.sleep(playspeed); - } else { - //video generating - - if (i % captureStepSize == 0) { - - //await graph update of this particular timepoint - while (awaitUpdate) { - Thread.sleep(10); - } - - if (!isCancelled()) { - /* - * ensures that this thread is not encoding an image - * while the encoder gets closed by EDT. - */ - - //take and process image - logger.info(MessageFormat.format( - bundle.getString("PROCESSING_IMAGE"), - new Object[] { image, totalimages })); - encoder.encodeVideo(0, - observer.takeGraphshot(width, height), - frameTime, TimeUnit.MILLISECONDS); - /* - * fire property change to support things like - * progressBars. the fired new property is a number - * inbetween 0 and 100 representing the processed - * percentage. - */ - int perc = (int) ((image/(double)totalimages) * 100); - this.firePropertyChange("video_progress", null, perc); - image++; - frameTime += timestamp; // timestamp for video encoding - } - } - } - } - return null; - } - - /* (non-Javadoc) - * @see javax.swing.SwingWorker#done() - */ - @Override - protected void done() { - super.done(); - if (encoder != null) { - encoder.flush(); - encoder.close(); - if (image >= totalimages) { - logger.info(bundle.getString("VIDEOENCODING_DONE")); - } else if (isCancelled()) { - logger.info(bundle.getString("VIDEOENCODING_CANCELED")); - } else { - GUITools.showErrorMessage(null, bundle.getString("VIDEOENCODING_ERROR")); - } - //update progressBar - firePropertyChange("video_done", null, null); - } - - /* - * Notify observer. - */ - observer.donePlay(); - - /* - * Remove playworker. - */ - playWorker = null; - } - - /* (non-Javadoc) - * @see javax.swing.SwingWorker#process(java.util.List) - */ - @Override - protected void process(List chunks) { - /* - * Ensures that there are not set any more timepoints after calling - * stopPlay() such that the timepoint remains on the first given - * timepoint like stopPlay() is intented. - */ - if (!isCancelled()) { - for (Double timePoint : chunks) { - operationsDone = false; - setCurrTimepoint(timePoint); - - /* - * Wait till graph drawing is finished in case of large - * data. (Observer has to invoke operationsDone() after - * finished graph drawing). - */ - while (!operationsDone) { - try { - logger.fine("Waiting for graph drawing to be completed."); - Thread.sleep(AWAITING_GRAPH_DRAWING); - } catch (InterruptedException e) { - logger.fine("Could not wait for graph drawing to be completed."); - e.printStackTrace(); - } - } - } - - /* - * notify waiting thread about graph update. - */ - if (generateVideo) { - awaitUpdate = false; - } - } - } - } - - /** - * Localization support. - */ - private static final transient ResourceBundle bundle = ResourceManager - .getBundle("org.sbml.simulator.gui.graph.DynamicGraph"); - - /** - * A {@link Logger} for this class. - */ - private static final transient Logger logger = Logger - .getLogger(DynamicCore.class.getName()); - - /** - * Play thread worker. - */ - private PlayWorker playWorker; - - /** - * Notification if graph is updated. Gets changed by to threads, therefore - * volatile. - */ - private volatile boolean operationsDone; - - /** - * Saves the currently displayed timestep. To ensure that the first - * timepoint setted by construction is send to the observers, this field is - * initialized with -1. - */ - private double currTimepoint = -1; - - /** - * Saves the maximum simulated time. - */ - private double maxTime; - - /** - * Saves the minimum simulated time. By default zero. - */ - private double minTime = 0; - - /** - * Dynamic displayed data. - */ - private MultiTable data; - - /** - * List of all simulated timepoints - */ - private double[] timePoints; - - /** - * After computation of Limits this HashMap saves for each species or - * reaction min and max data value. - */ - private Map id2MinMaxData = new HashMap(); - - /** - * Current status of limits whether computed or not. Not computed by default - * to save constructing time if not needed. - */ - private boolean limitsComputed = false; - - /** - * Listener, which will be notified, when the current timestep changes. - */ - private IDynamicGraph observer; - - /** - * Determines the speed of the the play method. This is the time in - * miliseconds between each timepoint. By default 25. - */ - private int playspeed = 25; - - /** - * Constructs the core with an observer and simulation data. Does not - * provide any data limits directly after construction. - * - * @param observer - * @param data - */ - public DynamicCore(IDynamicGraph observer, MultiTable data) { - this.observer = observer; - setData(data); - } - - /** - * Constructs the core with an observer and simulation data. Does provide - * data limits, which will be implicit computed, therefore this constructor - * is in O(n^2). - * - * @param observer - * @param data - * @param document - */ - public DynamicCore(IDynamicGraph observer, MultiTable data, - SBMLDocument document) { - this(observer, data); - computeSpecificLimits(document); - } - - /** - * Computation of a Hashmap which saves for all species and references - * max/min values. O(n^2). - * - * @param document - * document needed to distinguish between reactions and species. - */ - public void computeSpecificLimits(SBMLDocument document) { - for (int i = 1; i < data.getColumnCount(); i++) { - double maxData = Double.MIN_VALUE; - double minData = Double.MAX_VALUE; - - /* - * only look through species/reactions columns in particular - */ - if (document.getModel().getSpecies(data.getColumnIdentifier(i)) != null) { - for (int j = 0; j < data.getRowCount(); j++) { - double tmpValue = data.getValueAt(j, i); - if (tmpValue < minData) { - minData = tmpValue; - } - if (tmpValue > maxData) { - maxData = tmpValue; - } - } - // min/max saved for this species - id2MinMaxData.put(data.getColumnIdentifier(i), new double[] { - minData, maxData }); - } else if (document.getModel().getReaction( - data.getColumnIdentifier(i)) != null) { - for (int j = 0; j < data.getRowCount(); j++) { - double tmpValue = data.getValueAt(j, i); - if (tmpValue < minData) { - minData = tmpValue; - } - if (tmpValue > maxData) { - maxData = tmpValue; - } - } - // min/max saved for this reaction - id2MinMaxData.put(data.getColumnIdentifier(i), new double[] { - minData, maxData }); - } - } - limitsComputed = true; - } - - /** - * Notifies observer about the change and delivers changed species & - * reactions to all registered {@link DynamicView}s. - */ - public void fireTimepointChanged() { - double[] currTimePoints = { currTimepoint }; - observer.updateGraph(currTimepoint, data.filter(currTimePoints)); - } - - /** - * Generates a video by cycling through every timestep and taking graphshots - * at given capturepoints. (PropertyChanges are fired to the related - * {@link DynamicView}). - * - * @param view - * @param width - * @param height - * @param timestamp - * @param captureEveryXstep - * @param destinationFile - */ - public void generateVideo(DynamicView view, int width, int height, - int timestamp, int captureEveryXstep, String destinationFile) { - // start off by zero time - currTimepoint = data.getTimePoint(0); - fireTimepointChanged(); - playspeed = 1; // as fast as possible - - if (playWorker == null) { - // generate video - playWorker = new PlayWorker(true, width, height, timestamp, - captureEveryXstep, destinationFile); - if (view != null) { - playWorker.addPropertyChangeListener(view); - } - playWorker.execute(); - } - } - - /** - * Generates a video by cycling through every timestep and taking graphshots - * at given capturepoints. (propertyChanges are not fired). - * - * @param width - * @param height - * @param timestamp - * @param captureEveryXstep - * @param destinationFile - */ - public void generateVideo(int width, int height, int timestamp, - int captureEveryXstep, String destinationFile) { - generateVideo(null, width, height, timestamp, captureEveryXstep, - destinationFile); - } - - /** - * Returns data for the current timepoint. - * - * @return - */ - public MultiTable getCurrData() { - double[] currTimePoints = { currTimepoint }; - return data.filter(currTimePoints); - } - - /** - * Get the current timepoint of the core. - * - * @return - */ - public double getCurrTimepoint() { - return currTimepoint; - } - - /** - * Returns mapping from every species or reactions id to their specific - * minimum value and maximum value, if computed. - * - * @return - */ - public Map getId2minMaxData() { - return limitsComputed ? id2MinMaxData : null; - } - - /** - * Searches the index of a given timepoint. - * - * @param timepoint - * @return index of the timepoint, if not found, then -1 - */ - public int getIndexOfTimepoint(double timepoint) { - int searchedIndex = -1; - for (int i = 0; i < timePoints.length; i++) { - if (timepoint == timePoints[i]) { - searchedIndex = i; - } - } - return searchedIndex; - } - - /** - * Get the maximum timepoint of the core. - * - * @return - */ - public double getMaxTime() { - return maxTime; - } - - /** - * If limits computed it returns a double array whose first element is the - * minimum data of the given ids, and second element is the maximum data of - * given ids. Otherwise null. - * - * @param ids - * @return - */ - public double[] getMinMaxOfIDs(String... ids) { - if (limitsComputed) { - double minData = Double.MAX_VALUE; - double maxData = Double.MIN_VALUE; - for (String id : ids) { - if (id2MinMaxData.containsKey(id)) { - double[] dataOfID = id2MinMaxData.get(id); - if (dataOfID[0] < minData) { - minData = dataOfID[0]; - } - if (dataOfID[1] > maxData) { - maxData = dataOfID[1]; - } - } - } - return new double[] { minData, maxData }; - } else { - return null; - } - } - - /** - * Get the speed of cycling through all timepoints with the play method. - * - * @return - */ - public int getPlayspeed() { - return playspeed; - } - - /** - * Get timepoints of the simulation. - * - * @return - */ - public double[] getTimepoints() { - return timePoints; - } - - /** - * Notifies the play worker, that the graph is ready for the next timepoint. - * (Graph drawing completed). - */ - public void operationsDone() { - operationsDone = true; - } - - /** - * Pauses the play worker. - */ - public void pausePlay() { - if (playWorker != null) { - playWorker.cancel(true); - playWorker = null; - } - } - - /** - * Cycles through all saved timepoints (ongoing from the current timepoint) - * and additionally updates the graph. - */ - public void play() { - if (playWorker == null) { - // start from the beginning, if currently the last timepoint is set. - if (currTimepoint == timePoints[timePoints.length - 1]) { - setCurrTimepoint(0); - } - playWorker = new PlayWorker(); - playWorker.execute(); - } - } - - /** - * Set the current time displayed by the graph. - * - * @param time - */ - public void setCurrTimepoint(double time) { - if ((currTimepoint != time) && (time >= minTime) && (time <= maxTime)) { - this.currTimepoint = time; - fireTimepointChanged(); - } - } - - /** - * Set the current time displayed by the graph to the given rowIndex of the - * data. - * - * @param time - */ - public void setCurrTimepoint(int rowIndex) { - double incomingTimepoint = data.getTimePoint(rowIndex); - if ((currTimepoint != incomingTimepoint) && (incomingTimepoint >= minTime) - && (incomingTimepoint <= maxTime)) { - this.currTimepoint = incomingTimepoint; - fireTimepointChanged(); - } - } - - /** - * Set simulated data and the current timepoint to the first entry of the - * given data. - * - * @param data - */ - public void setData(MultiTable data) { - this.data = data; - timePoints = data.getTimePoints(); - minTime = data.getTimePoint(0); - maxTime = data.getTimePoint(data.getRowCount() - 1); - currTimepoint = data.getTimePoint(0); - } - - /** - * Set the speed of cycling through all timepoints with the play method. - * - * @param speed - */ - public void setPlayspeed(int speed) { - playspeed = speed; - } - - /** - * Stops the play worker if working, and/or sets timepoint to first - * timepoint in data - */ - public void stopPlay() { - if (playWorker != null) { - playWorker.cancel(true); - playWorker = null; - } - currTimepoint = data.getTimePoint(0); - fireTimepointChanged(); - } + /** + * A {@link SwingWorker} to cycle through all timepoints or video-encoding + * in background. This class is highly related to the {@link DynamicCore} + * and is therefore a private inner class. + * + * @author Fabian Schwarzkopf + * @author Lea Buchweitz + */ + + /** + * enable/disable loop of animation + */ + public static boolean loop = GraphOptions.CYCLE_SIMULATION.getValue( + SBPreferences.getPreferencesFor(GraphOptions.class));; + + /** + * deal with camera animation, first simulation is overview, second with animation path + */ + public static boolean cameraAnimation; + + /** + * handles one more simulation loop for camera animation + */ + public static boolean playAgain; + + private class PlayWorker extends SwingWorker { + /** + * Sleeptime while waiting for notification. + */ + private final long AWAITING_GRAPH_DRAWING = 20; + + + /** + * Enable/Disable video encoding. + */ + private boolean generateVideo = false; + + /** + * Video encoder. + */ + private IMediaWriter encoder; + + /** + * Timestamp and step size to capture images. + */ + private int timestamp, captureStepSize; + + /** + * Some control elements for video encoding. + */ + private int width, height, frameTime, image, totalimages; + + /** + * Switch to wait for graph update to be completed in order to + * synchronize graphupdating and picture taking. + * (Graphupdate -> picture -> Graphupdate -> picture -> ...) + */ + private volatile boolean awaitUpdate; + + /** + * Construct {@link PlayWorker} without video encoding. + */ + public PlayWorker() { + } + + /** + * Construct {@link PlayWorker} with implicit video encoding. + * + * @param generateVideo + * @param width + * @param height + * @param captureStepSize + * @param destinationFile + */ + public PlayWorker(boolean generateVideo, int width, int height, + int timestamp, int captureEveryXStep, String destinationFile) { + this(); + this.generateVideo = generateVideo; + captureStepSize = captureEveryXStep; + this.timestamp = timestamp; + this.width = width; + this.height = height; + frameTime = 0; + image = 1; + + totalimages = (data.getRowCount() - 1) / captureEveryXStep; + + if(cameraAnimation) { + totalimages *= 2; + } + + encoder = ToolFactory.makeWriter(destinationFile); + logger.info(MessageFormat.format( + bundle.getString("GENERATE_VIDEO"), new Object[] { width, + height })); + encoder.addVideoStream(0, 0, width, height); + } + + /* (non-Javadoc) + * @see javax.swing.SwingWorker#doInBackground() + */ + @Override + protected Void doInBackground() throws Exception { + // cycle through timepoints + for (int i = getIndexOfTimepoint(currTimepoint) + 1; i < timePoints.length; i++) { + + //turn on synchronization + if (generateVideo) { + awaitUpdate = true; + } + + //process timepoint in EDT + publish(timePoints[i]); + + if (!generateVideo) { + //wait in case of playing + Thread.sleep(playspeed); + } else { + //video generating + + if ((i % captureStepSize) == 0) { + + //await graph update of this particular timepoint + while (awaitUpdate) { + Thread.sleep(1000); + } + + if (!isCancelled()) { + /* + * ensures that this thread is not encoding an image + * while the encoder gets closed by EDT. + */ + + //take and process image + logger.info(MessageFormat.format( + bundle.getString("PROCESSING_IMAGE"), + new Object[] { image, totalimages })); + encoder.encodeVideo(0, + observer.takeGraphshot(width, height), + frameTime, TimeUnit.MILLISECONDS); + /* + * fire property change to support things like + * progressBars. the fired new property is a number + * inbetween 0 and 100 representing the processed + * percentage. + */ + int perc = (int) ((image/(double)totalimages) * 100); + this.firePropertyChange("video_progress", null, perc); + image++; + frameTime += timestamp; // timestamp for video encoding + } + } + if(cameraAnimation && (i == (timePoints.length-1))) { + if(playAgain) { + restartSimulationForAnimation(); + i = 0; + continue; + } else { + setPlayspeed(Items.getSpeed(Items.getItem + (SBPreferences.getPreferencesFor(GraphOptions.class).getString("SIM_SPEED_CHOOSER")))); + DynamicCore.resetToNextSimulationLoop(); + } + } + } + } + return null; + } + + /* (non-Javadoc) + * @see javax.swing.SwingWorker#done() + */ + @Override + protected void done() { + super.done(); + + if(cameraAnimation && !generateVideo) { + if(playAgain) { + restartSimulationForAnimation(); + return; + } else { + setPlayspeed(Items.getSpeed(Items.getItem + (SBPreferences.getPreferencesFor(GraphOptions.class).getString("SIM_SPEED_CHOOSER")))); + DynamicCore.resetToNextSimulationLoop(); + } + } + + if (encoder != null) { + + encoder.flush(); + encoder.close(); + if (image >= totalimages) { + logger.info(bundle.getString("VIDEOENCODING_DONE")); + } else if (isCancelled()) { + logger.info(bundle.getString("VIDEOENCODING_CANCELED")); + } else { + GUITools.showErrorMessage(null, bundle.getString("VIDEOENCODING_ERROR")); + } + //update progressBar + firePropertyChange("video_done", null, null); + } + + /* + * Notify observer. + */ + observer.donePlay(); + + /* + * Remove playworker. + */ + if(playWorker != null) { + playWorker.cancel(true); + playWorker = null; + } + + if(loop) { + try { + Thread.sleep(1500); + } catch (InterruptedException e) { e.printStackTrace(); } + play(); + } + } + + /* (non-Javadoc) + * @see javax.swing.SwingWorker#process(java.util.List) + */ + @Override + protected void process(List chunks) { + /* + * Ensures that there are not set any more timepoints after calling + * stopPlay() such that the timepoint remains on the first given + * timepoint like stopPlay() is intented. + */ + if (!isCancelled()) { + for (Double timePoint : chunks) { + operationsDone = false; + setCurrTimepoint(timePoint); + + /* + * Wait till graph drawing is finished in case of large + * data. (Observer has to invoke operationsDone() after + * finished graph drawing). + */ + while (!operationsDone) { + try { + logger.fine("Waiting for graph drawing to be completed."); + Thread.sleep(AWAITING_GRAPH_DRAWING); + } catch (InterruptedException e) { + logger.fine("Could not wait for graph drawing to be completed."); + e.printStackTrace(); + } + } + } + + /* + * notify waiting thread about graph update. + */ + if (generateVideo) { + awaitUpdate = false; + } + } + } + + /** + * restarts the simulation for the animation + */ + private void restartSimulationForAnimation() { + if((playWorker != null) && !generateVideo) { + playWorker.cancel(true); + playWorker = null; + } + try { + CameraAnimationView.resizeNodes(); + setPlayspeed(Items.getSpeed(Items.getItem + (SBPreferences.getPreferencesFor(GraphOptions.class).getString("SHOW_CAMERA_ANIMATION")))); + Thread.sleep(1000); + } catch (InterruptedException e) { e.printStackTrace(); } + + if(!generateVideo) { + play(); + } + playAgain = false; + + } + } + + /** + * Localization support. + */ + private static final transient ResourceBundle bundle = ResourceManager + .getBundle("org.sbml.simulator.gui.graph.DynamicGraph"); + + /** + * A {@link Logger} for this class. + */ + private static final transient Logger logger = Logger + .getLogger(DynamicCore.class.getName()); + + /** + * Play thread worker. + */ + private PlayWorker playWorker; + + /** + * Notification if graph is updated. Gets changed by to threads, therefore + * volatile. + */ + private volatile boolean operationsDone; + + /** + * Saves the currently displayed timestep. To ensure that the first + * timepoint setted by construction is send to the observers, this field is + * initialized with -1. + */ + private double currTimepoint = -1; + + /** + * Saves the maximum simulated time. + */ + private double maxTime; + + /** + * Saves the minimum simulated time. By default zero. + */ + private double minTime = 0; + + /** + * Dynamic displayed data. + */ + private MultiTable data; + + /** + * List of all simulated timepoints + */ + private double[] timePoints; + + /** + * After computation of Limits this HashMap saves for each species or + * reaction min and max data value. + */ + private Map id2MinMaxData = new HashMap(); + + /** + * Current status of limits whether computed or not. Not computed by default + * to save constructing time if not needed. + */ + private boolean limitsComputed = false; + + /** + * Listener, which will be notified, when the current timestep changes. + */ + private IDynamicGraph observer; + + /** + * another listener which will be notified about timestep changes if a camera animation should be displayed + */ + protected static IDynamicGraph cameraWay; + + /** + * Determines the speed of the the play method. This is the time in + * miliseconds between each timepoint. By default 25. + */ + private int playspeed = 25; + + /** + * Constructs the core with an observer and simulation data. Does not + * provide any data limits directly after construction. + * + * @param observer + * @param data + */ + public DynamicCore(IDynamicGraph observer, MultiTable data) { + this.observer = observer; + setData(data); + } + + public static void resetToNextSimulationLoop() { + ((CameraAnimationView) cameraWay).showOverviewAnimation(); + ((CameraAnimationView) cameraWay).resetToNextSimulationLoop(); + } + + /** + * Constructs the core with an observer and simulation data. Does provide + * data limits, which will be implicit computed, therefore this constructor + * is in O(n^2). + * + * @param observer + * @param data + * @param document + */ + public DynamicCore(IDynamicGraph observer, MultiTable data, + SBMLDocument document) { + this(observer, data); + computeSpecificLimits(document); + } + + /** + * Computation of a Hashmap which saves for all species and references + * max/min values. O(n^2). + * + * @param document + * document needed to distinguish between reactions and species. + */ + public void computeSpecificLimits(SBMLDocument document) { + for (int i = 1; i < data.getColumnCount(); i++) { + double maxData = Double.MIN_VALUE; + double minData = Double.MAX_VALUE; + + /* + * only look through species/reactions columns in particular + */ + if (document.getModel().getSpecies(data.getColumnIdentifier(i)) != null) { + for (int j = 0; j < data.getRowCount(); j++) { + double tmpValue = data.getValueAt(j, i); + if (tmpValue < minData) { + minData = tmpValue; + } + if (tmpValue > maxData) { + maxData = tmpValue; + } + } + // min/max saved for this species + id2MinMaxData.put(data.getColumnIdentifier(i), new double[] { + minData, maxData }); + } else if (document.getModel().getReaction( + data.getColumnIdentifier(i)) != null) { + for (int j = 0; j < data.getRowCount(); j++) { + double tmpValue = data.getValueAt(j, i); + if (tmpValue < minData) { + minData = tmpValue; + } + if (tmpValue > maxData) { + maxData = tmpValue; + } + } + // min/max saved for this reaction + id2MinMaxData.put(data.getColumnIdentifier(i), new double[] { + minData, maxData }); + } + } + limitsComputed = true; + } + + /** + * Notifies observer about the change and delivers changed species & + * reactions to all registered {@link DynamicView}s. + */ + public void fireTimepointChanged() { + double[] currTimePoints = { currTimepoint }; + observer.updateGraph(currTimepoint, data.filter(currTimePoints)); + if(cameraAnimation) { + if ((observer instanceof DynamicView) && (cameraWay != null) && (((CameraAnimationView) cameraWay).core == null)) { + ((CameraAnimationView) cameraWay).setGraph(((DynamicView) observer).getGraph().getGraph2D()); + ((CameraAnimationView) cameraWay).setTimeLine(maxTime); + ((CameraAnimationView) cameraWay).setZoom(); + ((CameraAnimationView) cameraWay).setCore(this); + if (playAgain) { + ((CameraAnimationView) cameraWay).showOverviewAnimation(); + } + } + cameraWay.updateGraph(currTimepoint, data.filter(currTimePoints)); + } + } + + /** + * Generates a video by cycling through every timestep and taking graphshots + * at given capturepoints. (PropertyChanges are fired to the related + * {@link DynamicView}). + * + * @param view + * @param width + * @param height + * @param timestamp + * @param captureEveryXstep + * @param destinationFile + */ + public void generateVideo(DynamicView view, int width, int height, + int timestamp, int captureEveryXstep, String destinationFile) { + // start off by zero time + currTimepoint = data.getTimePoint(0); + fireTimepointChanged(); + playspeed = 1; // as fast as possible + + if (playWorker == null) { + // generate video + playWorker = new PlayWorker(true, width, height, timestamp, + captureEveryXstep, destinationFile); + if (view != null) { + playWorker.addPropertyChangeListener(view); + } + playWorker.execute(); + } + } + + /** + * Generates a video by cycling through every timestep and taking graphshots + * at given capturepoints. (propertyChanges are not fired). + * + * @param width + * @param height + * @param timestamp + * @param captureEveryXstep + * @param destinationFile + */ + public void generateVideo(int width, int height, int timestamp, + int captureEveryXstep, String destinationFile) { + generateVideo(null, width, height, timestamp, captureEveryXstep, + destinationFile); + } + + /** + * Returns data for the current timepoint. + * + * @return + */ + public MultiTable getCurrData() { + double[] currTimePoints = { currTimepoint }; + return data.filter(currTimePoints); + } + + /** + * Returns current data + */ + public MultiTable getData() { + return data; + } + + /** + * Get the current timepoint of the core. + * + * @return + */ + public double getCurrTimepoint() { + return currTimepoint; + } + + /** + * Returns mapping from every species or reactions id to their specific + * minimum value and maximum value, if computed. + * + * @return + */ + public Map getId2minMaxData() { + return limitsComputed ? id2MinMaxData : null; + } + + /** + * Searches the index of a given timepoint. + * + * @param timepoint + * @return index of the timepoint, if not found, then -1 + */ + public int getIndexOfTimepoint(double timepoint) { + int searchedIndex = -1; + for (int i = 0; i < timePoints.length; i++) { + if (timepoint == timePoints[i]) { + searchedIndex = i; + } + } + return searchedIndex; + } + + /** + * Get the maximum timepoint of the core. + * + * @return + */ + public double getMaxTime() { + return maxTime; + } + + /** + * If limits computed it returns a double array whose first element is the + * minimum data of the given ids, and second element is the maximum data of + * given ids. Otherwise null. + * + * @param ids + * @return + */ + public double[] getMinMaxOfIDs(String... ids) { + if (limitsComputed) { + double minData = Double.MAX_VALUE; + double maxData = Double.MIN_VALUE; + for (String id : ids) { + if (id2MinMaxData.containsKey(id)) { + double[] dataOfID = id2MinMaxData.get(id); + if (dataOfID[0] < minData) { + minData = dataOfID[0]; + } + if (dataOfID[1] > maxData) { + maxData = dataOfID[1]; + } + } + } + return new double[] { minData, maxData }; + } else { + return null; + } + } + + /** + * If limits computed it returns a double array whose first element is the + * minimum data of the given ids, and second element is the maximum data of + * given ids. Otherwise null. And checks in contrast to the upper function if + * a concentration is lower than 0 + * + * @param ids + * @return + */ + public double[] getMinMaxOfIDsForConcentrationGraph(String... ids) { + if (limitsComputed) { + double minData = Double.MAX_VALUE; + double maxData = Double.MIN_VALUE; + for (String id : ids) { + if (id2MinMaxData.containsKey(id)) { + double[] dataOfID = id2MinMaxData.get(id); + if ((dataOfID[0] < minData) && !(dataOfID[0] < 0)) { + minData = dataOfID[0]; + } + if (dataOfID[1] > maxData) { + maxData = dataOfID[1]; + } + } + } + return new double[] { minData, maxData }; + } else { + return null; + } + } + + /** + * Get the speed of cycling through all timepoints with the play method. + * + * @return + */ + public int getPlayspeed() { + return playspeed; + } + + /** + * Get timepoints of the simulation. + * + * @return + */ + public double[] getTimepoints() { + return timePoints; + } + + /** + * Notifies the play worker, that the graph is ready for the next timepoint. + * (Graph drawing completed). + */ + public void operationsDone() { + operationsDone = true; + } + + /** + * Pauses the play worker. + */ + public void pausePlay() { + if (playWorker != null) { + playWorker.cancel(true); + playWorker = null; + } + } + + /** + * Cycles through all saved timepoints (ongoing from the current timepoint) + * and additionally updates the graph. + */ + public void play() { + setCycle(GraphOptions.CYCLE_SIMULATION.getValue(SBPreferences.getPreferencesFor(GraphOptions.class))); + + if (playWorker == null) { + // start from the beginning, if currently the last timepoint is set. + if (currTimepoint == timePoints[timePoints.length - 1]) { + setCurrTimepoint(0); + } + playWorker = new PlayWorker(); + playWorker.execute(); + + if(cameraAnimation) { + playAgain = true; + } + } + } + + /** + * Set the current time displayed by the graph. + * + * @param time + */ + public void setCurrTimepoint(double time) { + if ((currTimepoint != time) && (time >= minTime) && (time <= maxTime)) { + this.currTimepoint = time; + fireTimepointChanged(); + } + } + + /** + * Set the current time displayed by the graph to the given rowIndex of the + * data. + * + * @param time + */ + public void setCurrTimepoint(int rowIndex) { + double incomingTimepoint = data.getTimePoint(rowIndex); + if ((currTimepoint != incomingTimepoint) && (incomingTimepoint >= minTime) + && (incomingTimepoint <= maxTime)) { + this.currTimepoint = incomingTimepoint; + fireTimepointChanged(); + } + } + + /** + * Set simulated data and the current timepoint to the first entry of the + * given data. + * + * @param data + */ + public void setData(MultiTable data) { + this.data = data; + timePoints = data.getTimePoints(); + minTime = data.getTimePoint(0); + maxTime = data.getTimePoint(data.getRowCount() - 1); + currTimepoint = data.getTimePoint(0); + } + + /** + * Set the speed of cycling through all timepoints with the play method. + * + * @param speed + */ + public void setPlayspeed(int speed) { + playspeed = speed; + } + + /** + * Sets a loop to the simulation if true + * @param cycle + */ + public void setCycle(boolean cycle) { + loop = cycle; + } + + /** + * sets the new IDynamicGraph implementation of CameraAnimationView as second observer to + * call updateGraph() as well for this class (animation of camera is done with that) + * @param observer + */ + public void setAnotherObserver(IDynamicGraph observer) { + cameraWay = observer; + } + + public IDynamicGraph getAnotherObserver() { + return cameraWay; + } + + /** + * Stops the play worker if working, and/or sets timepoint to first + * timepoint in data + */ + public void stopPlay() { + if(loop) { + setCycle(false); + } else { + setCycle(GraphOptions.CYCLE_SIMULATION.getValue( + SBPreferences.getPreferencesFor(GraphOptions.class))); + } + + if (playWorker != null) { + playWorker.cancel(true); + playWorker = null; + } + currTimepoint = data.getTimePoint(0); + fireTimepointChanged(); + + } } diff --git a/src/org/sbml/simulator/gui/graph/DynamicView.java b/src/org/sbml/simulator/gui/graph/DynamicView.java index 621f5b8..322ccdd 100644 --- a/src/org/sbml/simulator/gui/graph/DynamicView.java +++ b/src/org/sbml/simulator/gui/graph/DynamicView.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -58,7 +56,6 @@ * of associated {@link DynamicCore}. * * @author Fabian Schwarzkopf - * @version $Rev$ */ public class DynamicView extends JSplitPane implements IDynamicGraph, PropertyChangeListener { @@ -67,10 +64,9 @@ public class DynamicView extends JSplitPane implements IDynamicGraph, * Stores all available {@link IGraphManipulator}s. * * @author Fabian Schwarzkopf - * @version $Rev$ */ public enum Manipulators { - NODESIZE, NODECOLOR, NODESIZE_AND_COLOR, NODECOLOR_AND_SIZE; + NODESIZE, NODECOLOR, NODESIZE_AND_COLOR, NODECOLOR_AND_SIZE, FILL_LEVEL; /** * Returns a string array of all manipulators. @@ -79,7 +75,7 @@ public enum Manipulators { */ public static String[] getAllManipulators() { return new String[] { NODESIZE.getName(), NODECOLOR.getName(), - NODESIZE_AND_COLOR.getName(), NODECOLOR_AND_SIZE.getName() }; + NODESIZE_AND_COLOR.getName(), NODECOLOR_AND_SIZE.getName(), FILL_LEVEL.getName() }; } /** @@ -96,6 +92,8 @@ public static Manipulators getManipulator(String manipulatorName) { return NODESIZE_AND_COLOR; } else if (manipulatorName.equals(bundle.getString("NODECOLOR_AND_SIZE"))) { return NODECOLOR_AND_SIZE; + } else if (manipulatorName.equals(bundle.getString("FILL_LEVEL"))) { + return FILL_LEVEL; } return null; } @@ -374,7 +372,9 @@ protected void done() { */ @Override public void donePlay() { - controlPanel.setStopStatus(); + if(!GraphOptions.CYCLE_SIMULATION.getValue(SBPreferences.getPreferencesFor(GraphOptions.class))) { + controlPanel.setStopStatus(); + } setEnabled(true); //ensure that view is enabled setEnableLegend(true); controlPanel.setStatusString(null); //no displayed status @@ -652,6 +652,8 @@ public void updateGraph() { public void updateGraph(double timepoint, MultiTable updateThem) { // update JSlider (in case of "play") controlPanel.setSearchbarValue(timepoint); + // to update the cursor in the concentration Graph + controller.setNewTimepoint(timepoint); if (graphManipulator != null) { for (int i = 1; i < updateThem.getColumnCount(); i++) { diff --git a/src/org/sbml/simulator/gui/graph/GraphOptions.java b/src/org/sbml/simulator/gui/graph/GraphOptions.java index 0cb6826..2e76213 100644 --- a/src/org/sbml/simulator/gui/graph/GraphOptions.java +++ b/src/org/sbml/simulator/gui/graph/GraphOptions.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -18,12 +16,14 @@ package org.sbml.simulator.gui.graph; import java.awt.Color; +import java.io.File; import java.util.ResourceBundle; import org.sbml.simulator.gui.graph.DynamicControlPanel.Items; import org.sbml.simulator.gui.graph.DynamicView.Manipulators; import de.zbit.gui.ColorPalette; +import de.zbit.io.filefilter.SBFileFilter; import de.zbit.util.ResourceManager; import de.zbit.util.prefs.KeyProvider; import de.zbit.util.prefs.Option; @@ -35,215 +35,245 @@ * Options for dynamic visualization. * * @author Fabian Schwarzkopf - * @version $Rev$ */ public interface GraphOptions extends KeyProvider { - /** - * The bundle for the user's current language. - */ - public static final ResourceBundle bundle = ResourceManager - .getBundle("org.sbml.simulator.gui.graph.DynamicGraph"); - - /** - * Choose visualization-style. - */ - public static final Option VISUALIZATION_STYLE = new Option( - "VISUALIZATION_STYLE", String.class, bundle, new Range( - String.class, Manipulators.getAllManipulators()), - Manipulators.NODESIZE.getName()); - - /** - * Switch for node labels. - */ - public static final Option SHOW_NODE_LABELS = new Option( - "SHOW_NODE_LABELS", Boolean.class, bundle, Boolean.FALSE); - - /** - * Switch for reaction labels. - */ - public static final Option SHOW_REACTION_LABELS = new Option( - "SHOW_REACTION_LABELS", Boolean.class, bundle, Boolean.FALSE); - - /** - * Enable/Disable relative change of concentrations. - */ - public static final Option RELATIVE_CONCENTRATION_CHANGES = new Option( - "RELATIVE_CONCENTRATION_CHANGES", Boolean.class, bundle, Boolean.FALSE); - - /** - * Enable/Disable interpolation of added experimental data. - */ - public static final Option INTERPOLATE_EXP_DATA = new Option( - "INTERPOLATE_EXP_DATA", Boolean.class, bundle, Boolean.TRUE); - - /** - * In case of dynamic node size change, it defines the minimum node size. - */ - public static final Option MIN_NODE_SIZE = new Option( - "MIN_NODE_SIZE", Double.class, bundle, new Range( - Double.class, "{(0, 1E3]}"), Double.valueOf(15d)); - - /** - * In case of dynamic node size change, it defines the maximum node size. - */ - public static final Option MAX_NODE_SIZE = new Option( - "MAX_NODE_SIZE", Double.class, bundle, new Range( - Double.class, "{(0, 1E3]}"), Double.valueOf(50d)); - - /** - * Switch for uniform node colors. - */ - public static final Option USE_UNIFORM_NODE_COLOR = new Option( - "USE_UNIFORM_NODE_COLOR", Boolean.class, bundle, Boolean.FALSE); - - /** - * Color for uniform node color. - */ - public static final Option UNIFORM_NODE_COLOR = new Option( - "UNIFORM_NODE_COLOR", Color.class, bundle, ColorPalette.SECOND_292); - - /** - * Color for high concentration. - */ - public static final Option COLOR1 = new Option( - "COLOR1", Color.class, bundle, ColorPalette.SECOND_180); - - /** - * Color for middle concentration - */ - public static final Option COLOR2 = new Option( - "COLOR2", Color.class, bundle, Color.WHITE); - - /** - * Color for low concentration - */ - public static final Option COLOR3 = new Option( - "COLOR3", Color.class, bundle, ColorPalette.SECOND_3015); - - /** - * Node size while color interpolation. - */ - public static final Option COLOR_NODE_SIZE = new Option( - "COLOR_NODE_SIZE", Double.class, bundle, new Range( - Double.class, "{(0, 1E3]}"), Double.valueOf(30d)); - - /** - * Determines the minimum line width of dynamic reaction visualization. - */ - public static final Option MIN_LINE_WIDTH = new Option( - "MIN_LINE_WIDTH", Double.class, bundle, new Range( - Double.class, "{(0, 1E2]}"), Double.valueOf(1d)); - - /** - * Determines the maximum line width of dynamic reaction visualization. - */ - public static final Option MAX_LINE_WIDTH = new Option( - "MAX_LINE_WIDTH", Double.class, bundle, new Range( - Double.class, "{(0, 1E3]}"), Double.valueOf(6d)); - - /** - * Sets the fast simulation speed. - */ - public static final Option SIM_SPEED_FAST = new Option( - "SIM_SPEED_FAST", Double.class, bundle, new Range( - Double.class, "{[1, 1E3]}"), Double.valueOf(5d)); - - /** - * Sets the normal simulation speed. - */ - public static final Option SIM_SPEED_NORMAL = new Option( - "SIM_SPEED_NORMAL", Double.class, bundle, new Range( - Double.class, "{[1, 1E3]}"), Double.valueOf(25d)); - - /** - * Sets the slow simulation speed. - */ - public static final Option SIM_SPEED_SLOW = new Option( - "SIM_SPEED_SLOW", Double.class, bundle, new Range( - Double.class, "{[1, 1E3]}"), Double.valueOf(80d)); - - /** - * Choose simulation speed. - */ + /** + * The bundle for the user's current language. + */ + public static final ResourceBundle bundle = ResourceManager + .getBundle("org.sbml.simulator.gui.graph.DynamicGraph"); + + /** + * Choose visualization-style. + */ + public static final Option VISUALIZATION_STYLE = new Option( + "VISUALIZATION_STYLE", String.class, bundle, new Range( + String.class, Manipulators.getAllManipulators()), + Manipulators.NODESIZE.getName()); + + /** + * Switch for node labels. + */ + public static final Option SHOW_NODE_LABELS = new Option( + "SHOW_NODE_LABELS", Boolean.class, bundle, Boolean.FALSE); + + /** + * Switch for reaction labels. + */ + public static final Option SHOW_REACTION_LABELS = new Option( + "SHOW_REACTION_LABELS", Boolean.class, bundle, Boolean.FALSE); + + /** + * Switch for cycle simulation. + */ + public static final Option CYCLE_SIMULATION = new Option( + "CYCLE_SIMULATION", Boolean.class, bundle, Boolean.FALSE); + + /** + * Enable/Disable relative change of concentrations. + */ + public static final Option RELATIVE_CONCENTRATION_CHANGES = new Option( + "RELATIVE_CONCENTRATION_CHANGES", Boolean.class, bundle, Boolean.FALSE); + + /** + * Enable/Disable interpolation of added experimental data. + */ + public static final Option INTERPOLATE_EXP_DATA = new Option( + "INTERPOLATE_EXP_DATA", Boolean.class, bundle, Boolean.TRUE); + + /** + * In case of dynamic node size change, it defines the minimum node size. + */ + public static final Option MIN_NODE_SIZE = new Option( + "MIN_NODE_SIZE", Double.class, bundle, new Range( + Double.class, "{(0, 1E3]}"), Double.valueOf(15d)); + + /** + * In case of dynamic node size change, it defines the maximum node size. + */ + public static final Option MAX_NODE_SIZE = new Option( + "MAX_NODE_SIZE", Double.class, bundle, new Range( + Double.class, "{(0, 1E3]}"), Double.valueOf(50d)); + + /** + * Switch for uniform node colors. + */ + public static final Option USE_UNIFORM_NODE_COLOR = new Option( + "USE_UNIFORM_NODE_COLOR", Boolean.class, bundle, Boolean.FALSE); + + /** + * Color for uniform node color. + */ + public static final Option UNIFORM_NODE_COLOR = new Option( + "UNIFORM_NODE_COLOR", Color.class, bundle, ColorPalette.SECOND_292); + + /** + * User wants to choose the colors himself + */ + public static final Option CHOOSE_OWN_NODE_COLORS = new Option ( + "CHOOSE_OWN_NODE_COLORS", Boolean.class, bundle, Boolean.FALSE); + + /** + * Color for high concentration. + */ + public static final Option COLOR1 = new Option( + "COLOR1", Color.class, bundle, ColorPalette.SECOND_180); + + /** + * Color for middle concentration + */ + public static final Option COLOR2 = new Option( + "COLOR2", Color.class, bundle, ColorPalette.SECOND_3015); + + /** + * Color for low concentration + */ + public static final Option COLOR3 = new Option( + "COLOR3", Color.class, bundle, ColorPalette.LIGHT_RED); + + /** + * Node size while color interpolation. + */ + public static final Option COLOR_NODE_SIZE = new Option( + "COLOR_NODE_SIZE", Double.class, bundle, new Range( + Double.class, "{(0, 1E3]}"), Double.valueOf(30d)); + + /** + * Determines the minimum line width of dynamic reaction visualization. + */ + public static final Option MIN_LINE_WIDTH = new Option( + "MIN_LINE_WIDTH", Double.class, bundle, new Range( + Double.class, "{(0, 1E2]}"), Double.valueOf(1d)); + + /** + * Determines the maximum line width of dynamic reaction visualization. + */ + public static final Option MAX_LINE_WIDTH = new Option( + "MAX_LINE_WIDTH", Double.class, bundle, new Range( + Double.class, "{(0, 1E3]}"), Double.valueOf(6d)); + + /** + * Sets step size for image taking. + */ + public static final Option VIDEO_IMAGE_STEPSIZE = new Option( + "VIDEO_IMAGE_STEPSIZE", Double.class, bundle, new Range( + Double.class, "{[1, 1E2]}"), Double.valueOf(5d)); + + /** + * Sets resolution multiplier. + */ + public static final Option VIDEO_RESOLUTION_MULTIPLIER = new Option( + "VIDEO_RESOLUTION_MULTIPLIER", Double.class, bundle, new Range( + Double.class, "{[0, 1E2]}"), Double.valueOf(1d)); + + /** + * Option to force resolution multiplier, even if the output resolution is + * greater than some threshold. + */ + public static final Option VIDEO_FORCE_RESOLUTION_MULTIPLIER = new Option( + "VIDEO_FORCE_RESOLUTION_MULTIPLIER", Boolean.class, bundle, Boolean.FALSE); + + /** + * Option to use the current whole graph to generate videos and images + * or the current view graph. + */ + public static final Option VIDEO_DISPLAY_WINDOW = new Option( + "VIDEO_DISPLAY_WINDOW", Boolean.class, bundle, Boolean.TRUE); + + /** + * Add a predefined camera animation + */ + public static final Option CAMERA_WAY_FILE = new Option( + "CAMERA_WAY_FILE", File.class, bundle, new Range(File.class, + SBFileFilter.createCSVFileFilter()), new File( + System.getProperty("user.dir"))); + + /** + * Sets the fast simulation speed. + */ + public static final Option SIM_SPEED_FAST = new Option( + "SIM_SPEED_FAST", Double.class, bundle, new Range( + Double.class, "{[1, 1E3]}"), Double.valueOf(5d)); + + /** + * Sets the normal simulation speed. + */ + public static final Option SIM_SPEED_NORMAL = new Option( + "SIM_SPEED_NORMAL", Double.class, bundle, new Range( + Double.class, "{[1, 1E3]}"), Double.valueOf(25d)); + + /** + * Sets the slow simulation speed. + */ + public static final Option SIM_SPEED_SLOW = new Option( + "SIM_SPEED_SLOW", Double.class, bundle, new Range( + Double.class, "{[1, 1E3]}"), Double.valueOf(80d)); + + /** + * Choose simulation speed. + */ public static final Option SIM_SPEED_CHOOSER = new Option( - "SIM_SPEED_CHOOSER", String.class, bundle, new Range(String.class, - Items.getAllSpeedItems()), Items.NORMAL.getName()); - -// /** -// * Sets framerate. -// */ -// public static final Option VIDEO_TIMESTAMP = new Option( -// "VIDEO_TIMESTAMP", Double.class, bundle, new Range( -// Double.class, "{[1, 1E2]}"), Double.valueOf(25d)); - - /** - * Sets step size for image taking. - */ - public static final Option VIDEO_IMAGE_STEPSIZE = new Option( - "VIDEO_IMAGE_STEPSIZE", Double.class, bundle, new Range( - Double.class, "{[1, 1E2]}"), Double.valueOf(5d)); - - /** - * Sets resolution multiplier. - */ - public static final Option VIDEO_RESOLUTION_MULTIPLIER = new Option( - "VIDEO_RESOLUTION_MULTIPLIER", Double.class, bundle, new Range( - Double.class, "{[1, 1E2]}"), Double.valueOf(3d)); - - /** - * Option to force resolution multiplier, even if the output resolution is - * greater than some threshold. - */ - public static final Option VIDEO_FORCE_RESOLUTION_MULTIPLIER = new Option( - "VIDEO_FORCE_RESOLUTION_MULTIPLIER", Boolean.class, bundle, Boolean.FALSE); - - /** - * Option to use the current whole graph to generate videos and images - * or the current view graph. - */ - public static final Option VIDEO_DISPLAY_WINDOW = new Option( - "VIDEO_DISPLAY_WINDOW", Boolean.class, bundle, Boolean.TRUE); - - /** - * Options for visualization. - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public static final OptionGroup GROUP_VISUALIZATION = new OptionGroup( - "GROUP_VISUALIZATION", bundle, INTERPOLATE_EXP_DATA, RELATIVE_CONCENTRATION_CHANGES, SHOW_NODE_LABELS, SHOW_REACTION_LABELS, VISUALIZATION_STYLE); - - /** - * Settings in case of dynamic change of node size. - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public static final OptionGroup GROUP_NODESIZE = new OptionGroup( - "GROUP_NODESIZE", bundle, USE_UNIFORM_NODE_COLOR, UNIFORM_NODE_COLOR, MIN_NODE_SIZE, MAX_NODE_SIZE); - - /** - * Settings in case of dynamic change of node color. - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public static final OptionGroup GROUP_NODECOLOR = new OptionGroup( - "GROUP_NODECOLOR", bundle, COLOR1, COLOR2, COLOR3, COLOR_NODE_SIZE); - - /** - * Settings for dynamic reaction visualization. - */ - @SuppressWarnings("unchecked") - public static final OptionGroup GROUP_REACTION = new OptionGroup( - "GROUP_REACTION", bundle, MIN_LINE_WIDTH, MAX_LINE_WIDTH); - - /** - * Options for simulation speed. - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public static final OptionGroup GROUP_SIM_SPEED = new OptionGroup( - "GROUP_SIM_SPEED", bundle, SIM_SPEED_FAST, SIM_SPEED_NORMAL, SIM_SPEED_SLOW, SIM_SPEED_CHOOSER); - - /** - * Settings for video encoding. - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public static final OptionGroup GROUP_VIDEO_ENCODING = new OptionGroup( - "GROUP_VIDEO_ENCODING", bundle, VIDEO_DISPLAY_WINDOW, VIDEO_FORCE_RESOLUTION_MULTIPLIER, VIDEO_RESOLUTION_MULTIPLIER, VIDEO_IMAGE_STEPSIZE); - + "SIM_SPEED_CHOOSER", String.class, bundle, new Range(String.class, + Items.getAllSpeedItems()), Items.NORMAL.getName()); + + /** + * camera animation should be displayed in a special speed + */ + public static final Option SHOW_CAMERA_ANIMATION = new Option( + "SHOW_CAMERA_ANIMATION", String.class, bundle, new Range(String.class, + Items.getAllCameraAnimationItems()), bundle.getString("NO_CAMERA_ANIMATION")); + + // /** + // * Sets framerate. + // */ + // public static final Option VIDEO_TIMESTAMP = new Option( + // "VIDEO_TIMESTAMP", Double.class, bundle, new Range( + // Double.class, "{[1, 1E2]}"), Double.valueOf(25d)); + + + /** + * Options for visualization. + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static final OptionGroup GROUP_VISUALIZATION = new OptionGroup( + "GROUP_VISUALIZATION", bundle, INTERPOLATE_EXP_DATA, RELATIVE_CONCENTRATION_CHANGES, + SHOW_NODE_LABELS, SHOW_REACTION_LABELS, CYCLE_SIMULATION, VISUALIZATION_STYLE); + + /** + * Settings in case of dynamic change of node size. + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static final OptionGroup GROUP_NODESIZE = new OptionGroup( + "GROUP_NODESIZE", bundle, USE_UNIFORM_NODE_COLOR, UNIFORM_NODE_COLOR, MIN_NODE_SIZE, + MAX_NODE_SIZE); + + /** + * Settings in case of dynamic change of node color. + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static final OptionGroup GROUP_NODECOLOR = new OptionGroup( + "GROUP_NODECOLOR", bundle, COLOR1, COLOR2, COLOR3, COLOR_NODE_SIZE, CHOOSE_OWN_NODE_COLORS); + + /** + * Settings for dynamic reaction visualization. + */ + @SuppressWarnings("unchecked") + public static final OptionGroup GROUP_REACTION = new OptionGroup( + "GROUP_REACTION", bundle, MIN_LINE_WIDTH, MAX_LINE_WIDTH); + + /** + * Options for simulation speed. + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static final OptionGroup GROUP_SIM_SPEED = new OptionGroup( + "GROUP_SIM_SPEED", bundle, SIM_SPEED_FAST, SIM_SPEED_NORMAL, SIM_SPEED_SLOW, SIM_SPEED_CHOOSER); + + /** + * Settings for video encoding. + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static final OptionGroup GROUP_VIDEO_ENCODING = new OptionGroup( + "GROUP_VIDEO_ENCODING", bundle, VIDEO_DISPLAY_WINDOW, VIDEO_FORCE_RESOLUTION_MULTIPLIER, + VIDEO_RESOLUTION_MULTIPLIER, VIDEO_IMAGE_STEPSIZE); + } diff --git a/src/org/sbml/simulator/gui/graph/IDynamicGraph.java b/src/org/sbml/simulator/gui/graph/IDynamicGraph.java index 638f08f..7394e04 100644 --- a/src/org/sbml/simulator/gui/graph/IDynamicGraph.java +++ b/src/org/sbml/simulator/gui/graph/IDynamicGraph.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -27,29 +25,28 @@ * MVC-pattern. * * @author Fabian Schwarzkopf - * @version $Rev$ */ public interface IDynamicGraph { - /** - * Method invoked by related {@link DynamicCore} when play thread is done. - */ - public void donePlay(); - - /** - * Return a {@link BufferedImage} with given resolution of currently - * displayed Graph. - * @param width - * @param height - * @return - */ - public BufferedImage takeGraphshot(int width, int height); - - /** - * Method invoked by related {@link DynamicCore} when time point changes. - * @param timepoint - * @param updateThem - */ - public void updateGraph(double timepoint, MultiTable updateThem); - + /** + * Method invoked by related {@link DynamicCore} when play thread is done. + */ + public void donePlay(); + + /** + * Return a {@link BufferedImage} with given resolution of currently + * displayed Graph. + * @param width + * @param height + * @return + */ + public BufferedImage takeGraphshot(int width, int height); + + /** + * Method invoked by related {@link DynamicCore} when time point changes. + * @param timepoint + * @param updateThem + */ + public void updateGraph(double timepoint, MultiTable updateThem); + } diff --git a/src/org/sbml/simulator/gui/graph/IGraphManipulator.java b/src/org/sbml/simulator/gui/graph/IGraphManipulator.java index e13558c..6818e87 100644 --- a/src/org/sbml/simulator/gui/graph/IGraphManipulator.java +++ b/src/org/sbml/simulator/gui/graph/IGraphManipulator.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -28,37 +26,49 @@ * graph should implement this interface and override the methods. * * @author Fabian Schwarzkopf - * @version $Rev$ */ public interface IGraphManipulator { - /** - * Changes the visualization of a given node. - * @param id - * @param value - * @param labels - */ - public void dynamicChangeOfNode(String id, double value, boolean labels); - - /** - * Changes the visualization of a given {@link Reaction}. - * @param id - * @param value - */ - public void dynamicChangeOfReaction(String id, double value, boolean labels); - - /** - * Reverts the changes for the given id. - * @param id - */ - public void revertChanges(String id); - - /** - * un/hide given id/node - * @param id - * @param node - * @param b - */ - public void hide(String id, Node node, boolean b); - + /** + * Changes the visualization of a given node. + * @param id + * @param value + * @param labels + */ + public void dynamicChangeOfNode(String id, double value, boolean labels); + + /** + * Changes the visualization of a given {@link Reaction}. + * @param id + * @param value + */ + public void dynamicChangeOfReaction(String id, double value, boolean labels); + + /** + * Reverts the changes for the given id. + * @param id + */ + public void revertChanges(String id); + + /** + * un/hide given id/node + * @param id + * @param node + * @param b + */ + public void hide(String id, Node node, boolean b); + + /** + * sets new min and max node sizes if they were changed + * @param minNodeSize + * @param maxNodeSize + */ + public void setNewMinMaxNodeSize(double minNodeSize, double maxNodeSize); + + /** + * resets the adding factor for the node sizes + * @param newSize + */ + public void setAddSizeForOverview(int newSize); + } diff --git a/src/org/sbml/simulator/gui/graph/ImageGenerator.java b/src/org/sbml/simulator/gui/graph/ImageGenerator.java index b2b6341..5719220 100644 --- a/src/org/sbml/simulator/gui/graph/ImageGenerator.java +++ b/src/org/sbml/simulator/gui/graph/ImageGenerator.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -23,6 +21,7 @@ import java.awt.image.BufferedImage; import java.util.logging.Logger; +import de.zbit.gui.GUITools; import y.io.JPGIOHandler; import y.io.ViewPortConfigurator; import y.view.Graph2D; @@ -33,217 +32,230 @@ * This class handles image generating. * * @author Fabian Schwarzkopf - * @version $Rev$ */ public class ImageGenerator { - /** - * A {@link Logger} for this class. - */ - private static final transient Logger logger = Logger.getLogger(ImageGenerator.class.getName()); - - /** - * Graph on which the images are taken. - */ - private Graph2D graph; - - /** - * Determines whether the whole graph is pictured or just the current - * display window. - */ - private boolean wholeGraph; - - /** - * Fix point for video. - */ - private Point viewPoint; - - /** - * Fix point for video. - */ - private double zoomLevel; - - /** - * Constructs a new {@link ImageGenerator} on the given graph. Depending on - * the given boolean, either the whole graph will be pictured or just the - * current view. - * - * @param graph - * @param wholeGraph - */ - public ImageGenerator(Graph2D graph, boolean wholeGraph) { - this.graph = graph; - this.wholeGraph = wholeGraph; + /** + * A {@link Logger} for this class. + */ + private static final transient Logger logger = Logger.getLogger(ImageGenerator.class.getName()); + + /** + * Graph on which the images are taken. + */ + private Graph2D graph; + + /** + * Determines whether the whole graph is pictured or just the current + * display window. + */ + private boolean wholeGraph; + + /** + * Fix point for video. + */ + private Point viewPoint; + + /** + * Fix point for video. + */ + private double zoomLevel; + + /** + * Constructs a new {@link ImageGenerator} on the given graph. Depending on + * the given boolean, either the whole graph will be pictured or just the + * current view. + * + * @param graph + * @param wholeGraph + */ + public ImageGenerator(Graph2D graph, boolean wholeGraph) { + this.graph = graph; + this.wholeGraph = wholeGraph; + } + + /** + * This function determines the fix points to generate videos. The fix + * points are either determined on the whole graph or on the current view. + * It ensures that graph elements will stay on their location even if the + * graph size changes during visualization (e. g. nodes getting + * bigger/smaller). + * + * @param width + * of the output resolution + */ + public void determineFixPoints(int width) { + //save current view + Graph2DView originalViewPort = (Graph2DView) graph.getCurrentView(); + + //create dedicated view + JPGIOHandler ioh = new JPGIOHandler(); + Graph2DView imageView = ioh.createDefaultGraph2DView(graph); + + //configure imageView such that whole graph is contained + ViewPortConfigurator vpc = new ViewPortConfigurator(); + vpc.setGraph2D(imageView.getGraph2D()); + if (wholeGraph) { + //use whole graph + vpc.setGraph2D(imageView.getGraph2D()); + vpc.setClipType(ViewPortConfigurator.CLIP_GRAPH); + //scale it to achieve high resolution + vpc.setSizeType(ViewPortConfigurator.SIZE_USE_CUSTOM_WIDTH); + vpc.setCustomWidth(width); + } else { + //use original view + vpc.setGraph2DView(originalViewPort); + vpc.setClipType(ViewPortConfigurator.CLIP_VIEW); + //scale it anyway for high resultion + vpc.setSizeType(ViewPortConfigurator.SIZE_USE_CUSTOM_WIDTH); + vpc.setCustomWidth(width); } + vpc.configure(imageView); + + //save initial viewpoint + viewPoint = imageView.getViewPoint(); + //save initial zoomlevel + zoomLevel = imageView.getZoom(); + + logger.fine("Fixpoints set. Viewpoint: " + viewPoint + "; Zoomlevel: " + + zoomLevel); + } + + /** + * Returned width and height represent the unscaled graph as a whole or the + * width and height of the current display window. + * @return {width, height} + */ + public int[] getScreenshotResolution() { + //save current view + Graph2DView originalViewPort = (Graph2DView) graph.getCurrentView(); - /** - * This function determines the fix points to generate videos. The fix - * points are either determined on the whole graph or on the current view. - * It ensures that graph elements will stay on their location even if the - * graph size changes during visualization (e. g. nodes getting - * bigger/smaller). - * - * @param width - * of the output resolution - */ - public void determineFixPoints(int width) { - //save current view - Graph2DView originalViewPort = (Graph2DView) graph.getCurrentView(); - - //create dedicated view - JPGIOHandler ioh = new JPGIOHandler(); - Graph2DView imageView = ioh.createDefaultGraph2DView(graph); - - //configure imageView such that whole graph is contained - ViewPortConfigurator vpc = new ViewPortConfigurator(); - vpc.setGraph2D(imageView.getGraph2D()); - if (wholeGraph) { - //use whole graph - vpc.setGraph2D(imageView.getGraph2D()); - vpc.setClipType(ViewPortConfigurator.CLIP_GRAPH); - //scale it to achieve high resolution - vpc.setSizeType(ViewPortConfigurator.SIZE_USE_CUSTOM_WIDTH); - vpc.setCustomWidth(width); - } else { - //use original view - vpc.setGraph2DView(originalViewPort); - vpc.setClipType(ViewPortConfigurator.CLIP_VIEW); - //scale it anyway for high resultion - vpc.setSizeType(ViewPortConfigurator.SIZE_USE_CUSTOM_WIDTH); - vpc.setCustomWidth(width); - } - vpc.configure(imageView); - - //save initial viewpoint - viewPoint = imageView.getViewPoint(); - //save initial zoomlevel - zoomLevel = imageView.getZoom(); - - logger.fine("Fixpoints set. Viewpoint: " + viewPoint + "; Zoomlevel: " - + zoomLevel); + //create dedicated view + JPGIOHandler ioh = new JPGIOHandler(); + Graph2DView imageView = ioh.createDefaultGraph2DView(graph); + + //configure view + ViewPortConfigurator vpc = new ViewPortConfigurator(); + if (wholeGraph) { + //configure imageView such that whole graph is contained + vpc.setGraph2D(imageView.getGraph2D()); + vpc.setClipType(ViewPortConfigurator.CLIP_GRAPH); + vpc.setSizeType(ViewPortConfigurator.SIZE_USE_ORIGINAL); + } else { + //use original view + vpc.setGraph2DView(originalViewPort); + vpc.setClipType(ViewPortConfigurator.CLIP_VIEW); + //do not scale it, because this method returns the real resolution + vpc.setSizeType(ViewPortConfigurator.SIZE_USE_ORIGINAL); } + vpc.configure(imageView); + + int width = imageView.getWidth(); + int height = imageView.getHeight(); - /** - * Returned width and height represent the unscaled graph as a whole or the - * width and height of the current display window. - * @return {width, height} + return new int[]{width, height}; + } + + /** + * This method returns an {@link BufferedImage} of the given size. To + * achieve higher resolutions than the actual graph size, the graph gets + * scaled to the given size in a dedicated view to take the screen shot. + *

+ * In order to generate videos as sequence of images, fix points should + * initially be determined first with determineFixpoints(). Then each + * picture will be taken from the same point of view and zoom level. This + * means there will be no elements changing their position due to changing + * their size while a dynamic simulation. Especially important if the whole + * graph is pictured, because than the bounding box will vary if the + * elements change their size. + * @param width + * @param height + * @return + */ + public BufferedImage takeGraphshot(int width, int height) { + /* + * Take screenshot in dedicated view to ensure that nothing is cut off + * and to change screenshotresolution independent of actual view (this + * allows higher screenshot resolutions without users noticing the + * necessary scaling). */ - public int[] getScreenshotResolution() { - //save current view - Graph2DView originalViewPort = (Graph2DView) graph.getCurrentView(); - - //create dedicated view - JPGIOHandler ioh = new JPGIOHandler(); - Graph2DView imageView = ioh.createDefaultGraph2DView(graph); - - //configure view - ViewPortConfigurator vpc = new ViewPortConfigurator(); - if (wholeGraph) { - //configure imageView such that whole graph is contained - vpc.setGraph2D(imageView.getGraph2D()); - vpc.setClipType(ViewPortConfigurator.CLIP_GRAPH); - vpc.setSizeType(ViewPortConfigurator.SIZE_USE_ORIGINAL); - } else { - //use original view - vpc.setGraph2DView(originalViewPort); - vpc.setClipType(ViewPortConfigurator.CLIP_VIEW); - //do not scale it, because this method returns the real resolution - vpc.setSizeType(ViewPortConfigurator.SIZE_USE_ORIGINAL); - } - vpc.configure(imageView); - - int width = imageView.getWidth(); - int height = imageView.getHeight(); - - return new int[]{width, height}; + + //unselect objects + graph.unselectAll(); + + //save current view + Graph2DView originalViewPort = (Graph2DView) graph.getCurrentView(); + + //create dedicated view for graphshot + JPGIOHandler ioh = new JPGIOHandler(); + Graph2DView imageView = ioh.createDefaultGraph2DView(graph); + + if(imageView.getX() != originalViewPort.getX() && + imageView.getY() != originalViewPort.getY()) { + originalViewPort.setBounds(imageView.getX(), imageView.getY(), originalViewPort.getWidth(), originalViewPort.getHeight()); + } + + //use original render settings + imageView.setGraph2DRenderer(originalViewPort.getGraph2DRenderer()); + imageView.setRenderingHints(originalViewPort.getRenderingHints()); + + //set dedicated view + graph.setCurrentView(imageView); + + //settings for dedicated view + ViewPortConfigurator vpc = new ViewPortConfigurator(); + if (wholeGraph) { + vpc.setGraph2D(imageView.getGraph2D()); + //do not cut off anything not in view + vpc.setClipType(ViewPortConfigurator.CLIP_GRAPH); + //scale image to video size + vpc.setSizeType(ViewPortConfigurator.SIZE_USE_CUSTOM_WIDTH); + vpc.setCustomWidth(width); + } else { + //use current display window + vpc.setGraph2DView(originalViewPort); + vpc.setClipType(ViewPortConfigurator.CLIP_VIEW); + //scale it anyway to ensure high resolution + vpc.setSizeType(ViewPortConfigurator.SIZE_USE_CUSTOM_WIDTH); + vpc.setCustomWidth(width); } + //configure dedicated view with settings + vpc.configure(imageView); - /** - * This method returns an {@link BufferedImage} of the given size. To - * achieve higher resolutions than the actual graph size, the graph gets - * scaled to the given size in a dedicated view to take the screen shot. - *

- * In order to generate videos as sequence of images, fix points should - * initially be determined first with determineFixpoints(). Then each - * picture will be taken from the same point of view and zoom level. This - * means there will be no elements changing their position due to changing - * their size while a dynamic simulation. Especially important if the whole - * graph is pictured, because than the bounding box will vary if the - * elements change their size. - * @param width - * @param height - * @return + /* + * fix zoomlevel and viewpoint to prevent pixel jumping during video + * generating. Make sure to call determineFixePoints(int width) before calling + * this function. */ - public BufferedImage takeGraphshot(int width, int height) { - /* - * Take screenshot in dedicated view to ensure that nothing is cut off - * and to change screenshotresolution independent of actual view (this - * allows higher screenshot resolutions without users noticing the - * necessary scaling). - */ - - //unselect objects - graph.unselectAll(); - - //save current view - Graph2DView originalViewPort = (Graph2DView) graph.getCurrentView(); - - //create dedicated view for graphshot - JPGIOHandler ioh = new JPGIOHandler(); - Graph2DView imageView = ioh.createDefaultGraph2DView(graph); - - //use original render settings - imageView.setGraph2DRenderer(originalViewPort.getGraph2DRenderer()); - imageView.setRenderingHints(originalViewPort.getRenderingHints()); - - //set dedicated view - graph.setCurrentView(imageView); - - //settings for dedicated view - ViewPortConfigurator vpc = new ViewPortConfigurator(); - if (wholeGraph) { - vpc.setGraph2D(imageView.getGraph2D()); - //do not cut off anything not in view - vpc.setClipType(ViewPortConfigurator.CLIP_GRAPH); - //scale image to video size - vpc.setSizeType(ViewPortConfigurator.SIZE_USE_CUSTOM_WIDTH); - vpc.setCustomWidth(width); - } else { - //use current display window - vpc.setGraph2DView(originalViewPort); - vpc.setClipType(ViewPortConfigurator.CLIP_VIEW); - //scale it anyway to ensure high resolution - vpc.setSizeType(ViewPortConfigurator.SIZE_USE_CUSTOM_WIDTH); - vpc.setCustomWidth(width); - } - //configure dedicated view with settings - vpc.configure(imageView); - - /* - * fix zoomlevel and viewpoint to prevent pixel jumping during video - * generating. Make sure to call determineFixePoints(int width) before calling - * this function. - */ - if (zoomLevel != 0 && viewPoint != null) { - imageView.setZoom(zoomLevel); - imageView.setViewPoint(viewPoint.x, viewPoint.y); - } else { - logger.fine("No Fixpoints available. There might be some pixel jumping in videos."); - } - - BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR); - //if BufferedImage is too large, overlap will be white - Graphics2D paintArea = image.createGraphics(); - paintArea.setColor(Color.WHITE); - paintArea.fillRect(0, 0, width, height); - //paint screenshot - imageView.paintVisibleContent(image.createGraphics()); - - //restore original view - graph.removeView(graph.getCurrentView()); - graph.setCurrentView(originalViewPort); - - return image; + if (zoomLevel != 0 && viewPoint != null) { + if(DynamicCore.cameraAnimation && DynamicCore.playAgain) { + imageView.setZoom(zoomLevel); + imageView.setViewPoint(viewPoint.x, viewPoint.y); + } + } else { + logger.fine("No Fixpoints available. There might be some pixel jumping in videos."); + } + + BufferedImage image = null; + if(width > 46340 || height > 46340) { + GUITools.showErrorMessage(null, "The pixelsize of width:" + width + " or height:" + height + " is greater than " + + "46340 pixels, so BufferedImage in ImageGenerator line 235 is at its end! Scale your " + + "image size down."); + } else { + image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR); } - + //if BufferedImage is too large, overlap will be white + Graphics2D paintArea = image.createGraphics(); + paintArea.setColor(Color.WHITE); + paintArea.fillRect(0, 0, width, height); + //paint screenshot + imageView.paintVisibleContent(image.createGraphics()); + + //restore original view + graph.removeView(graph.getCurrentView()); + graph.setCurrentView(originalViewPort); + + return image; + } + } diff --git a/src/org/sbml/simulator/gui/graph/ManipulatorOfFillLevel.java b/src/org/sbml/simulator/gui/graph/ManipulatorOfFillLevel.java new file mode 100644 index 0000000..1f2ebd4 --- /dev/null +++ b/src/org/sbml/simulator/gui/graph/ManipulatorOfFillLevel.java @@ -0,0 +1,229 @@ +package org.sbml.simulator.gui.graph; + +import java.awt.Color; +import java.util.logging.Logger; + +import org.sbml.jsbml.Reaction; +import org.sbml.jsbml.SBMLDocument; + +import de.zbit.graph.sbgn.CloneMarker; +import de.zbit.graph.sbgn.FillLevelNodeRealizer; +import de.zbit.gui.ColorPalette; +import de.zbit.sbml.layout.y.ILayoutGraph; +import y.base.Node; +import y.view.NodeLabel; +import y.view.NodeRealizer; + +/** + * This class is a {@link IGraphManipulator}. It changes the color of the given + * nodes as well as their filling level. Changes of color are relative to concentration changes, + * changes of filling level are absolute to concentration changes. + * + * @author Lea Buchweitz + */ + +public class ManipulatorOfFillLevel extends AGraphManipulator { + + /** + * A {@link Logger} for this class. + */ + private static final transient Logger logger = Logger.getLogger(ManipulatorOfFillLevel.class.getName()); + + /** + * Node size per default 30. + */ + private double nodeSize = 30; + + /** + * if camera animation is active and overview is shown node size is different + */ + private static double addSizeForOverview; + + /** + * determines default node color. + */ + private Color DEFAULT_NODE_COLOR = ColorPalette.SECOND_3015; + + /** + * Field for the first color (high concentration), second color (mid + * concentration), third color (low concentration). + */ + private int[] RGBcolor1, RGBcolor2, RGBcolor3; + + /** + * Saves minimum and maximum value of selected Species to save computation + * time. + */ + private double[] minMaxOfSelectedSpecies; + + /** + * Constructs fill level manipulator with default RGB colors as color1 + * (high) -> color2 (mid) -> color3 (low) and a constant node size. + * {@link Reaction}s line widths as given. Concentration changes as user given. + * + * @param graph + * @param document + * @param core + * @param selectedSpecies + * @param nodeSize + * @param color3 + * @param color2 + * @param color1 + * @param color1 + */ + public ManipulatorOfFillLevel(ILayoutGraph layoutGraph, SBMLDocument document, DynamicCore core, + String[] selectedSpecies, double nodeSize, double addSizeForOverview, Color color1, Color color2, Color color3) { + super(layoutGraph, document, core); + + this.addSizeForOverview = addSizeForOverview; + + this.nodeSize = nodeSize; + + // default colors + // max concentration + RGBcolor1 = new int[] {color1.getRed(), + color1.getGreen(), + color1.getBlue()}; + // middle concentration + RGBcolor2 = new int[] {color2.getRed(), + color2.getGreen(), + color2.getBlue()}; + // min concentration + RGBcolor3 = new int[] {color3.getRed(), + color3.getGreen(), + color3.getBlue()}; + + /* + * Store min/max once to save computation time in case of absolute + * concentration changes. + */ + minMaxOfSelectedSpecies = core.getMinMaxOfIDs(selectedSpecies); + + } + + /** + * Constructs fill level manipulator with the given RGB colors as color1 + * (high) -> color2 (mid) -> color3 (low) and a constant node size. + * {@link Reaction}s line widths as given. Concentration changes as user given. + * + * @param graph + * @param document + * @param core + * @param selectedSpecies + * @param color1 + * @param nodeSize + */ + + public ManipulatorOfFillLevel(ILayoutGraph graph, SBMLDocument document, + DynamicCore core, String[] selectedSpecies, double nodeSize, double addSizeForOverview, Color color2) { + + super(graph, document, core); + + this.addSizeForOverview = addSizeForOverview; + + this.nodeSize = nodeSize; + + Color[] minMax = calculateColorsFromDefault(color2); + + // min + RGBcolor3 = new int[] { minMax[0].getRed(), minMax[0].getGreen(), minMax[0].getBlue() }; + // middle + RGBcolor2 = new int[] { color2.getRed(), color2.getGreen(), color2.getBlue() }; + // max + RGBcolor1 = new int[]{ minMax[1].getRed(), minMax[1].getGreen(), minMax[1].getBlue() }; + + /* + * Store min/max once to save computation time in case of absolute + * concentration changes. + */ + minMaxOfSelectedSpecies = core.getMinMaxOfIDs(selectedSpecies); + } + + @Override + public void dynamicChangeOfNode(String id, double value, boolean labels) { + if (id2speciesNode.get(id) != null) { + for (Node node : graph.getSpeciesId2nodes().get(id)) { + + double addSize = 0; + if(DynamicCore.cameraAnimation && DynamicCore.playAgain) { + addSize = addSizeForOverview; + } + + double minValueFill, maxValueFill, minValueColor, maxValueColor; + // absolute filling level + minValueFill = id2minMaxData.get(id)[0]; + maxValueFill = id2minMaxData.get(id)[1]; + // relative color + minValueColor = minMaxOfSelectedSpecies[0]; + maxValueColor = minMaxOfSelectedSpecies[1]; + + double percentFill = adjustValue(minValueFill, maxValueFill, 0, 1, value); + int[] angles = degreeInterpolationForFillingLevel(percentFill); + + double percentColor = adjustValue(minValueColor, maxValueColor, 0, 1, value); + int[] RGBinterpolated = linearColorInterpolationForThree(percentColor, + RGBcolor1, RGBcolor2, RGBcolor3); + + NodeRealizer nr; + if(!node2Realizer.containsKey(node)) { + nr = graph.getGraph2D().getRealizer(node); + node2Realizer.put(node, nr); + } else { + nr = node2Realizer.get(node); + } + + FillLevelNodeRealizer realizerFillLevel; + if(!node2FillRealizer.containsKey(node)) { + realizerFillLevel = new FillLevelNodeRealizer(nr, percentFill, angles, + new Color(RGBcolor2[0], RGBcolor2[1], RGBcolor2[2])); + node2FillRealizer.put(node, realizerFillLevel); + realizerFillLevel.setNodeIsCloned(((CloneMarker) nr).isNodeCloned()); + } else { + realizerFillLevel = node2FillRealizer.get(node); + } + + graph.getGraph2D().setRealizer(node, realizerFillLevel); + + NodeLabel nl = (NodeLabel) nr.getLabel(); + realizerFillLevel.setLabel(nl); + + double ratio = realizerFillLevel.getHeight() / realizerFillLevel.getWidth(); + + realizerFillLevel.setAngles(angles); + realizerFillLevel.setPercent(percentFill); + realizerFillLevel.setSize(nodeSize+addSize, nodeSize+addSize*ratio); + realizerFillLevel.setColor(new Color(RGBinterpolated[0], RGBinterpolated[1], + RGBinterpolated[2])); + + /* + * Label Node with ID and real value at this timepoint. Last label will + * be treated as dynamic label + */ + + if (labels) { + labelNode(realizerFillLevel, id, value); + } else if (nr.labelCount() > 1) { + // labels switched off, therefore remove them, if there are any + nr.removeLabel(nr.getLabel(nr.labelCount()-1)); + } + + } + + // update view + graph.getGraph2D().updateViews(); + } + + } + + public void setNewMinMaxNodeSize(double minNodeSize, double maxNodeSize) {} + + /** + * resets the adding factor for the node sizes + * @param newSize + */ + @Override + public void setAddSizeForOverview(int newSize) { + addSizeForOverview = newSize; + } + +} diff --git a/src/org/sbml/simulator/gui/graph/ManipulatorOfNodeColor.java b/src/org/sbml/simulator/gui/graph/ManipulatorOfNodeColor.java index baec8b4..7795b76 100644 --- a/src/org/sbml/simulator/gui/graph/ManipulatorOfNodeColor.java +++ b/src/org/sbml/simulator/gui/graph/ManipulatorOfNodeColor.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -35,178 +33,257 @@ * nodes and width of given reactions. * * @author Fabian Schwarzkopf - * @version $Rev$ */ public class ManipulatorOfNodeColor extends AGraphManipulator { - - /** - * A {@link Logger} for this class. - */ - private static final transient Logger logger = Logger.getLogger(ManipulatorOfNodeColor.class.getName()); - - /** - * Field for the first color (high concentration), second color (mid - * concentration), third color (low concentration). - */ - private int[] RGBcolor1, RGBcolor2, RGBcolor3; - - /** - * Saves minimum and maximum value of selected Species to save computation - * time. - */ - private double[] minMaxOfSelectedSpecies; - - /** - * Node size per default 30. - */ - private double nodeSize = 30; - - /** - * Concentration changes relativ or absolute? Per default false. + + /** + * A {@link Logger} for this class. + */ + private static final transient Logger logger = Logger.getLogger(ManipulatorOfNodeColor.class.getName()); + + /** + * Field for the first color (high concentration), second color (mid + * concentration), third color (low concentration). + */ + private int[] RGBcolor1, RGBcolor2, RGBcolor3; + + /** + * Saves minimum and maximum value of selected Species to save computation + * time. + */ + private double[] minMaxOfSelectedSpecies; + + /** + * Node size per default 30. + */ + private double nodeSize = 30; + + /** + * if camera animation is active and overview is shown node size is different + */ + private static double addSizeForOverview; + + /** + * Concentration changes relativ or absolute? Per default false. + */ + private boolean relativeConcentrations = false; + + /** + * Constructs node-color manipulator with default gradient camine red (high) + * -> white (mid) -> gold (low) and default node size and default reactions + * line widths. + * Concentration changes absolute per default. + * + * @param graph + * @param document + * @param core + * @param selectedSpecies + * @param selectedReactions + */ + public ManipulatorOfNodeColor(ILayoutGraph graph, SBMLDocument document, DynamicCore core, + String[] selectedSpecies, + String[] selectedReactions) { + + super(graph, document, core, selectedReactions, DEFAULT_MIN_LINEWIDTH, DEFAULT_MAX_LINEWIDTH); + + REVERT_NODE_SIZE = nodeSize; + + // default colors + RGBcolor1 = new int[] { ColorPalette.CAMINE_RED.getRed(), + ColorPalette.CAMINE_RED.getGreen(), + ColorPalette.CAMINE_RED.getBlue() }; + RGBcolor2 = new int[]{255, 255, 255}; //white + RGBcolor3 = new int[]{ ColorPalette.GOLD.getRed(), + ColorPalette.GOLD.getGreen(), + ColorPalette.GOLD.getBlue() }; + /* + * Store min/max once to save computation time in case of absolute + * concentration changes. */ - private boolean relativeConcentrations = false; - - /** - * Constructs node-color manipulator with default gradient camine red (high) - * -> white (mid) -> gold (low) and default node size and default reactions - * line widths. - * Concentration changes absolute per default. - * - * @param graph - * @param document - * @param core - * @param selectedSpecies - * @param selectedReactions + minMaxOfSelectedSpecies = core.getMinMaxOfIDs(selectedSpecies); + } + + /** + * Constructs node-color manipulator with the given RGB colors as color1 + * (high) -> color2 (mid) -> color3 (low) and a constant node size. + * {@link Reaction}s line widths as given. Concentration changes as user given. + * + * @param graph + * @param document + * @param core + * @param selectedSpecies + * @param selectedReactions + * @param relativeConcentrations + * @param nodeSize + * @param color1 + * @param color2 + * @param color3 + * @param reactionsMinLineWidth + * @param reactionsMaxLineWidth + */ + public ManipulatorOfNodeColor(ILayoutGraph graph, SBMLDocument document, + DynamicCore core, String[] selectedSpecies, + String[] selectedReactions, boolean relativeConcentrations, + double nodeSize, double addSizeForOverview, Color color1, Color color2, Color color3, + float reactionsMinLineWidth, float reactionsMaxLineWidth) { + + // no use of this() because of other super constructor + super(graph, document, core, selectedReactions, reactionsMinLineWidth, reactionsMaxLineWidth); + + this.addSizeForOverview = addSizeForOverview; + + // gather settings + this.nodeSize = nodeSize; + REVERT_NODE_SIZE = nodeSize; + int r = color1.getRed(); + int g = color1.getGreen(); + int b = color1.getBlue(); + RGBcolor1 = new int[] { r, g, b }; + r = color2.getRed(); + g = color2.getGreen(); + b = color2.getBlue(); + RGBcolor2 = new int[] { r, g, b }; + r = color3.getRed(); + g = color3.getGreen(); + b = color3.getBlue(); + RGBcolor3 = new int[] { r, g, b }; + this.relativeConcentrations = relativeConcentrations; + + /* + * Store min/max once to save computation time in case of absolute + * concentration changes. */ - public ManipulatorOfNodeColor(ILayoutGraph graph, SBMLDocument document, DynamicCore core, - String[] selectedSpecies, - String[] selectedReactions) { - - super(graph, document, core, selectedReactions, DEFAULT_MIN_LINEWIDTH, DEFAULT_MAX_LINEWIDTH); - - REVERT_NODE_SIZE = nodeSize; - - // default colors - RGBcolor1 = new int[] { ColorPalette.CAMINE_RED.getRed(), - ColorPalette.CAMINE_RED.getGreen(), - ColorPalette.CAMINE_RED.getBlue() }; - RGBcolor2 = new int[]{255, 255, 255}; //white - RGBcolor3 = new int[]{ ColorPalette.GOLD.getRed(), - ColorPalette.GOLD.getGreen(), - ColorPalette.GOLD.getBlue() }; - /* - * Store min/max once to save computation time in case of absolute - * concentration changes. - */ - minMaxOfSelectedSpecies = core.getMinMaxOfIDs(selectedSpecies); - } - - /** - * Constructs node-color manipulator with the given RGB colors as color1 - * (high) -> color2 (mid) -> color3 (low) and a constant node size. - * {@link Reaction}s line widths as given. Concentration changes as user given. - * - * @param graph - * @param document - * @param core - * @param selectedSpecies - * @param selectedReactions - * @param relativeConcentrations - * @param nodeSize - * @param color1 - * @param color2 - * @param color3 - * @param reactionsMinLineWidth - * @param reactionsMaxLineWidth + minMaxOfSelectedSpecies = core.getMinMaxOfIDs(selectedSpecies); + } + + /** + * Constructs node-color manipulator with the given RGB colors as color1 + * (high) -> color2 (mid) -> color3 (low) and a constant node size. + * {@link Reaction}s line widths as given. Concentration changes as user given. + * + * @param graph + * @param document + * @param core + * @param selectedSpecies + * @param selectedReactions + * @param relativeConcentrations + * @param nodeSize + * @param color1 + * @param reactionsMinLineWidth + * @param reactionsMaxLineWidth + */ + public ManipulatorOfNodeColor(ILayoutGraph graph, SBMLDocument document, + DynamicCore core, String[] selectedSpecies, + String[] selectedReactions, boolean relativeConcentrations, + double nodeSize, double addSizeForOverview, Color color2, float reactionsMinLineWidth, + float reactionsMaxLineWidth) { + + // no use of this() because of other super constructor + super(graph, document, core, selectedReactions, reactionsMinLineWidth, reactionsMaxLineWidth); + + this.addSizeForOverview = addSizeForOverview; + + // gather settings + this.nodeSize = nodeSize; + REVERT_NODE_SIZE = nodeSize; + + Color[] minMax = calculateColorsFromDefault(color2); + + // min + RGBcolor3 = new int[] { minMax[0].getRed(), minMax[0].getGreen(), minMax[0].getBlue() }; + // middle + RGBcolor2 = new int[] { color2.getRed(), color2.getGreen(), color2.getBlue() }; + // max + RGBcolor1 = new int[]{ minMax[1].getRed(), minMax[1].getGreen(), minMax[1].getBlue() }; + + this.relativeConcentrations = relativeConcentrations; + + /* + * Store min/max once to save computation time in case of absolute + * concentration changes. */ - public ManipulatorOfNodeColor(ILayoutGraph graph, SBMLDocument document, - DynamicCore core, String[] selectedSpecies, - String[] selectedReactions, boolean relativeConcentrations, - double nodeSize, Color color1, Color color2, Color color3, - float reactionsMinLineWidth, float reactionsMaxLineWidth) { - - // no use of this() because of other super constructor - super(graph, document, core, selectedReactions, reactionsMinLineWidth, reactionsMaxLineWidth); - - // gather settings - this.nodeSize = nodeSize; - REVERT_NODE_SIZE = nodeSize; - int r = color1.getRed(); - int g = color1.getGreen(); - int b = color1.getBlue(); - RGBcolor1 = new int[] { r, g, b }; - r = color2.getRed(); - g = color2.getGreen(); - b = color2.getBlue(); - RGBcolor2 = new int[] { r, g, b }; - r = color3.getRed(); - g = color3.getGreen(); - b = color3.getBlue(); - RGBcolor3 = new int[] { r, g, b }; - this.relativeConcentrations = relativeConcentrations; - + minMaxOfSelectedSpecies = core.getMinMaxOfIDs(selectedSpecies); + } + + /* (non-Javadoc) + * @see org.sbml.simulator.gui.graph.IGraphManipulator#dynamicChangeOfNode(java.lang.String, double, boolean) + */ + @Override + public void dynamicChangeOfNode(String id, double value, boolean labels) { + if (id2speciesNode.get(id) != null) { + for (Node node : graph.getSpeciesId2nodes().get(id)) { + hide(id, node, false); + + NodeRealizer nr; + if(!node2Realizer.containsKey(node)) { + nr = graph.getGraph2D().getRealizer(node); + node2Realizer.put(node, nr); + } else { + nr = node2Realizer.get(node); + graph.getGraph2D().setRealizer(node, nr); + } + + double addSize = 0; + if(DynamicCore.cameraAnimation && DynamicCore.playAgain) { + addSize = addSizeForOverview; + } + + // init visualization style + double ratio = nr.getHeight() / nr.getWidth(); //keep ratio in case of elliptic nodes + nr.setSize(nodeSize+addSize, nodeSize+addSize*ratio); //standard node size + + double minValue, maxValue; // values to compute adjusting + if (relativeConcentrations) { + /* + * Realtive changes. Use species specific min/max values. + */ + minValue = id2minMaxData.get(id)[0]; + maxValue = id2minMaxData.get(id)[1]; + } else { + /* + * Absolute changes. Use min/max values of all selected species. + */ + minValue = minMaxOfSelectedSpecies[0]; + maxValue = minMaxOfSelectedSpecies[1]; + } + // compute adjusting + double percent = adjustValue(minValue, maxValue, 0, 1, value); + int[] RGBinterpolated = linearColorInterpolationForThree(percent, + RGBcolor1, RGBcolor2, RGBcolor3); + logger.finer(MessageFormat + .format("Species {0}: value={1}, results in percent={2} and r={3}, g={4}, b={5}", + new Object[] { id, value, percent, + RGBinterpolated[0], RGBinterpolated[1], + RGBinterpolated[2] })); + + // visualize + nr.setFillColor(new Color(RGBinterpolated[0], RGBinterpolated[1], RGBinterpolated[2])); + /* - * Store min/max once to save computation time in case of absolute - * concentration changes. + * Label Node with ID and real value at this timepoint. Last label will + * be treated as dynamic label */ - minMaxOfSelectedSpecies = core.getMinMaxOfIDs(selectedSpecies); - } - - /* (non-Javadoc) - * @see org.sbml.simulator.gui.graph.IGraphManipulator#dynamicChangeOfNode(java.lang.String, double, boolean) - */ - @Override - public void dynamicChangeOfNode(String id, double value, boolean labels) { - if (id2speciesNode.get(id) != null) { - for (Node node : graph.getSpeciesId2nodes().get(id)) { - hide(id, node, false); - NodeRealizer nr = graph.getGraph2D().getRealizer(node); - - // init visualization style - double ratio = nr.getHeight() / nr.getWidth(); //keep ratio in case of elliptic nodes - nr.setSize(nodeSize, nodeSize*ratio); //standard node size - - double minValue, maxValue; // values to compute adjusting - if (relativeConcentrations) { - /* - * Realtive changes. Use species specific min/max values. - */ - minValue = id2minMaxData.get(id)[0]; - maxValue = id2minMaxData.get(id)[1]; - } else { - /* - * Absolute changes. Use min/max values of all selected species. - */ - minValue = minMaxOfSelectedSpecies[0]; - maxValue = minMaxOfSelectedSpecies[1]; - } - // compute adjusting - double percent = adjustValue(minValue, maxValue, 0, 1, value); - int[] RGBinterpolated = linearColorInterpolationForThree(percent, - RGBcolor1, RGBcolor2, RGBcolor3); - logger.finer(MessageFormat - .format("Species {0}: value={1}, results in percent={2} and r={3}, g={4}, b={5}", - new Object[] { id, value, percent, - RGBinterpolated[0], RGBinterpolated[1], - RGBinterpolated[2] })); - - // visualize - nr.setFillColor(new Color(RGBinterpolated[0], RGBinterpolated[1], RGBinterpolated[2])); - - /* - * Label Node with ID and real value at this timepoint. Last label will - * be treated as dynamic label - */ - if (labels) { - labelNode(nr, id, value); - } else if (nr.labelCount() > 1) { - // labels switched off, therefore remove them, if there are any - nr.removeLabel(nr.getLabel(nr.labelCount() - 1)); - } - + if (labels) { + labelNode(nr, id, value); + } else if (nr.labelCount() > 1) { + // labels switched off, therefore remove them, if there are any + nr.removeLabel(nr.getLabel(nr.labelCount() - 1)); } - // update view - graph.getGraph2D().updateViews(); + } + // update view + graph.getGraph2D().updateViews(); } + } + + public void setNewMinMaxNodeSize(double minNodeSize, double maxNodeSize) {} + + /** + * resets the adding factor for the node sizes + * @param newSize + */ + @Override + public void setAddSizeForOverview(int newSize) { + addSizeForOverview = newSize; + } } diff --git a/src/org/sbml/simulator/gui/graph/ManipulatorOfNodeColorAndSize.java b/src/org/sbml/simulator/gui/graph/ManipulatorOfNodeColorAndSize.java index c74b464..802ac50 100644 --- a/src/org/sbml/simulator/gui/graph/ManipulatorOfNodeColorAndSize.java +++ b/src/org/sbml/simulator/gui/graph/ManipulatorOfNodeColorAndSize.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -23,10 +21,9 @@ import org.sbml.jsbml.SBMLDocument; +import de.zbit.sbml.layout.y.ILayoutGraph; import y.base.Node; import y.view.NodeRealizer; -import de.zbit.gui.ColorPalette; -import de.zbit.sbml.layout.y.ILayoutGraph; /** @@ -36,7 +33,6 @@ * concentration changes. * * @author Fabian Schwarzkopf - * @version $Rev$ */ public class ManipulatorOfNodeColorAndSize extends AGraphManipulator{ @@ -48,8 +44,13 @@ public class ManipulatorOfNodeColorAndSize extends AGraphManipulator{ /** * Minimum and maximum Node Size with default initialization. */ - private double minNodeSize = DEFAULT_MIN_NODE_SIZE, + private static double minNodeSize = DEFAULT_MIN_NODE_SIZE, maxNodeSize = DEFAULT_MAX_NODE_SIZE; + + /** + * if camera animation is active and overview is shown node size is different + */ + private static double addSizeForOverview; /** * Field for the first color (high concentration), second color (mid @@ -79,21 +80,27 @@ public class ManipulatorOfNodeColorAndSize extends AGraphManipulator{ */ public ManipulatorOfNodeColorAndSize(ILayoutGraph graph, SBMLDocument document, DynamicCore core, String[] selectedSpecies, - String[] selectedReactions) { + String[] selectedReactions, double minNodeSize, double maxNodeSize, double addSizeForOverview, Color color2) { super(graph, document, core, selectedReactions, DEFAULT_MIN_LINEWIDTH, DEFAULT_MAX_LINEWIDTH); + + this.addSizeForOverview = addSizeForOverview; REVERT_NODE_SIZE = DEFAULT_MIN_NODE_SIZE; + if (minNodeSize < maxNodeSize) { + this.minNodeSize = minNodeSize; + this.maxNodeSize = maxNodeSize; + } + + Color[] maxMin = calculateColorsFromDefault(color2); - // default colors - RGBcolor1 = new int[] { ColorPalette.CAMINE_RED.getRed(), - ColorPalette.CAMINE_RED.getGreen(), - ColorPalette.CAMINE_RED.getBlue() }; - RGBcolor2 = new int[]{255, 255, 255}; //white - RGBcolor3 = new int[]{ ColorPalette.GOLD.getRed(), - ColorPalette.GOLD.getGreen(), - ColorPalette.GOLD.getBlue() }; + // max + RGBcolor1 = new int[] { maxMin[0].getRed(), maxMin[0].getGreen(), maxMin[0].getBlue() }; + // middle + RGBcolor2 = new int[] { color2.getRed(), color2.getGreen(), color2.getBlue() }; + // min + RGBcolor3 = new int[]{ maxMin[1].getRed(), maxMin[1].getGreen(), maxMin[1].getBlue() }; /* * Store min/max once to save computation time for absolute part @@ -125,12 +132,14 @@ public ManipulatorOfNodeColorAndSize(ILayoutGraph graph, SBMLDocument document, */ public ManipulatorOfNodeColorAndSize(ILayoutGraph graph, SBMLDocument document, DynamicCore core, String[] selectedSpecies, - String[] selectedReactions, double minNodeSize, double maxNodeSize, + String[] selectedReactions, double minNodeSize, double maxNodeSize, double addSizeForOverview, Color color1, Color color2, Color color3, float reactionsMinLineWidth, float reactionsMaxLineWidth) { // no use of this() because of other super constructor super(graph, document, core, selectedReactions, reactionsMinLineWidth, reactionsMaxLineWidth); + + this.addSizeForOverview = addSizeForOverview; // gather settings if (minNodeSize < maxNodeSize) { @@ -163,11 +172,17 @@ public ManipulatorOfNodeColorAndSize(ILayoutGraph graph, @Override public void dynamicChangeOfNode(String id, double value, boolean labels) { if (id2speciesNode.get(id) != null) { + + double addSize = 0; + if(DynamicCore.cameraAnimation && DynamicCore.playAgain) { + addSize = addSizeForOverview; + } + // compute adusting of node size (relative) double x1 = id2minMaxData.get(id)[0]; double x2 = id2minMaxData.get(id)[1]; - double y1 = minNodeSize; - double y2 = maxNodeSize; + double y1 = minNodeSize+addSize; + double y2 = maxNodeSize+addSize; double size = adjustValue(x1, x2, y1, y2, value); boolean invisible = isInvisible(value); // compute adjusting of node color (absolute) @@ -187,7 +202,16 @@ public void dynamicChangeOfNode(String id, double value, boolean labels) { } else { hide(id, node, false); // visualize - NodeRealizer nr = graph.getGraph2D().getRealizer(node); + + NodeRealizer nr; + if(!node2Realizer.containsKey(node)) { + nr = graph.getGraph2D().getRealizer(node); + node2Realizer.put(node, nr); + } else { + nr = node2Realizer.get(node); + graph.getGraph2D().setRealizer(node, nr); + } + double ratio = nr.getHeight() / nr.getWidth(); // keep ratio in case of elliptic nodes nr.setSize(size, size * ratio); nr.setFillColor(new Color(RGBinterpolated[0], RGBinterpolated[1], @@ -208,5 +232,28 @@ public void dynamicChangeOfNode(String id, double value, boolean labels) { graph.getGraph2D().updateViews(); } } + + /** + * sets new min and max node sizes if they were changed + * @param minNodeSize + * @param maxNodeSize + */ + public void setNewMinMaxNodeSize(double minNodeSize, double maxNodeSize) { + if(this.minNodeSize != minNodeSize) { + this.minNodeSize = minNodeSize; + } + if(this.maxNodeSize != maxNodeSize) { + this.maxNodeSize = maxNodeSize; + } + } + + /** + * resets the adding factor for the node sizes + * @param newSize + */ + @Override + public void setAddSizeForOverview(int newSize) { + addSizeForOverview = newSize; + } } diff --git a/src/org/sbml/simulator/gui/graph/ManipulatorOfNodeSize.java b/src/org/sbml/simulator/gui/graph/ManipulatorOfNodeSize.java index 65d7870..d0a5f7f 100644 --- a/src/org/sbml/simulator/gui/graph/ManipulatorOfNodeSize.java +++ b/src/org/sbml/simulator/gui/graph/ManipulatorOfNodeSize.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -33,9 +31,8 @@ * nodes and width of given reactions. * * @author Fabian Schwarzkopf - * @version $Rev$ */ -public class ManipulatorOfNodeSize extends AGraphManipulator{ +public class ManipulatorOfNodeSize extends AGraphManipulator{ /** * A {@link Logger} for this class. @@ -61,8 +58,13 @@ public class ManipulatorOfNodeSize extends AGraphManipulator{ /** * Minimum and maximum Node Size with default initialization. */ - private double minNodeSize = DEFAULT_MIN_NODE_SIZE, + private static double minNodeSize = DEFAULT_MIN_NODE_SIZE, maxNodeSize = DEFAULT_MAX_NODE_SIZE; + + /** + * if camera animation is active and overview is shown node size is different + */ + private static double addSizeForOverview; /** * Concentration changes relativ or absolute? Per default false. @@ -89,13 +91,15 @@ public class ManipulatorOfNodeSize extends AGraphManipulator{ */ public ManipulatorOfNodeSize(ILayoutGraph isbmlLayoutGraph, SBMLDocument document, DynamicCore core, Color uniformNodeColor, String[] selectedSpecies, - String[] selectedReactions, double minNodeSize, double maxNodeSize, + String[] selectedReactions, double minNodeSize, double maxNodeSize, double addSizeForOverview, boolean relativeConcentrations, float reactionsMinLineWidth, float reactionsMaxLineWidth) { // no use of this() because of other super constructor super(isbmlLayoutGraph, document, core, selectedReactions, reactionsMinLineWidth, reactionsMaxLineWidth); + + this.addSizeForOverview = addSizeForOverview; if (minNodeSize < maxNodeSize) { this.minNodeSize = minNodeSize; @@ -134,12 +138,14 @@ public ManipulatorOfNodeSize(ILayoutGraph isbmlLayoutGraph, SBMLDocument documen public ManipulatorOfNodeSize(ILayoutGraph graph, SBMLDocument document, DynamicCore core, LegendTableModel legendTableModel, String[] selectedSpecies, String[] selectedReactions, - double minNodeSize, double maxNodeSize, + double minNodeSize, double maxNodeSize, double addSizeForOverview, boolean relativeConcentrations, float reactionsMinLinewidth, float reactionsMaxLineWidth) { super(graph, document, core, selectedReactions, reactionsMinLinewidth, reactionsMaxLineWidth); + + this.addSizeForOverview = addSizeForOverview; this.legendTable = legendTableModel; if (minNodeSize < maxNodeSize) { @@ -204,10 +210,16 @@ public void dynamicChangeOfNode(String id, double value, boolean labels) { minValue = minMaxOfSelectedSpecies[0]; maxValue = minMaxOfSelectedSpecies[1]; } + + double addSize = 0; + if(DynamicCore.cameraAnimation && DynamicCore.playAgain) { + addSize = addSizeForOverview; + } // compute adusting - double size = adjustValue(minValue, maxValue, minNodeSize, - maxNodeSize, value); + double size = adjustValue(minValue, maxValue, minNodeSize+addSize, + maxNodeSize+addSize, value); + boolean invisible = isInvisible(value); logger.finer(MessageFormat.format( "Species {0}: value={1}, results in node size={2}", @@ -220,7 +232,16 @@ public void dynamicChangeOfNode(String id, double value, boolean labels) { else { hide(id, node, false); // visualize - NodeRealizer nr = graph.getGraph2D().getRealizer(node); + + NodeRealizer nr; + if(!node2Realizer.containsKey(node)) { + nr = graph.getGraph2D().getRealizer(node); + node2Realizer.put(node, nr); + } else { + nr = node2Realizer.get(node); + graph.getGraph2D().setRealizer(node, nr); + } + double ratio = nr.getHeight() / nr.getWidth(); //keep ratio in case of elliptic nodes nr.setSize(size, size * ratio); //use standard color if no legendTableModel is provided @@ -248,5 +269,28 @@ public void dynamicChangeOfNode(String id, double value, boolean labels) { graph.getGraph2D().updateViews(); } } + + /** + * sets new min and max node sizes if they were changed + * @param minNodeSize + * @param maxNodeSize + */ + public void setNewMinMaxNodeSize(double minNodeSize, double maxNodeSize) { + if(this.minNodeSize != minNodeSize) { + this.minNodeSize = minNodeSize; + } + if(this.maxNodeSize != maxNodeSize) { + this.maxNodeSize = maxNodeSize; + } + } + + /** + * resets the adding factor for the node sizes + * @param newSize + */ + @Override + public void setAddSizeForOverview(int newSize) { + addSizeForOverview = newSize; + } } diff --git a/src/org/sbml/simulator/gui/graph/ManipulatorOfNodeSizeAndColor.java b/src/org/sbml/simulator/gui/graph/ManipulatorOfNodeSizeAndColor.java index 75a1da1..3040806 100644 --- a/src/org/sbml/simulator/gui/graph/ManipulatorOfNodeSizeAndColor.java +++ b/src/org/sbml/simulator/gui/graph/ManipulatorOfNodeSizeAndColor.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -23,10 +21,9 @@ import org.sbml.jsbml.SBMLDocument; +import de.zbit.sbml.layout.y.ILayoutGraph; import y.base.Node; import y.view.NodeRealizer; -import de.zbit.gui.ColorPalette; -import de.zbit.sbml.layout.y.ILayoutGraph; /** @@ -36,177 +33,226 @@ * concentration changes. * * @author Fabian Schwarzkopf - * @version $Rev$ */ public class ManipulatorOfNodeSizeAndColor extends AGraphManipulator { - - /** - * A {@link Logger} for this class. - */ - private static final transient Logger logger = Logger.getLogger(ManipulatorOfNodeSizeAndColor.class.getName()); - - /** - * Minimum and maximum Node Size with default initialization. - */ - private double minNodeSize = DEFAULT_MIN_NODE_SIZE, - maxNodeSize = DEFAULT_MAX_NODE_SIZE; - - /** - * Field for the first color (high concentration), second color (mid - * concentration), third color (low concentration). - */ - private int[] RGBcolor1, RGBcolor2, RGBcolor3; - - /** - * Saves minimum and maximum value of selected Species to save computation - * time. - */ - private double[] minMaxOfSelectedSpecies; - - /** - * Constructs a new node-size and node-color manipulator. Changes of - * node-size are computed absolute, changes of node-color are computed - * relative. Minimum node size and maximum node size per default and - * reactions line widths per default. Default gradient camine red (high) -> - * white (mid) -> gold (low). - * - * @param graph - * @param document - * @param core - * @param selectedSpecies - * @param selectedReactions - */ - public ManipulatorOfNodeSizeAndColor(ILayoutGraph graph, SBMLDocument document, - DynamicCore core, String[] selectedSpecies, - String[] selectedReactions) { - - super(graph, document, core, selectedReactions, DEFAULT_MIN_LINEWIDTH, - DEFAULT_MAX_LINEWIDTH); - - REVERT_NODE_SIZE = DEFAULT_MIN_NODE_SIZE; - - // default colors - RGBcolor1 = new int[] { ColorPalette.CAMINE_RED.getRed(), - ColorPalette.CAMINE_RED.getGreen(), - ColorPalette.CAMINE_RED.getBlue() }; - RGBcolor2 = new int[]{255, 255, 255}; //white - RGBcolor3 = new int[]{ ColorPalette.GOLD.getRed(), - ColorPalette.GOLD.getGreen(), - ColorPalette.GOLD.getBlue() }; - - /* - * Store min/max once to save computation time for absolute part - * concentration changes. - */ - minMaxOfSelectedSpecies = core.getMinMaxOfIDs(selectedSpecies); + + /** + * A {@link Logger} for this class. + */ + private static final transient Logger logger = Logger.getLogger(ManipulatorOfNodeSizeAndColor.class.getName()); + + /** + * Minimum and maximum Node Size with default initialization. + */ + private static double minNodeSize = DEFAULT_MIN_NODE_SIZE, + maxNodeSize = DEFAULT_MAX_NODE_SIZE; + + /** + * if camera animation is active and overview is shown node size is different + */ + private static double addSizeForOverview; + + /** + * Field for the first color (high concentration), second color (mid + * concentration), third color (low concentration). + */ + private int[] RGBcolor1, RGBcolor2, RGBcolor3; + + /** + * Saves minimum and maximum value of selected Species to save computation + * time. + */ + private double[] minMaxOfSelectedSpecies; + + /** + * Constructs a new node-size and node-color manipulator. Changes of + * node-size are computed absolute, changes of node-color are computed + * relative. Minimum node size and maximum node size per default and + * reactions line widths per default. Default gradient camine red (high) -> + * white (mid) -> gold (low). + * + * @param graph + * @param document + * @param core + * @param selectedSpecies + * @param selectedReactions + */ + public ManipulatorOfNodeSizeAndColor(ILayoutGraph graph, SBMLDocument document, + DynamicCore core, String[] selectedSpecies, + String[] selectedReactions, double minNodeSize, double maxNodeSize, double addSizeForOverview, Color color2) { + + super(graph, document, core, selectedReactions, DEFAULT_MIN_LINEWIDTH, + DEFAULT_MAX_LINEWIDTH); + + this.addSizeForOverview = addSizeForOverview; + + REVERT_NODE_SIZE = DEFAULT_MIN_NODE_SIZE; + if (minNodeSize < maxNodeSize) { + this.minNodeSize = minNodeSize; + this.maxNodeSize = maxNodeSize; } - - /** - * Constructs a new node-size and node-color manipulator. Changes of - * node-size are computed absolute, changes of node-color are computed - * relative. Minimum node size and maximum node size as given. If minimum - * node size greater than maximum node size, default values will be used. - * Color gradient as given by color1 (high) -> color2 (mid) -> color3 (low). - * Reactions line widths as given. - * - * @param graph - * @param document - * @param core - * @param selectedSpecies - * @param selectedReactions - * @param minNodeSize - * @param maxNodeSize - * @param color1 - * @param color2 - * @param color3 - * @param reactionsMinLinewidth - * @param reactionsMaxLineWidth + + Color[] minMax = calculateColorsFromDefault(color2); + + // min + RGBcolor3 = new int[] { minMax[0].getRed(), minMax[0].getGreen(), minMax[0].getBlue() }; + // middle + RGBcolor2 = new int[] { color2.getRed(), color2.getGreen(), color2.getBlue() }; + // max + RGBcolor1 = new int[]{ minMax[1].getRed(), minMax[1].getGreen(), minMax[1].getBlue() }; + + /* + * Store min/max once to save computation time for absolute part + * concentration changes. */ - public ManipulatorOfNodeSizeAndColor(ILayoutGraph graph, - SBMLDocument document, DynamicCore core, String[] selectedSpecies, - String[] selectedReactions, double minNodeSize, double maxNodeSize, - Color color1, Color color2, Color color3, - float reactionsMinLineWidth, float reactionsMaxLineWidth) { - - // no use of this() because of other super constructor - super(graph, document, core, selectedReactions, reactionsMinLineWidth, reactionsMaxLineWidth); - - // gather settings - if (minNodeSize < maxNodeSize) { - this.minNodeSize = minNodeSize; - this.maxNodeSize = maxNodeSize; - } // else ignore input and use default node sizes - int r = color1.getRed(); - int g = color1.getGreen(); - int b = color1.getBlue(); - RGBcolor1 = new int[] { r, g, b }; - r = color2.getRed(); - g = color2.getGreen(); - b = color2.getBlue(); - RGBcolor2 = new int[] { r, g, b }; - r = color3.getRed(); - g = color3.getGreen(); - b = color3.getBlue(); - RGBcolor3 = new int[] { r, g, b }; - - /* - * Store min/max once to save computation time for absolute part of - * concentration changes. - */ - minMaxOfSelectedSpecies = core.getMinMaxOfIDs(selectedSpecies); - } + minMaxOfSelectedSpecies = core.getMinMaxOfIDs(selectedSpecies); + } + + /** + * Constructs a new node-size and node-color manipulator. Changes of + * node-size are computed absolute, changes of node-color are computed + * relative. Minimum node size and maximum node size as given. If minimum + * node size greater than maximum node size, default values will be used. + * Color gradient as given by color1 (high) -> color2 (mid) -> color3 (low). + * Reactions line widths as given. + * + * @param graph + * @param document + * @param core + * @param selectedSpecies + * @param selectedReactions + * @param minNodeSize + * @param maxNodeSize + * @param color1 + * @param color2 + * @param color3 + * @param reactionsMinLinewidth + * @param reactionsMaxLineWidth + */ + public ManipulatorOfNodeSizeAndColor(ILayoutGraph graph, + SBMLDocument document, DynamicCore core, String[] selectedSpecies, + String[] selectedReactions, double minNodeSize, double maxNodeSize, double addSizeForOverview, + Color color1, Color color2, Color color3, + float reactionsMinLineWidth, float reactionsMaxLineWidth) { + + // no use of this() because of other super constructor + super(graph, document, core, selectedReactions, reactionsMinLineWidth, reactionsMaxLineWidth); + + this.addSizeForOverview = addSizeForOverview; + + // gather settings + if (minNodeSize < maxNodeSize) { + this.minNodeSize = minNodeSize; + this.maxNodeSize = maxNodeSize; + } // else ignore input and use default node sizes + int r = color1.getRed(); + int g = color1.getGreen(); + int b = color1.getBlue(); + RGBcolor1 = new int[] { r, g, b }; + r = color2.getRed(); + g = color2.getGreen(); + b = color2.getBlue(); + RGBcolor2 = new int[] { r, g, b }; + r = color3.getRed(); + g = color3.getGreen(); + b = color3.getBlue(); + RGBcolor3 = new int[] { r, g, b }; - /* (non-Javadoc) - * @see org.sbml.simulator.gui.graph.IGraphManipulator#dynamicChangeOfNode(java.lang.String, double, boolean) + /* + * Store min/max once to save computation time for absolute part of + * concentration changes. */ - @Override - public void dynamicChangeOfNode(String id, double value, boolean labels) { - if (id2speciesNode.get(id) != null) { - - // compute adusting of node size (absolute) - double size = adjustValue(minMaxOfSelectedSpecies[0], - minMaxOfSelectedSpecies[1], minNodeSize, maxNodeSize, value); - - boolean invisible = isInvisible(value); - - // compute adjusting of node color (relative) - double percent = adjustValue(id2minMaxData.get(id)[0], - id2minMaxData.get(id)[1], 0, 1, value); - int[] RGBinterpolated = linearColorInterpolationForThree(percent, - RGBcolor1, RGBcolor2, RGBcolor3); - logger.finer(MessageFormat - .format("Species {0}: value={1}, results in node size={2} and color percent={3} and r={4}, g={5}, b={6}", - new Object[] { id, value, size, percent, - RGBinterpolated[0], RGBinterpolated[1], - RGBinterpolated[2] })); - - for (Node node : graph.getSpeciesId2nodes().get(id)) { - if (invisible) { - hide(id, node, true); - } - else { - hide(id, node, false); - // visualize - NodeRealizer nr = graph.getGraph2D().getRealizer(node); - double ratio = nr.getHeight() / nr.getWidth(); // keep ratio in case of elliptic nodes - nr.setSize(size, size * ratio); - nr.setFillColor(new Color(RGBinterpolated[0], RGBinterpolated[1], - RGBinterpolated[2])); - /* - * Label Node with ID and real value at this timepoint. Last label will - * be treated as dynamic label - */ - if (labels) { - labelNode(nr, id, value); - } else if (nr.labelCount() > 1) { - // labels switched off, therefore remove them, if there are any - nr.removeLabel(nr.getLabel(nr.labelCount() - 1)); - } - } - } - // update view - graph.getGraph2D().updateViews(); + minMaxOfSelectedSpecies = core.getMinMaxOfIDs(selectedSpecies); + } + + /* (non-Javadoc) + * @see org.sbml.simulator.gui.graph.IGraphManipulator#dynamicChangeOfNode(java.lang.String, double, boolean) + */ + @Override + public void dynamicChangeOfNode(String id, double value, boolean labels) { + if (id2speciesNode.get(id) != null) { + + double addSize = 0; + if(DynamicCore.cameraAnimation && DynamicCore.playAgain) { + addSize = addSizeForOverview; + } + + // compute adusting of node size (absolute) + double size = adjustValue(minMaxOfSelectedSpecies[0], + minMaxOfSelectedSpecies[1], minNodeSize+addSize, maxNodeSize+addSize, value); + + boolean invisible = isInvisible(value); + + // compute adjusting of node color (relative) + double percent = adjustValue(id2minMaxData.get(id)[0], + id2minMaxData.get(id)[1], 0, 1, value); + int[] RGBinterpolated = linearColorInterpolationForThree(percent, + RGBcolor1, RGBcolor2, RGBcolor3); + logger.finer(MessageFormat + .format("Species {0}: value={1}, results in node size={2} and color percent={3} and r={4}, g={5}, b={6}", + new Object[] { id, value, size, percent, + RGBinterpolated[0], RGBinterpolated[1], + RGBinterpolated[2] })); + + for (Node node : graph.getSpeciesId2nodes().get(id)) { + if (invisible) { + hide(id, node, true); + } + else { + hide(id, node, false); + // visualize + + NodeRealizer nr; + if(!node2Realizer.containsKey(node)) { + nr = graph.getGraph2D().getRealizer(node); + node2Realizer.put(node, nr); + } else { + nr = node2Realizer.get(node); + graph.getGraph2D().setRealizer(node, nr); + } + + double ratio = nr.getHeight() / nr.getWidth(); // keep ratio in case of elliptic nodes + nr.setSize(size, size * ratio); + nr.setFillColor(new Color(RGBinterpolated[0], RGBinterpolated[1], + RGBinterpolated[2])); + /* + * Label Node with ID and real value at this timepoint. Last label will + * be treated as dynamic label + */ + if (labels) { + labelNode(nr, id, value); + } else if (nr.labelCount() > 1) { + // labels switched off, therefore remove them, if there are any + nr.removeLabel(nr.getLabel(nr.labelCount() - 1)); + } } + } + // update view + graph.getGraph2D().updateViews(); } + } + + /** + * sets new min and max node sizes if they were changed + * @param minNodeSize + * @param maxNodeSize + */ + public void setNewMinMaxNodeSize(double minNodeSize, double maxNodeSize) { + if(this.minNodeSize != minNodeSize) { + this.minNodeSize = minNodeSize; + } + if(this.maxNodeSize != maxNodeSize) { + this.maxNodeSize = maxNodeSize; + } + } + + /** + * resets the adding factor for the node sizes + * @param newSize + */ + @Override + public void setAddSizeForOverview(int newSize) { + addSizeForOverview = newSize; + } } diff --git a/src/org/sbml/simulator/gui/graph/RearrangeCycles.java b/src/org/sbml/simulator/gui/graph/RearrangeCycles.java new file mode 100644 index 0000000..2168c45 --- /dev/null +++ b/src/org/sbml/simulator/gui/graph/RearrangeCycles.java @@ -0,0 +1,382 @@ +package org.sbml.simulator.gui.graph; + +import java.util.ArrayList; +import java.util.List; + +import org.sbml.jsbml.ListOf; +import org.sbml.jsbml.Model; +import org.sbml.jsbml.SBase; +import org.sbml.jsbml.ext.layout.BoundingBox; +import org.sbml.jsbml.ext.layout.CubicBezier; +import org.sbml.jsbml.ext.layout.Curve; +import org.sbml.jsbml.ext.layout.CurveSegment; +import org.sbml.jsbml.ext.layout.Dimensions; +import org.sbml.jsbml.ext.layout.GraphicalObject; +import org.sbml.jsbml.ext.layout.Layout; +import org.sbml.jsbml.ext.layout.Point; +import org.sbml.jsbml.ext.layout.ReactionGlyph; +import org.sbml.jsbml.ext.layout.SpeciesGlyph; +import org.sbml.jsbml.ext.layout.SpeciesReferenceGlyph; +import org.sbml.jsbml.ext.layout.SpeciesReferenceRole; +import org.sbml.jsbml.ext.layout.TextGlyph; + +/** + * This class arranges all Species and its TextGlyphs in a correct circle which are involved in a cycle. + * All curveSegments are deleted and new BezierCurves are calculated + * + * @author Lea Buchweitz + */ + +public class RearrangeCycles implements Runnable{ + + private List allGraphicalElements; + private List nodes; + //private List startEndPoints; + private List basePointsCycle; + private List basePointsSides; + private List allElements; + + private Model model; + private Layout layout; + private Point centerOfCircle; + + private double radius; + private double speciesSize; + private double reactionSize; + + public RearrangeCycles(Layout layout, List allElements, double radius) { + + allGraphicalElements = new ArrayList(); + //startEndPoints = new ArrayList(); + nodes = new ArrayList(); + basePointsCycle = new ArrayList(); + basePointsSides = new ArrayList(); + + // ist unn�tig, allGraphicalElements hat dieselben infos, nur nicht NUR als ID + this.allElements = allElements; + this.layout = layout; + this.radius = radius; + model = layout.getModel(); + + for(String id : allElements) + { + SBase elem = model.findUniqueNamedSBase(id); + if((elem != null) && (elem instanceof GraphicalObject)) + { + allGraphicalElements.add((GraphicalObject) elem); + } + } + run(); + } + + @Override + public void run() { + + List objWithText = new ArrayList(); + + // get text elements + for(GraphicalObject obj : allGraphicalElements) + { + nodes.add(obj.getBoundingBox()); + + if(obj instanceof ReactionGlyph) { + objWithText.add(((ReactionGlyph) obj).getId()); + reactionSize = ((ReactionGlyph) obj).getBoundingBox().getDimensions().getWidth(); + } + if(obj instanceof SpeciesGlyph) { + objWithText.add(((SpeciesGlyph) obj).getId()); + speciesSize = ((SpeciesGlyph) obj).getBoundingBox().getDimensions().getWidth(); + } + } + + centerOfCircle = calculateCircleCenter(allGraphicalElements, radius); + + List translateVectors = calculatePositionsOnCircle(nodes, centerOfCircle, radius); + + System.out.println("NEUE ANORDNUNG RUM"); + + for(GraphicalObject obj : allGraphicalElements) + { + if(obj instanceof ReactionGlyph) + { + Point start = ((ReactionGlyph) obj).getBoundingBox().getPosition(); + + ListOf speciesRefList = ((ReactionGlyph) obj).getListOfSpeciesReferenceGlyphs(); + + Curve curve = new Curve(); + + // deletes every linesegment or curve from speciesreferences + for(int i=0; i < speciesRefList.getChildCount(); i++) + { + curve = speciesRefList.get(i).getCurve(); + for(int n = curve.getCurveSegmentCount()-1; n >= 0; n--) { + curve.removeCurveSegment(n); + } + } + + // traverse all species which are part of that reaction + for(int i=0; i < speciesRefList.getChildCount(); i++) + { + boolean switchPoints = false; + + SBase species = model.findUniqueNamedSBase(speciesRefList.get(i).getSpeciesGlyph()); + Point end = ((SpeciesGlyph) species).getBoundingBox().getPosition(); + + // if current speciesGlyph is part of the cycle + if(allElements.contains(speciesRefList.get(i).getSpeciesGlyph())) + { + // if the speciesGlyph is the substrate of the reaction the beziercurve will + // be drawn from there to the reactionnode + if(speciesRefList.get(i).getRole() == SpeciesReferenceRole.SUBSTRATE) { + switchPoints = true; + } + + CubicBezier cubicBez = new CubicBezier(speciesRefList.get(i).getLevel(), speciesRefList.get(i).getVersion()); + if(switchPoints) // species is start, reaction is end + { + Point direction = new Point(start.x()-end.x(), start.y()-end.y(),start.z()); + double norm = 1/(Math.sqrt(Math.pow(direction.x(), 2)+Math.pow(direction.y(), 2))); + + cubicBez.createEnd((start.x()+(reactionSize/2))-(direction.x()*norm*15), + (start.y()+(reactionSize/2))-(direction.y()*norm*15), start.z()); + cubicBez.createStart(end.x()+(speciesSize/2), end.y()+(speciesSize/2), end.z()); + cubicBez.createBasePoint2(-((start.y()-centerOfCircle.y())), + ((start.x()-centerOfCircle.x())), start.z()); + cubicBez.createBasePoint1((end.y()-centerOfCircle.y()), + -((end.x()-centerOfCircle.x())), end.z()); + //System.out.println("Bezier f�r Substrat " + speciesRefList.get(i)); + + } else // species is end, reaction is start + { + Point direction = new Point(end.x()-start.x(),end.y()-start.y(),start.z()); + double norm = 1/(Math.sqrt(Math.pow(direction.x(), 2)+Math.pow(direction.y(), 2))); + + cubicBez.createStart((start.x()+(reactionSize/2))-(direction.x()*norm*15), + (start.y()+(reactionSize/2))-(direction.y()*norm*15), start.z()); + cubicBez.createEnd(end.x()+(speciesSize/2), end.y()+(speciesSize/2), end.z()); + cubicBez.createBasePoint1((start.y()-centerOfCircle.y()), + -((start.x()-centerOfCircle.x())), start.z()); + cubicBez.createBasePoint2(-((end.y()-centerOfCircle.y())), + (end.x()-centerOfCircle.x()), end.z()); + //System.out.println("Bezier f�r Produkt " + speciesRefList.get(i)); + } + curve = speciesRefList.get(i).getCurve(); + curve.addCurveSegment(cubicBez); + basePointsCycle.add(cubicBez); + + if(speciesRefList.get(i).getSpeciesGlyph().equals("_1576570")) { + //System.out.println("Ich " + speciesRefList.get(i).getSpeciesGlyph() +" habe "+speciesRefList.get(i).getCurve().getCurveSegmentCount()); + } + } + } + } + } + + calculateBezierBasePoints(basePointsCycle, centerOfCircle, radius); + + ReactionGlyph reac = new ReactionGlyph(); + + for(GraphicalObject obj : allGraphicalElements) + { + if(obj instanceof ReactionGlyph) + { + reac = (ReactionGlyph) obj; + + Point start = ((ReactionGlyph) obj).getBoundingBox().getPosition(); + + ListOf speciesRefList = ((ReactionGlyph) obj).getListOfSpeciesReferenceGlyphs(); + + Curve curve = new Curve(); + + // gets new starting point of the sidesubstrates and sideproducts + for(int i=0; i < speciesRefList.getChildCount(); i++) + //evtl getspeciesreferenceglyphcount?!?! (-> reactionglyph) + { + double thirdX = 0; + double thirdY = 0; + + SpeciesReferenceRole srr = SpeciesReferenceRole.UNDEFINED; + + Point end = new Point(); + + if(speciesRefList.get(i).getRole() == SpeciesReferenceRole.SIDESUBSTRATE) + { + srr = SpeciesReferenceRole.SUBSTRATE; + } + + if(speciesRefList.get(i).getRole() == SpeciesReferenceRole.SIDEPRODUCT) { + srr = SpeciesReferenceRole.PRODUCT; + } + + // search in whole speciesreferencelist for the substrate of sidesubstrate + for(int k = speciesRefList.getChildCount()-1 ; k >= 0 ; k--) + { + if((speciesRefList.get(k).getRole() == srr) && (srr != SpeciesReferenceRole.UNDEFINED)) + { + //System.out.println("srr muss produkt sein: " + srr+ " reaction ist: " + obj.getId()); + //System.out.println(srr+" ist "+speciesRefList.get(k)+ " zu "+speciesRefList.get(i)); + ListOf seg = speciesRefList.get(k).getCurve().getListOfCurveSegments(); + // Behelf f�r oben_links + if(seg.size() != 0) { + CubicBezier existingBez = (CubicBezier) seg.getFirst(); + + // get sidesubstrate position + SBase species = model.findUniqueNamedSBase(speciesRefList.get(i).getSpeciesGlyph()); + end = ((SpeciesGlyph) species).getBoundingBox().getPosition(); + + double t = 0.2; + + // calculate point on bezier curve + thirdX = (Math.pow((1-t),3)*existingBez.getStart().x())+ + (3*Math.pow((1-t),2)*t*existingBez.getBasePoint1().x())+ + (3*(1-t)*Math.pow(t,2)*existingBez.getBasePoint2().x())+ + (Math.pow(t,3)*existingBez.getEnd().x()); + thirdY = (Math.pow((1-t),3)*existingBez.getStart().y())+ + (3*Math.pow((1-t),2)*t*existingBez.getBasePoint1().y())+ + (3*(1-t)*Math.pow(t,2)*existingBez.getBasePoint2().y())+ + (Math.pow(t,3)*existingBez.getEnd().y()); + + CubicBezier cubicBez = new CubicBezier(speciesRefList.get(i).getLevel(), speciesRefList.get(i).getVersion()); + + if(speciesRefList.get(i).getRole() == SpeciesReferenceRole.SIDESUBSTRATE) + { + cubicBez.createEnd(thirdX, thirdY, 0); + cubicBez.createStart(end.x()+(speciesSize/2), end.y()+(speciesSize/2), end.z()); + } else + { + cubicBez.createStart(thirdX, thirdY, 0); + cubicBez.createEnd(end.x()+(speciesSize/2), end.y()+(speciesSize/2), end.z()); + } + + cubicBez.createBasePoint1(end.y()-thirdY, -(end.x()-thirdX), start.z()); + cubicBez.createBasePoint2(-(end.y()-thirdY), end.x()-thirdX, end.z()); + curve = speciesRefList.get(i).getCurve(); + curve.addCurveSegment(cubicBez); + basePointsSides.add(cubicBez); + } // neue if klammer + } + } + } + } + } + + calculateBezierBasePoints(basePointsSides, centerOfCircle, radius); + + calculateTextGlyphPositions(objWithText, translateVectors, layout.getListOfTextGlyphs(), radius); + + //YGraphView windowView = new YGraphView(model.getSBMLDocument()); + + } + + // calculates the center of all speciesGlyphs and reactionGlyphs + private Point calculateCircleCenter(List points , double radius) + { + double centerX = 0; + double centerY = 0; + + for (int i = 0; i < points.size(); i++) { + GraphicalObject obj = points.get(i); + BoundingBox box = obj.getBoundingBox(); + Point p = box.getPosition(); + + centerX += p.getX(); + centerY += p.getY(); + } + + centerX = centerX / points.size(); + centerY = centerY / points.size(); + + return new Point(centerX, centerY, 0); + } + + // transforms all speciesGlyphs and reactionGlyphs on the circle + half of BoundingBox + private List calculatePositionsOnCircle(List points, Point center, double radius) + { + List translateVectors = new ArrayList(); + Point p; + BoundingBox box = new BoundingBox(); + boolean isNode = false; + + for (BoundingBox obj : points) { + box = obj; + p = box.getPosition(); + isNode = true; + + double diffX = p.getX() - center.getX(); + double diffY = p.getY() - center.getY(); + double diffLength = Math.sqrt(Math.pow(diffX, 2) + Math.pow(diffY, 2)); + + + if(isNode) + { + p.setX((((diffX / diffLength) * radius) + center.getX()) - middleOfElemX(box.getDimensions())); + p.setY((((diffY / diffLength) * radius) + center.getY()) - middleOfElemY(box.getDimensions())); + + translateVectors.add(new Point(diffX,diffY,diffLength)); + } + } + + return translateVectors; + } + + // gets width of a speciesGlyph or reactionGlyph + private double middleOfElemX(Dimensions dim) { + return (dim.getWidth()/2); + } + + // gets height of a speciesGlyph or reactionGlyph + private double middleOfElemY(Dimensions dim) { + return (dim.getHeight()/2); + } + + // translates the text to the circle as well + private void calculateTextGlyphPositions(List ids, List translate, ListOf textElements, + double radius) { + + for(int i = 0; i < ids.size(); i++) { + + Point p = translate.get(i); + + for(int k = 0; k < textElements.size(); k++) { + + if(textElements.get(k).getGraphicalObject().toString().equals(ids.get(i))) { + textElements.get(k).getBoundingBox().getPosition().setX(textElements.get(k) + .getBoundingBox().getPosition().getX()+((p.getX()/p.getZ())*(radius-p.getZ()))); + textElements.get(k).getBoundingBox().getPosition().setY(textElements.get(k) + .getBoundingBox().getPosition().getY()+((p.getY()/p.getZ())*(radius-p.getZ()))); + break; + } + } + } + } + + + // calculates the controlpoints of the new beziercurve + private void calculateBezierBasePoints(List cubicBeziers, Point center, double radius) { + + for(CubicBezier seg : cubicBeziers) { + + double startCenterX = seg.getStart().getX()-center.getX(); + double startCenterY = seg.getStart().getY()-center.getY(); + + double endCenterX = seg.getEnd().getX()-center.getX(); + double endCenterY = seg.getEnd().getY()-center.getY(); + + double a = (4/3)*Math.tan(0.25*Math.acos(((startCenterX * endCenterX) + (startCenterY * endCenterY))/(Math.sqrt(Math.pow(startCenterX, 2)+ + Math.pow(startCenterY, 2))* (Math.sqrt(Math.pow(endCenterX, 2)+ + Math.pow(endCenterY, 2)))))); + + if(!Double.isNaN(a)) { + + seg.getBasePoint1().setX((seg.getStart().getX()+(a*startCenterY))); + seg.getBasePoint1().setY((seg.getStart().getY()+(a*-startCenterX))); + + seg.getBasePoint2().setX((seg.getEnd().getX()+(a*-endCenterY))); + seg.getBasePoint2().setY((seg.getEnd().getY()+(a*endCenterX))); + + } else { + System.out.println("a ist: "+a); + } + } + } +} diff --git a/src/org/sbml/simulator/gui/graph/TestCycleArranging.java b/src/org/sbml/simulator/gui/graph/TestCycleArranging.java new file mode 100644 index 0000000..f5870d4 --- /dev/null +++ b/src/org/sbml/simulator/gui/graph/TestCycleArranging.java @@ -0,0 +1,155 @@ +package org.sbml.simulator.gui.graph; + +import java.awt.BorderLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; +import java.util.ResourceBundle; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.xml.stream.XMLStreamException; + +import org.sbml.jsbml.ListOf; +import org.sbml.jsbml.Model; +import org.sbml.jsbml.SBMLDocument; +import org.sbml.jsbml.SBMLReader; +import org.sbml.jsbml.ext.layout.Layout; +import org.sbml.jsbml.ext.layout.LayoutConstants; +import org.sbml.jsbml.ext.layout.LayoutModelPlugin; + +import de.zbit.io.OpenedFile; +import de.zbit.sbml.gui.SBMLWritingTask; +import de.zbit.util.ResourceManager; + +/** + * This class reads out all the objects which are given from a .txt file. All given objects are either + * ReactionGlyphs or SpeciesGlyphs which are involved in a cycle. + * If the objects are arranged, a new .xml document is saved to use with SBMLsimulator + * + * @author Lea Buchweitz + */ + +public class TestCycleArranging { + + public static final transient ResourceBundle bundle = ResourceManager.getBundle("org.sbml.simulator.gui.graph.DynamicGraph"); + public static int allInfos = 0; + public static SBMLDocument data; + public static File file; + + public static void main(String[] args) throws XMLStreamException, IOException + { + file = new File(args[0]); + data = SBMLReader.read(file); + + //new YGraphView(data.getSBMLDocument()); + + TestCycleArranging start = new TestCycleArranging(); + start.getInfoAboutCycles(); + + } + + private void getInfoAboutCycles() { + + ButtonPressed buttonPressed = new ButtonPressed(); + String circleRad = bundle.getString("RADIUS_OF_CIRCLE"); + + JLabel pathReactions = new JLabel(bundle.getString("FILE_WITH_REACTIONNODES")); + JButton searchReactions = new JButton("..."); + searchReactions.addActionListener(buttonPressed); + + JLabel pathSpecies = new JLabel(bundle.getString("FILE_WITH_SPECIES")); + JButton searchSpecies = new JButton("..."); + searchSpecies.addActionListener(buttonPressed); + + JTextField radius = new JTextField(); + radius.setText(circleRad); + + JPanel panel = new JPanel(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + + JFrame window = new JFrame(); + + window.setSize(300,200); + window.setTitle("Zykel Infos"); + window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + + JButton ok = new JButton("OK"); + ok.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) + { + List allElements = new LinkedList(); + double givenRadius = 0; + if((allInfos == 2) && !radius.getText().equals(circleRad)) { + allElements = buttonPressed.elements; + givenRadius = Double.parseDouble(radius.getText()); + window.dispose(); + try { + startRedrawingData(allElements, givenRadius); + } catch (FileNotFoundException e1) { + e1.printStackTrace(); + } + } + } + }); + + c.fill = GridBagConstraints.HORIZONTAL; + c.gridx = 0; + c.gridy = 0; + panel.add(pathReactions, c); + c.gridx = 0; + c.gridy = 1; + panel.add(pathSpecies, c); + c.gridx = 1; + c.gridy = 0; + panel.add(searchReactions, c); + c.gridx = 1; + c.gridy = 1; + panel.add(searchSpecies, c); + c.gridx = 0; + c.gridy = 2; + panel.add(radius, c); + c.fill = GridBagConstraints.CENTER; + c.gridy = 3; + panel.add(ok, c); + + window.add(panel, BorderLayout.CENTER); + window.setVisible(true); + + } + + private void startRedrawingData(List allElements, double radius) throws FileNotFoundException + { + Model model = data.getModel(); + + LayoutModelPlugin plugin = (LayoutModelPlugin) model.getPlugin(LayoutConstants.shortLabel); + + ListOf listOfLayouts = plugin.getListOfLayouts(); + + Layout layout; + + for (int i=0; i < listOfLayouts.getChildCount(); i++) + { + layout = listOfLayouts.get(i); + new RearrangeCycles(layout,allElements,radius); + //new YGraphView(data.getSBMLDocument()); + + // object keeps same Name + SBMLWritingTask newSBML = + new SBMLWritingTask(new OpenedFile(new File("C:/Users/Lea.B/Documents/Studium/Bachelorarbeit/Libs&Modelle/PLT_teilweise_optimiert.xml"), data),null); + // oder: new OpenedFile(args[1],...); + //newSBML.execute(); + } + } + +} diff --git a/src/org/sbml/simulator/gui/graph/package-info.java b/src/org/sbml/simulator/gui/graph/package-info.java index 62f82ba..8d84e1f 100644 --- a/src/org/sbml/simulator/gui/graph/package-info.java +++ b/src/org/sbml/simulator/gui/graph/package-info.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -20,7 +18,6 @@ * Support for graphical simulation and simulation visualization. * * @author - * @version $Rev$ * @since */ package org.sbml.simulator.gui.graph; diff --git a/src/org/sbml/simulator/gui/package-info.java b/src/org/sbml/simulator/gui/package-info.java index d0b22ca..7490743 100755 --- a/src/org/sbml/simulator/gui/package-info.java +++ b/src/org/sbml/simulator/gui/package-info.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -22,7 +20,6 @@ * * @author Andreas Dräger * @author Alexander Dörr - * @version $Rev$ * @since 1.0 */ package org.sbml.simulator.gui; diff --git a/src/org/sbml/simulator/gui/plot/BoxAndWhiskerXYToolTipGenerator.java b/src/org/sbml/simulator/gui/plot/BoxAndWhiskerXYToolTipGenerator.java index 9d3d28c..085791c 100644 --- a/src/org/sbml/simulator/gui/plot/BoxAndWhiskerXYToolTipGenerator.java +++ b/src/org/sbml/simulator/gui/plot/BoxAndWhiskerXYToolTipGenerator.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -30,7 +28,6 @@ * quartils Q1 and Q3. * * @author Andreas Dräger - * @version $Rev$ * @since 1.0 */ public class BoxAndWhiskerXYToolTipGenerator extends diff --git a/src/org/sbml/simulator/gui/plot/BoxPlotDataset.java b/src/org/sbml/simulator/gui/plot/BoxPlotDataset.java index 5cef039..1fa2205 100644 --- a/src/org/sbml/simulator/gui/plot/BoxPlotDataset.java +++ b/src/org/sbml/simulator/gui/plot/BoxPlotDataset.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -35,7 +33,6 @@ * the data content in form of box plots. * * @author Andreas Dräger - * @version $Rev$ * @since 1.0 */ public class BoxPlotDataset extends AbstractXYDataset implements @@ -44,7 +41,6 @@ public class BoxPlotDataset extends AbstractXYDataset implements /** * * @author Andreas Dräger - * @version $Rev$ * @since 1.0 */ private class Item { @@ -98,7 +94,6 @@ public String toString() { /** * * @author Andreas Dräger - * @version $Rev$ * @since 1.0 */ private class Series extends TreeMap implements Comparable { diff --git a/src/org/sbml/simulator/gui/plot/MetaDataset.java b/src/org/sbml/simulator/gui/plot/MetaDataset.java index 4d80355..b41143d 100644 --- a/src/org/sbml/simulator/gui/plot/MetaDataset.java +++ b/src/org/sbml/simulator/gui/plot/MetaDataset.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -26,7 +24,6 @@ * is created. * * @author Andreas Dräger - * @version $Rev$ * @since 1.0 */ public interface MetaDataset extends XYDataset { diff --git a/src/org/sbml/simulator/gui/plot/Plot.java b/src/org/sbml/simulator/gui/plot/Plot.java index 23de9d0..224f41d 100644 --- a/src/org/sbml/simulator/gui/plot/Plot.java +++ b/src/org/sbml/simulator/gui/plot/Plot.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -55,7 +53,6 @@ * @author Max Zwießele * @author Philip Stevens * @date 2010-09-08 - * @version $Rev$ * @since 1.0 */ public class Plot extends ChartPanel implements PreferenceChangeListener { diff --git a/src/org/sbml/simulator/gui/plot/PlotOptions.java b/src/org/sbml/simulator/gui/plot/PlotOptions.java index 0741219..86879f9 100644 --- a/src/org/sbml/simulator/gui/plot/PlotOptions.java +++ b/src/org/sbml/simulator/gui/plot/PlotOptions.java @@ -1,6 +1,4 @@ /* - * $Id: PlotOptions.java 17:29:23 draeger$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -32,7 +30,6 @@ * A collection of options and user preferences for the plot of results. * * @author Andreas Dräger - * @version $Rev$ * @since 1.0 * @date 2011-03-23 */ diff --git a/src/org/sbml/simulator/gui/plot/SeriesInfo.java b/src/org/sbml/simulator/gui/plot/SeriesInfo.java index 4cf070b..7bb756d 100644 --- a/src/org/sbml/simulator/gui/plot/SeriesInfo.java +++ b/src/org/sbml/simulator/gui/plot/SeriesInfo.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -23,7 +21,6 @@ * Stores information about a series for a plot. * * @author Andreas Dräger - * @version $Rev$ * @since 1.0 */ public class SeriesInfo { diff --git a/src/org/sbml/simulator/gui/plot/XYBoxAndWhiskerRenderer.java b/src/org/sbml/simulator/gui/plot/XYBoxAndWhiskerRenderer.java index 1080d96..1f0cc8b 100644 --- a/src/org/sbml/simulator/gui/plot/XYBoxAndWhiskerRenderer.java +++ b/src/org/sbml/simulator/gui/plot/XYBoxAndWhiskerRenderer.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -48,7 +46,6 @@ * in this program. * * @author Andreas Dräger - * @version $Rev$ * @since 1.0 */ public class XYBoxAndWhiskerRenderer extends diff --git a/src/org/sbml/simulator/gui/plot/XYDatasetAdapter.java b/src/org/sbml/simulator/gui/plot/XYDatasetAdapter.java index f2b8744..6e71eed 100644 --- a/src/org/sbml/simulator/gui/plot/XYDatasetAdapter.java +++ b/src/org/sbml/simulator/gui/plot/XYDatasetAdapter.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -26,7 +24,6 @@ * @author Max Zwießele * @author Philip Stevens * @author Andreas Dräger - * @version $Rev$ * @since 1.0 */ public class XYDatasetAdapter extends AbstractXYDataset implements MetaDataset { diff --git a/src/org/sbml/simulator/gui/plot/package-info.java b/src/org/sbml/simulator/gui/plot/package-info.java index bc8e069..84ed421 100644 --- a/src/org/sbml/simulator/gui/plot/package-info.java +++ b/src/org/sbml/simulator/gui/plot/package-info.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -21,7 +19,6 @@ * plot. * * @author Andreas Dräger - * @version $Rev$ * @since 1.0 */ package org.sbml.simulator.gui.plot; diff --git a/src/org/sbml/simulator/gui/table/LegendTableCellRenderer.java b/src/org/sbml/simulator/gui/table/LegendTableCellRenderer.java index a90166d..72053d7 100644 --- a/src/org/sbml/simulator/gui/table/LegendTableCellRenderer.java +++ b/src/org/sbml/simulator/gui/table/LegendTableCellRenderer.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -44,7 +42,6 @@ * * @author Andreas Dräger * @date 2010-04-07 - * @version $Rev$ * @since 1.0 */ public class LegendTableCellRenderer extends JLabel implements TableCellRenderer { diff --git a/src/org/sbml/simulator/gui/table/LegendTableModel.java b/src/org/sbml/simulator/gui/table/LegendTableModel.java index 82bbb40..916ea2d 100644 --- a/src/org/sbml/simulator/gui/table/LegendTableModel.java +++ b/src/org/sbml/simulator/gui/table/LegendTableModel.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -50,7 +48,6 @@ * * @author Andreas Dräger * @date 2010-04-07 - * @version $Rev$ * @since 1.0 */ public class LegendTableModel extends AbstractTableModel implements PropertyChangeListener { diff --git a/src/org/sbml/simulator/gui/table/package-info.java b/src/org/sbml/simulator/gui/table/package-info.java index 69a0573..b8438aa 100644 --- a/src/org/sbml/simulator/gui/table/package-info.java +++ b/src/org/sbml/simulator/gui/table/package-info.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -21,7 +19,6 @@ * that are used in the SBMLsimulator. * * @author Andreas Dräger - * @version $Rev$ * @since 1.0 */ package org.sbml.simulator.gui.table; diff --git a/src/org/sbml/simulator/io/CSVDataImporter.java b/src/org/sbml/simulator/io/CSVDataImporter.java index 1e3ebc5..601f6dc 100644 --- a/src/org/sbml/simulator/io/CSVDataImporter.java +++ b/src/org/sbml/simulator/io/CSVDataImporter.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -46,7 +44,6 @@ * @author Andreas Dräger * @author Roland Keller * @date 2010-09-03 - * @version $Rev$ * @since 1.0 */ public class CSVDataImporter { diff --git a/src/org/sbml/simulator/io/CSVReadingTask.java b/src/org/sbml/simulator/io/CSVReadingTask.java index a5658d0..3427981 100644 --- a/src/org/sbml/simulator/io/CSVReadingTask.java +++ b/src/org/sbml/simulator/io/CSVReadingTask.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -40,7 +38,6 @@ * A background job for reading character-separated values from a file. * * @author Andreas Dräger - * @version $Rev$ * @since 1.0 */ public class CSVReadingTask extends SwingWorker, Void> { diff --git a/src/org/sbml/simulator/io/SimulatorIOOptions.java b/src/org/sbml/simulator/io/SimulatorIOOptions.java index 875232a..a6dbb6f 100644 --- a/src/org/sbml/simulator/io/SimulatorIOOptions.java +++ b/src/org/sbml/simulator/io/SimulatorIOOptions.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -33,7 +31,6 @@ * * @author Andreas Dräger * @date 2010-10-22 - * @version $Rev$ * @since 1.0 */ public interface SimulatorIOOptions extends KeyProvider { diff --git a/src/org/sbml/simulator/io/package-info.java b/src/org/sbml/simulator/io/package-info.java index 0b135c7..2b3c5e8 100755 --- a/src/org/sbml/simulator/io/package-info.java +++ b/src/org/sbml/simulator/io/package-info.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -23,7 +21,6 @@ * * @author Andreas Dräger * @author Roland Keller - * @version $Rev$ * @since 1.0 */ package org.sbml.simulator.io; diff --git a/src/org/sbml/simulator/math/SplineCalculation.java b/src/org/sbml/simulator/math/SplineCalculation.java index 7d1e1e5..ef2306a 100644 --- a/src/org/sbml/simulator/math/SplineCalculation.java +++ b/src/org/sbml/simulator/math/SplineCalculation.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -30,7 +28,6 @@ * data. * * @author Roland Keller - * @version $Rev$ * @since 1.2 */ public class SplineCalculation { diff --git a/src/org/sbml/simulator/math/package-info.java b/src/org/sbml/simulator/math/package-info.java index b4b658d..ec355b2 100755 --- a/src/org/sbml/simulator/math/package-info.java +++ b/src/org/sbml/simulator/math/package-info.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -21,7 +19,6 @@ * package. * * @author Roland Keller - * @version $Rev$ * @since 1.0 */ package org.sbml.simulator.math; diff --git a/src/org/sbml/simulator/package-info.java b/src/org/sbml/simulator/package-info.java index 9cfbed7..c0eb028 100755 --- a/src/org/sbml/simulator/package-info.java +++ b/src/org/sbml/simulator/package-info.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -23,7 +21,6 @@ * @author Roland Keller * @author Andreas Dr&quml;ger * @author Alexander Dörr - * @version $Rev$ * @since 1.0 */ package org.sbml.simulator; diff --git a/src/org/sbml/simulator/stability/gui/package-info.java b/src/org/sbml/simulator/stability/gui/package-info.java index db11528..e3c4b17 100755 --- a/src/org/sbml/simulator/stability/gui/package-info.java +++ b/src/org/sbml/simulator/stability/gui/package-info.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -19,7 +17,6 @@ /** * GUI elements that facilitate the stability analysis. * @author - * @version $Rev$ * @since */ package org.sbml.simulator.stability.gui; diff --git a/src/org/sbml/simulator/stability/math/IdentityMatrix.java b/src/org/sbml/simulator/stability/math/IdentityMatrix.java index c0d7c73..47a6caf 100755 --- a/src/org/sbml/simulator/stability/math/IdentityMatrix.java +++ b/src/org/sbml/simulator/stability/math/IdentityMatrix.java @@ -1,53 +1,50 @@ -/* - * $Id: IdentityMatrix.java 338 2012-02-17 07:03:11Z draeger $ - * $URL: https://rarepos.cs.uni-tuebingen.de/svn-path/SBMLsimulator/branches/Andreas/src/org/sbml/simulator/math/IdentityMatrix.java $ - * --------------------------------------------------------------------- - * This file is part of SBMLsimulator, a Java-based simulator for models - * of biochemical processes encoded in the modeling language SBML. - * - * Copyright (C) 2007-2016 by the University of Tuebingen, Germany. - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation. A copy of the license - * agreement is provided in the file named "LICENSE.txt" included with - * this software distribution and also available online as - * . - * --------------------------------------------------------------------- - */ -package org.sbml.simulator.stability.math; - -/** - * This Class represents a m x m identity matrix - * - * @author Alexander Dörr - * @version $Rev: 338 $ - * @since 1.0 - */ -public class IdentityMatrix extends StabilityMatrix { - - /** - * Generated serial version identifier. - */ - private static final long serialVersionUID = 5386269669997716715L; - - /** - * - * @param m - */ - public IdentityMatrix(int m) { - super(m, m, 0); - setOne(); - } - - /** - * Sets in each row/column a one at the position characteristic for an - * identity matrix - */ - private void setOne() { - for (int i = 0; i < this.getColumnDimension(); i++) { - this.set(i, i, 1); - } - } - -} +/* + * --------------------------------------------------------------------- + * This file is part of SBMLsimulator, a Java-based simulator for models + * of biochemical processes encoded in the modeling language SBML. + * + * Copyright (C) 2007-2016 by the University of Tuebingen, Germany. + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation. A copy of the license + * agreement is provided in the file named "LICENSE.txt" included with + * this software distribution and also available online as + * . + * --------------------------------------------------------------------- + */ +package org.sbml.simulator.stability.math; + +/** + * This Class represents a m x m identity matrix + * + * @author Alexander Dörr + * @since 1.0 + */ +public class IdentityMatrix extends StabilityMatrix { + + /** + * Generated serial version identifier. + */ + private static final long serialVersionUID = 5386269669997716715L; + + /** + * + * @param m + */ + public IdentityMatrix(int m) { + super(m, m, 0); + setOne(); + } + + /** + * Sets in each row/column a one at the position characteristic for an + * identity matrix + */ + private void setOne() { + for (int i = 0; i < this.getColumnDimension(); i++) { + this.set(i, i, 1); + } + } + +} diff --git a/src/org/sbml/simulator/stability/math/StabilityMatrix.java b/src/org/sbml/simulator/stability/math/StabilityMatrix.java index dbb9877..7b98d41 100755 --- a/src/org/sbml/simulator/stability/math/StabilityMatrix.java +++ b/src/org/sbml/simulator/stability/math/StabilityMatrix.java @@ -1,399 +1,396 @@ -/* - * $Id: StabilityMatrix.java 338 2012-02-17 07:03:11Z draeger $ - * $URL: https://rarepos.cs.uni-tuebingen.de/svn-path/SBMLsimulator/branches/Andreas/src/org/sbml/simulator/math/StabilityMatrix.java $ - * --------------------------------------------------------------------- - * This file is part of SBMLsimulator, a Java-based simulator for models - * of biochemical processes encoded in the modeling language SBML. - * - * Copyright (C) 2007-2016 by the University of Tuebingen, Germany. - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation. A copy of the license - * agreement is provided in the file named "LICENSE.txt" included with - * this software distribution and also available online as - * . - * --------------------------------------------------------------------- - */ -package org.sbml.simulator.stability.math; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -import eva2.tools.math.Jama.EigenvalueDecomposition; -import eva2.tools.math.Jama.Matrix; - -/** - * This Class extends the representation of a m x n Matrix with some additional - * functions - * - * @author Alexander Dörr - * @date 2009-12-18 - * @version $Rev: 338 $ - * @since 1.0 - */ -public class StabilityMatrix extends Matrix { - - /** - * Generated serial version identifier. - */ - private static final long serialVersionUID = -2678044872448572954L; - - /** - * Creates a m x n StabilityMatrix - * - * @param m - * number of rows - * @param n - * number of columns - */ - public StabilityMatrix(int m, int n) { - super(m, n); - } - - /** - * Creates a m x n StabilityMatrix with all entries set to c - * - * @param m - * number of rows - * @param n - * number of columns - * @param c - * scalar value - */ - public StabilityMatrix(int m, int n, int c) { - super(m, n, c); - } - - /** - * Creates a m x n StabilityMatrix with the entries given in array - * - * @param array - * entries - * @param m - * number of rows - * @param n - * number of columns - */ - public StabilityMatrix(double[][] array, int m, int n) { - super(array, m, n); - } - - /* (non-Javadoc) - * @see eva2.tools.math.Jama.Matrix#transpose() - */ - @Override - public StabilityMatrix transpose() { - int m=this.getRowDimension(); - int n= this.getColumnDimension(); - StabilityMatrix X = new StabilityMatrix(n,m); - double[][] C = X.getArray(); - for (int i = 0; i < m; i++) { - for (int j = 0; j < n; j++) { - C[j][i] = this.get(i, j); - } - } - return X; - } - - /** - * Returns the real part of the eigenvalues of this matrix - * - * @return array with the eigenvalues - */ - public double[] getEigenvalues() { - return (new EigenvalueDecomposition(this)).getRealEigenvalues(); - } - - /** - * Substitutes the values of row m with the given values - * - * @param m - * number of the row to be changed - * @param row - * the new values of row m - */ - public void setRow(int m, double[] row) { - for (int i = 0; i < this.getColumnDimension(); i++) { - this.set(m, i, row[i]); - } - } - - /** - * Copy a row from the matrix. - * - * @return row m in a one-dimensional array - */ - public double[] getRow(int m) { - double[] vals = new double[this.getColumnDimension()]; - for (int i = 0; i < this.getColumnDimension(); i++) { - vals[i] = this.get(m, i); - } - return vals; - } - - /** - * Substitutes the values of column n with the given values - * - * @param n - * number of the column to be changed - * @param row - * the new values of column n - */ - public void setColumn(int n, double[] column) { - for (int i = 0; i < this.getRowDimension(); i++) { - this.set(i, n, column[i]); - } - } - - /** - * Returns a copy of this matrix without row m and column n - * - * @param m - * row index - * @param n - * column index - * @return this matrix without row m and column n - */ - public StabilityMatrix getSubmatrix(int m, int n) { - - StabilityMatrix submatrix = new StabilityMatrix( - this.getRowDimension() - 1, this.getColumnDimension() - 1); - int subm = 0, subn = 0; - - for (int row = 0; row < this.getRowDimension(); row++) { - - if (row == m) { - continue; - } - for (int column = 0; column < this.getColumnDimension(); column++) { - - if (column == n) { - continue; - } - submatrix.set(subm, subn, this.get(row, column)); - subn++; - } - subn = 0; - subm++; - } - - return submatrix; - } - - /** - * Returns a copy of this matrix without rows and columns with an number - * greater than index - * - * @param index - * max row/column number - * @return this matrix without rows and columns greater than the given index - */ - public StabilityMatrix getSubmatrix(int index) { - StabilityMatrix submatrix = new StabilityMatrix(index + 1, index + 1); - - for (int r = 0; r <= index; r++) { - for (int c = 0; c <= index; c++) { - submatrix.set(r, c, this.get(r, c)); - } - } - - return submatrix; - } - - /** - * Returns a new StabilityMatrix without the given columns - * - * @param integers - * array with indices of the columns to be dropped, the indices - * have to be unique and in ascending order - * - * @return - */ - public StabilityMatrix dropColumns(Integer[] integers) { - StabilityMatrix submatrix = new StabilityMatrix(getRowDimension(), - getColumnDimension() - integers.length); - - for (int i = 0, n = 0; i < getColumnDimension(); i++) { - - if (Arrays.binarySearch(integers, i) < 0) { - submatrix.setColumn(n, getColumn(i)); - n++; - } - } - - return submatrix; - } - - /** - * Returns a new StabilityMatrix without the given rows - * - * @param integers - * array with indices of the rows to be dropped, the indices have - * to be unique and in ascending order - * - * @return - */ - public StabilityMatrix dropRows(Integer[] integers) { - StabilityMatrix submatrix = new StabilityMatrix(getRowDimension() - - integers.length, getColumnDimension()); - - for (int i = 0, n = 0; i < getRowDimension(); i++) { - - if (Arrays.binarySearch(integers, i) < 0) { - submatrix.setRow(n, getRow(i)); - n++; - } - } - - return submatrix; - } - - /** - * Changes the position of column i with column j and vice versa - * - * @param i - * @param j - */ - public void swapColumns(int i, int j) { - double[] columni = this.getColumn(i); - - this.setColumn(i, this.getColumn(j)); - this.setColumn(j, columni); - } - - /** - * Changes the position of column i with column j and vice versa - * - * @param i - * @param j - */ - public void swapRows(int i, int j) { - double[] rowi = this.getRow(i); - - this.setRow(i, this.getRow(j)); - this.setRow(j, rowi); - } - - /** - * Returns a HashSet with all column indeces at which the entry is equal to - * value - * - * @param m - * row index - * @return - */ - public Set getColIndecesEqual(int m, double value) { - HashSet set = new HashSet(); - for (int i = 0; i < getColumnDimension(); i++) { - if (get(m, i) == value) { - set.add(i); - } - } - - return set; - } - - /** - * Returns an array with all column indeces at which the entry is not equal - * to the given value - * - * @param m - * row index - * @return - */ - public Integer[] getColIndecesDiffer(int m, double value) { - ArrayList list = new ArrayList(); - - for (int i = 0; i < getColumnDimension(); i++) { - if (get(m, i) != value) { - list.add(i); - } - } - - Integer arr[] = new Integer[list.size()]; - - return list.toArray(arr); - } - - /** - * Checks if all entries in this matrix are zero - * - * @return - */ - public boolean allZero() { - for (int i = 0; i < this.getRowDimension(); i++) { - for (int j = 0; j < this.getColumnDimension(); j++) { - if (this.get(i, j) != 0d) { - return false; - } - } - } - return true; - } - - /** - * Sums up the given row with the row at position m and returns the result - * - * @param m - * @param tosum - * @return - */ - public double[] plusRow(int m, double[] tosum) { - double[] row = this.getRow(m); - - for (int i = 0; i < row.length; i++) { - row[i] += tosum[i]; - } - - return row; - } - - /** - * - * @param m - * @param scalar - * @return - */ - public double[] mulitplyRow(int m, double scalar) { - double[] row = this.getRow(m); - - for (int i = 0; i < row.length; i++) { - row[i] = row[i] * scalar; - } - - return row; - } - - /** - * Clone the StabilityMatrix object. - */ - @Override - public StabilityMatrix clone() { - return this.copy(); - } - - /** - * Returns a deep copy of a this StabilityMatrix - */ - @Override - public StabilityMatrix copy() { - StabilityMatrix copy = new StabilityMatrix(this.getRowDimension(), this - .getColumnDimension()); - double[][] array = copy.getArray(); - for (int i = 0; i < this.getRowDimension(); i++) { - for (int j = 0; j < this.getColumnDimension(); j++) { - array[i][j] = this.get(i, j); - } - } - return copy; - } - - public StabilityMatrix times(StabilityMatrix B) { - return new StabilityMatrix((((Matrix) (this)).times((Matrix) B)) - .getArray(), this.getRowDimension(), B.getColumnDimension()); - } - -} +/* + * --------------------------------------------------------------------- + * This file is part of SBMLsimulator, a Java-based simulator for models + * of biochemical processes encoded in the modeling language SBML. + * + * Copyright (C) 2007-2016 by the University of Tuebingen, Germany. + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation. A copy of the license + * agreement is provided in the file named "LICENSE.txt" included with + * this software distribution and also available online as + * . + * --------------------------------------------------------------------- + */ +package org.sbml.simulator.stability.math; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import eva2.tools.math.Jama.EigenvalueDecomposition; +import eva2.tools.math.Jama.Matrix; + +/** + * This Class extends the representation of a m x n Matrix with some additional + * functions + * + * @author Alexander Dörr + * @date 2009-12-18 + * @since 1.0 + */ +public class StabilityMatrix extends Matrix { + + /** + * Generated serial version identifier. + */ + private static final long serialVersionUID = -2678044872448572954L; + + /** + * Creates a m x n StabilityMatrix + * + * @param m + * number of rows + * @param n + * number of columns + */ + public StabilityMatrix(int m, int n) { + super(m, n); + } + + /** + * Creates a m x n StabilityMatrix with all entries set to c + * + * @param m + * number of rows + * @param n + * number of columns + * @param c + * scalar value + */ + public StabilityMatrix(int m, int n, int c) { + super(m, n, c); + } + + /** + * Creates a m x n StabilityMatrix with the entries given in array + * + * @param array + * entries + * @param m + * number of rows + * @param n + * number of columns + */ + public StabilityMatrix(double[][] array, int m, int n) { + super(array, m, n); + } + + /* (non-Javadoc) + * @see eva2.tools.math.Jama.Matrix#transpose() + */ + @Override + public StabilityMatrix transpose() { + int m=this.getRowDimension(); + int n= this.getColumnDimension(); + StabilityMatrix X = new StabilityMatrix(n,m); + double[][] C = X.getArray(); + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + C[j][i] = this.get(i, j); + } + } + return X; + } + + /** + * Returns the real part of the eigenvalues of this matrix + * + * @return array with the eigenvalues + */ + public double[] getEigenvalues() { + return (new EigenvalueDecomposition(this)).getRealEigenvalues(); + } + + /** + * Substitutes the values of row m with the given values + * + * @param m + * number of the row to be changed + * @param row + * the new values of row m + */ + public void setRow(int m, double[] row) { + for (int i = 0; i < this.getColumnDimension(); i++) { + this.set(m, i, row[i]); + } + } + + /** + * Copy a row from the matrix. + * + * @return row m in a one-dimensional array + */ + public double[] getRow(int m) { + double[] vals = new double[this.getColumnDimension()]; + for (int i = 0; i < this.getColumnDimension(); i++) { + vals[i] = this.get(m, i); + } + return vals; + } + + /** + * Substitutes the values of column n with the given values + * + * @param n + * number of the column to be changed + * @param row + * the new values of column n + */ + public void setColumn(int n, double[] column) { + for (int i = 0; i < this.getRowDimension(); i++) { + this.set(i, n, column[i]); + } + } + + /** + * Returns a copy of this matrix without row m and column n + * + * @param m + * row index + * @param n + * column index + * @return this matrix without row m and column n + */ + public StabilityMatrix getSubmatrix(int m, int n) { + + StabilityMatrix submatrix = new StabilityMatrix( + this.getRowDimension() - 1, this.getColumnDimension() - 1); + int subm = 0, subn = 0; + + for (int row = 0; row < this.getRowDimension(); row++) { + + if (row == m) { + continue; + } + for (int column = 0; column < this.getColumnDimension(); column++) { + + if (column == n) { + continue; + } + submatrix.set(subm, subn, this.get(row, column)); + subn++; + } + subn = 0; + subm++; + } + + return submatrix; + } + + /** + * Returns a copy of this matrix without rows and columns with an number + * greater than index + * + * @param index + * max row/column number + * @return this matrix without rows and columns greater than the given index + */ + public StabilityMatrix getSubmatrix(int index) { + StabilityMatrix submatrix = new StabilityMatrix(index + 1, index + 1); + + for (int r = 0; r <= index; r++) { + for (int c = 0; c <= index; c++) { + submatrix.set(r, c, this.get(r, c)); + } + } + + return submatrix; + } + + /** + * Returns a new StabilityMatrix without the given columns + * + * @param integers + * array with indices of the columns to be dropped, the indices + * have to be unique and in ascending order + * + * @return + */ + public StabilityMatrix dropColumns(Integer[] integers) { + StabilityMatrix submatrix = new StabilityMatrix(getRowDimension(), + getColumnDimension() - integers.length); + + for (int i = 0, n = 0; i < getColumnDimension(); i++) { + + if (Arrays.binarySearch(integers, i) < 0) { + submatrix.setColumn(n, getColumn(i)); + n++; + } + } + + return submatrix; + } + + /** + * Returns a new StabilityMatrix without the given rows + * + * @param integers + * array with indices of the rows to be dropped, the indices have + * to be unique and in ascending order + * + * @return + */ + public StabilityMatrix dropRows(Integer[] integers) { + StabilityMatrix submatrix = new StabilityMatrix(getRowDimension() + - integers.length, getColumnDimension()); + + for (int i = 0, n = 0; i < getRowDimension(); i++) { + + if (Arrays.binarySearch(integers, i) < 0) { + submatrix.setRow(n, getRow(i)); + n++; + } + } + + return submatrix; + } + + /** + * Changes the position of column i with column j and vice versa + * + * @param i + * @param j + */ + public void swapColumns(int i, int j) { + double[] columni = this.getColumn(i); + + this.setColumn(i, this.getColumn(j)); + this.setColumn(j, columni); + } + + /** + * Changes the position of column i with column j and vice versa + * + * @param i + * @param j + */ + public void swapRows(int i, int j) { + double[] rowi = this.getRow(i); + + this.setRow(i, this.getRow(j)); + this.setRow(j, rowi); + } + + /** + * Returns a HashSet with all column indeces at which the entry is equal to + * value + * + * @param m + * row index + * @return + */ + public Set getColIndecesEqual(int m, double value) { + HashSet set = new HashSet(); + for (int i = 0; i < getColumnDimension(); i++) { + if (get(m, i) == value) { + set.add(i); + } + } + + return set; + } + + /** + * Returns an array with all column indeces at which the entry is not equal + * to the given value + * + * @param m + * row index + * @return + */ + public Integer[] getColIndecesDiffer(int m, double value) { + ArrayList list = new ArrayList(); + + for (int i = 0; i < getColumnDimension(); i++) { + if (get(m, i) != value) { + list.add(i); + } + } + + Integer arr[] = new Integer[list.size()]; + + return list.toArray(arr); + } + + /** + * Checks if all entries in this matrix are zero + * + * @return + */ + public boolean allZero() { + for (int i = 0; i < this.getRowDimension(); i++) { + for (int j = 0; j < this.getColumnDimension(); j++) { + if (this.get(i, j) != 0d) { + return false; + } + } + } + return true; + } + + /** + * Sums up the given row with the row at position m and returns the result + * + * @param m + * @param tosum + * @return + */ + public double[] plusRow(int m, double[] tosum) { + double[] row = this.getRow(m); + + for (int i = 0; i < row.length; i++) { + row[i] += tosum[i]; + } + + return row; + } + + /** + * + * @param m + * @param scalar + * @return + */ + public double[] mulitplyRow(int m, double scalar) { + double[] row = this.getRow(m); + + for (int i = 0; i < row.length; i++) { + row[i] = row[i] * scalar; + } + + return row; + } + + /** + * Clone the StabilityMatrix object. + */ + @Override + public StabilityMatrix clone() { + return this.copy(); + } + + /** + * Returns a deep copy of a this StabilityMatrix + */ + @Override + public StabilityMatrix copy() { + StabilityMatrix copy = new StabilityMatrix(this.getRowDimension(), this + .getColumnDimension()); + double[][] array = copy.getArray(); + for (int i = 0; i < this.getRowDimension(); i++) { + for (int j = 0; j < this.getColumnDimension(); j++) { + array[i][j] = this.get(i, j); + } + } + return copy; + } + + public StabilityMatrix times(StabilityMatrix B) { + return new StabilityMatrix((((Matrix) (this)).times((Matrix) B)) + .getArray(), this.getRowDimension(), B.getColumnDimension()); + } + +} diff --git a/src/org/sbml/simulator/stability/math/StoichiometricMatrix.java b/src/org/sbml/simulator/stability/math/StoichiometricMatrix.java index ec45ef6..0b097a7 100755 --- a/src/org/sbml/simulator/stability/math/StoichiometricMatrix.java +++ b/src/org/sbml/simulator/stability/math/StoichiometricMatrix.java @@ -1,450 +1,447 @@ -/* - * $Id: StoichiometricMatrix.java 338 2012-02-17 07:03:11Z draeger $ - * $URL: https://rarepos.cs.uni-tuebingen.de/svn-path/SBMLsimulator/branches/Andreas/src/org/sbml/simulator/math/StoichiometricMatrix.java $ - * --------------------------------------------------------------------- - * This file is part of SBMLsimulator, a Java-based simulator for models - * of biochemical processes encoded in the modeling language SBML. - * - * Copyright (C) 2007-2016 by the University of Tuebingen, Germany. - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation. A copy of the license - * agreement is provided in the file named "LICENSE.txt" included with - * this software distribution and also available online as - * . - * --------------------------------------------------------------------- - */ -package org.sbml.simulator.stability.math; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.logging.Logger; - -import eva2.tools.math.Jama.LUDecomposition; -import eva2.tools.math.Jama.Matrix; - -/** - * This Class represents a m x n stoichiometric matrix - * - * @author Alexander Dörr - * @date 2010-12-23 - * @version $Rev: 338 $ - * @since 1.0 - */ -public class StoichiometricMatrix extends StabilityMatrix { - - /** - * Generated serial version identifier. - */ - private static final long serialVersionUID = 8418337736328552077L; - - /** - * A {@link Logger} for this class. - */ - private static final Logger logger = Logger.getLogger(StoichiometricMatrix.class.getName()); - - /** - * A m x r matrix holding the link matrix for the reduced stoichiometric - * matrix of this matrix - */ - private StabilityMatrix linkMatrix = null; - - /** - * A r x n matrix holding the reduced form of this matrix - */ - private StabilityMatrix reducedMatrix = null; - - /** - * A (m - r) x m matrix holding the conservation relations/moieties of this - * matrix - */ - private StabilityMatrix conservationRelations = null; - - /** - * A n x (n - r) matrix holding the feasible steady state fluxes of this - * matrix - */ - private StabilityMatrix steadyStateFluxes = null; - - /** - * A HashMap containing inversion of the permutations of the metabolites due - * to the LU decomposition and the algorithm - */ - private Map permutations = null; - - /** - * A HashSet containing all indices of the removed rows when computing the - * reduced stoichiometric matrix - */ - private Set linearDependent; - - /** - * A linked list containing the indices of the removed rows in the same - * order as they appear in the rows of the conservation relations - */ - private List removedRows; - - /** - * The rank of this matrix - */ - private int rank; - - /** - * Creates a m x n stoichiometric matrix N - * - * @param m - * number of rows - * @param n - * number of columns - */ - public StoichiometricMatrix(int m, int n) { - super(m, n); - } - - /** - * Creates a m x n stoichiometric matrix N with all entries set to c - * - * @param m - * number of rows - * @param n - * number of columns - * @param c - * scalar value - */ - public StoichiometricMatrix(int m, int n, int c) { - super(m, n, c); - } - - /** - * Creates a m x n stoichiometric matrix N with the entries given in array - * - * @param array - * entries - * @param m - * number of rows - * @param n - * number of columns - */ - public StoichiometricMatrix(double[][] array, int m, int n) { - super(array, m, n); - } - - /** - * Returns the link matrix of this matrix - * - * @return - */ - public StabilityMatrix getLinkMatrix() { - if (linkMatrix == null) { - reduceModel(); - } - - return linkMatrix; - } - - /** - * Returns the reduced form of this matrix - * - * @return - */ - public StabilityMatrix getReducedMatrix() { - if (reducedMatrix == null) { - reduceModel(); - } - - return reducedMatrix; - } - - /** - * Returns the conservation relations of this matrix - * - * @return - */ - public StabilityMatrix getConservationRelations() { - if (conservationRelations == null) { - reduceModel(); - } - - return conservationRelations; - } - - /** - * This method calculates the reduced stoichiometric matrix with its - * metabolic link matrix and its conservation relations as side products. - * Refering to Palsson, the conservation relations are also known as the - * left null space of N. This is achieved by performing an QR decomposition - * as described in "Conservation analysis of large biochemical networks" by - * Ravishankar Rao Vallabhajosyula and Herbert Sauro. The permutation matrix - * is calculated through LU decomposition. - * - */ - private void reduceModel() { - StabilityMatrix stoich; - permutations = new HashMap(); - removedRows = new LinkedList(); - - if (!((this.getRowDimension() > 0) && (this.getColumnDimension() > 0))) { - logger.fine("Wrong dimensions"); - } - - // check if matrix has to be augmented before performing the LU - // decomposition - if (this.getRowDimension() >= this.getColumnDimension()) { - stoich = this; - } else { - stoich = augmentN(); - } - - LUDecomposition lu = new LUDecomposition(stoich); - - int m = stoich.getRowDimension(); - - StabilityMatrix P = new StabilityMatrix(m, m, 0); - - // build the permutation matrix out of the pivot elements from the LU - // decomposition - int[] pivot = lu.getPivot(); - for (int i = 0; i < pivot.length; i++) { - P.set(pivot[i], i, 1); - } - // System.out.println("P"); - // System.out.println(P); - - QRDecomposition qr = new QRDecomposition(stoich.transpose().times(P)); - - // Matrix Q = qr.getQ(); - Matrix R = roundValues(qr.getR()); - - // System.out.println("Q"); - // System.out.println(Q); - // - // System.out.println("R"); - // System.out.println(R); - - StabilityMatrix Rt = new StabilityMatrix(R.copy().getArray(), - R.getRowDimension(), R.getColumnDimension()); - - // dividing each row its diagonal element - for (int i = 0; i < Rt.getRowDimension(); i++) { - double unity = Rt.get(i, i); - if (unity != 0d) { - for (int j = 0; j < Rt.getColumnDimension(); j++) { - Rt.set(i, j, (Math.round(Rt.get(i, j) / unity * 1E4d)) / 1E4d); - } - } - } - rank = Rt.getRowDimension(); - - // Gauss-Jordan reduction to eliminate non-zero values above the - // diagonal - for (int i = Rt.getRowDimension() - 1; i >= 0; i--) { - if (Rt.get(i, i) == 0d) { - rank--; - - } else { - - double[] row = Rt.getRow(i); - - for (int j = i - 1; j >= 0; j--) { - double value = Rt.get(j, i); - - for (int k = row.length - 1; k >= j; k--) { - Rt.set(j, k, Rt.get(j, k) - (value * row[k])); - } - - } - - } - - } - // System.out.println("rank: " + rank); - // System.out.println("Rt"); - // System.out.println(Rt); - - StabilityMatrix L = new StabilityMatrix(this.getRowDimension(), rank); - StabilityMatrix Lo = new StabilityMatrix(this.getRowDimension() - rank, - this.getRowDimension()); - - buildReducedN(P); - - // build the conservation and the link matrix - int l = 0, n, loindex; - double value; - double[] column; - for (int i = 0; i < L.getRowDimension(); i++) { - if (i < rank) { - L.set(i, i, 1); - } else { - column = Rt.getColumn(i); - for (int j = 0; j < L.getColumnDimension(); j++) { - if (column[j] != 0d) { - value = Math.round(column[j] * 1E3d) / 1E3d; - n = permutations.get(j); - Lo.set(l, n, -value); - } - } - - m = permutations.get(i); - Lo.set(l, m, 1); - - l++; - loindex = 0; - - for (int j = 0; j < Lo.getColumnDimension(); j++) { - if (!linearDependent.contains(j)) { - if (Lo.get(i - rank, j) != 0) { - L.set(i, loindex, -Lo.get(i - rank, j)); - } - loindex++; - } - } - } - } - - this.linkMatrix = L; - this.conservationRelations = Lo; - - } - - /** - * When the number of reactions is greater than the number of metabolites, - * the LU decomposition does not work. This is circumvented by adding - * additional zero rows at the end of the matrix as described in - * "Conservation analysis of large biochemical networks" by Ravishankar Rao - * Vallabhajosyula and Herbert Sauro. - * - * @return - */ - private StabilityMatrix augmentN() { - StabilityMatrix augmentedN = new StabilityMatrix( - this.getColumnDimension(), this.getColumnDimension(), 0); - - for (int i = 0; i < this.getRowDimension(); i++) { - augmentedN.setRow(i, this.getRow(i)); - } - - return augmentedN; - } - - /** - * This method uses the permutation matrix to build the reduced - * stoichiometric matrix - * - * @param permutationMatrix - */ - private void buildReducedN(StabilityMatrix permutationMatrix) { - linearDependent = new HashSet(); - reducedMatrix = new StabilityMatrix(rank, this.getColumnDimension()); - - // save permutations of the rows due to the LU - // decomposition and add dependent rows to the hash, strictly speaking - // rows that are moved to a new position with a higher index than the - // rank - for (int i = 0; i < this.getRowDimension(); i++) { - for (int j = 0; j < this.getRowDimension(); j++) { - - if (permutationMatrix.get(i, j) == 1.0) { - if (j >= rank) { - linearDependent.add(i); - removedRows.add(i); - } - permutations.put(j, i); - continue; - - } - } - } - - int l = 0; - - // exclude linear dependent rows when building the reduced - // stoichiometric matrix - for (int i = 0; i < this.getRowDimension(); i++) { - - if (!linearDependent.contains(i)) { - reducedMatrix.setRow(l, this.getRow(i)); - l++; - } - } - } - - /** - * This method calculates the feasible steady state fluxes of the model with - * this stoichiometric matrix, referring to Palsson also known as the null - * space of N. This is achieved by performing an SVD decomposition as - * described in "Systems Biology: Properties of Reconstructed Networks" by - * Bernhard O. Palsson. - */ - private void calculateSteadyStateFluxes() { - SingularValueDecomposition svd = new SingularValueDecomposition(this); - int rank = svd.rank(); - - steadyStateFluxes = new StabilityMatrix(this.getColumnDimension(), - this.getColumnDimension() - rank); - Matrix V = svd.getV(); - - for (int i = 0; i < this.getColumnDimension() - rank; i++) { - for (int j = 0; j < this.getColumnDimension(); j++) { - steadyStateFluxes.set(j, i, V.get(j, rank + i)); - } - } - - } - - /** - * This method changes values that are as good as zero to zero due to - * numerical inaccuracy. - * - * @param matrix - * @return - */ - public static Matrix roundValues(Matrix matrix) { - for (int m = 0; m < matrix.getRowDimension(); m++) { - for (int n = 0; n < matrix.getColumnDimension(); n++) { - - if (matrix.get(m, n) < 1E-9 && matrix.get(m, n) > 0) { - matrix.set(m, n, 0); - } else if (matrix.get(m, n) > -1E-9 && matrix.get(m, n) < 0) { - matrix.set(m, n, 0); - } - - } - } - return matrix; - } - - /** - * Returns the feasible steady state fluxes of this matrix - * - * @return - */ - public StabilityMatrix getSteadyStateFluxes() { - if (steadyStateFluxes == null) { - calculateSteadyStateFluxes(); - } - return steadyStateFluxes; - } - - /** - * This method returns a linked list of integer values corresponding to the - * rows of this matrix, that are removed when building the reduced - * stoichiometric matrix. Please note that the indices correspond to the - * array notation, where e.g. 0 stands for the first row in the matrix. - * Their sequence corresponds the order of the appearance in the - * conservation relations. - * - * @return - */ - public List getLinearDependent() { - if (removedRows == null) { - reduceModel(); - } - return removedRows; - } - -} +/* + * --------------------------------------------------------------------- + * This file is part of SBMLsimulator, a Java-based simulator for models + * of biochemical processes encoded in the modeling language SBML. + * + * Copyright (C) 2007-2016 by the University of Tuebingen, Germany. + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation. A copy of the license + * agreement is provided in the file named "LICENSE.txt" included with + * this software distribution and also available online as + * . + * --------------------------------------------------------------------- + */ +package org.sbml.simulator.stability.math; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.logging.Logger; + +import eva2.tools.math.Jama.LUDecomposition; +import eva2.tools.math.Jama.Matrix; + +/** + * This Class represents a m x n stoichiometric matrix + * + * @author Alexander Dörr + * @date 2010-12-23 + * @since 1.0 + */ +public class StoichiometricMatrix extends StabilityMatrix { + + /** + * Generated serial version identifier. + */ + private static final long serialVersionUID = 8418337736328552077L; + + /** + * A {@link Logger} for this class. + */ + private static final Logger logger = Logger.getLogger(StoichiometricMatrix.class.getName()); + + /** + * A m x r matrix holding the link matrix for the reduced stoichiometric + * matrix of this matrix + */ + private StabilityMatrix linkMatrix = null; + + /** + * A r x n matrix holding the reduced form of this matrix + */ + private StabilityMatrix reducedMatrix = null; + + /** + * A (m - r) x m matrix holding the conservation relations/moieties of this + * matrix + */ + private StabilityMatrix conservationRelations = null; + + /** + * A n x (n - r) matrix holding the feasible steady state fluxes of this + * matrix + */ + private StabilityMatrix steadyStateFluxes = null; + + /** + * A HashMap containing inversion of the permutations of the metabolites due + * to the LU decomposition and the algorithm + */ + private Map permutations = null; + + /** + * A HashSet containing all indices of the removed rows when computing the + * reduced stoichiometric matrix + */ + private Set linearDependent; + + /** + * A linked list containing the indices of the removed rows in the same + * order as they appear in the rows of the conservation relations + */ + private List removedRows; + + /** + * The rank of this matrix + */ + private int rank; + + /** + * Creates a m x n stoichiometric matrix N + * + * @param m + * number of rows + * @param n + * number of columns + */ + public StoichiometricMatrix(int m, int n) { + super(m, n); + } + + /** + * Creates a m x n stoichiometric matrix N with all entries set to c + * + * @param m + * number of rows + * @param n + * number of columns + * @param c + * scalar value + */ + public StoichiometricMatrix(int m, int n, int c) { + super(m, n, c); + } + + /** + * Creates a m x n stoichiometric matrix N with the entries given in array + * + * @param array + * entries + * @param m + * number of rows + * @param n + * number of columns + */ + public StoichiometricMatrix(double[][] array, int m, int n) { + super(array, m, n); + } + + /** + * Returns the link matrix of this matrix + * + * @return + */ + public StabilityMatrix getLinkMatrix() { + if (linkMatrix == null) { + reduceModel(); + } + + return linkMatrix; + } + + /** + * Returns the reduced form of this matrix + * + * @return + */ + public StabilityMatrix getReducedMatrix() { + if (reducedMatrix == null) { + reduceModel(); + } + + return reducedMatrix; + } + + /** + * Returns the conservation relations of this matrix + * + * @return + */ + public StabilityMatrix getConservationRelations() { + if (conservationRelations == null) { + reduceModel(); + } + + return conservationRelations; + } + + /** + * This method calculates the reduced stoichiometric matrix with its + * metabolic link matrix and its conservation relations as side products. + * Refering to Palsson, the conservation relations are also known as the + * left null space of N. This is achieved by performing an QR decomposition + * as described in "Conservation analysis of large biochemical networks" by + * Ravishankar Rao Vallabhajosyula and Herbert Sauro. The permutation matrix + * is calculated through LU decomposition. + * + */ + private void reduceModel() { + StabilityMatrix stoich; + permutations = new HashMap(); + removedRows = new LinkedList(); + + if (!((this.getRowDimension() > 0) && (this.getColumnDimension() > 0))) { + logger.fine("Wrong dimensions"); + } + + // check if matrix has to be augmented before performing the LU + // decomposition + if (this.getRowDimension() >= this.getColumnDimension()) { + stoich = this; + } else { + stoich = augmentN(); + } + + LUDecomposition lu = new LUDecomposition(stoich); + + int m = stoich.getRowDimension(); + + StabilityMatrix P = new StabilityMatrix(m, m, 0); + + // build the permutation matrix out of the pivot elements from the LU + // decomposition + int[] pivot = lu.getPivot(); + for (int i = 0; i < pivot.length; i++) { + P.set(pivot[i], i, 1); + } + // System.out.println("P"); + // System.out.println(P); + + QRDecomposition qr = new QRDecomposition(stoich.transpose().times(P)); + + // Matrix Q = qr.getQ(); + Matrix R = roundValues(qr.getR()); + + // System.out.println("Q"); + // System.out.println(Q); + // + // System.out.println("R"); + // System.out.println(R); + + StabilityMatrix Rt = new StabilityMatrix(R.copy().getArray(), + R.getRowDimension(), R.getColumnDimension()); + + // dividing each row its diagonal element + for (int i = 0; i < Rt.getRowDimension(); i++) { + double unity = Rt.get(i, i); + if (unity != 0d) { + for (int j = 0; j < Rt.getColumnDimension(); j++) { + Rt.set(i, j, (Math.round(Rt.get(i, j) / unity * 1E4d)) / 1E4d); + } + } + } + rank = Rt.getRowDimension(); + + // Gauss-Jordan reduction to eliminate non-zero values above the + // diagonal + for (int i = Rt.getRowDimension() - 1; i >= 0; i--) { + if (Rt.get(i, i) == 0d) { + rank--; + + } else { + + double[] row = Rt.getRow(i); + + for (int j = i - 1; j >= 0; j--) { + double value = Rt.get(j, i); + + for (int k = row.length - 1; k >= j; k--) { + Rt.set(j, k, Rt.get(j, k) - (value * row[k])); + } + + } + + } + + } + // System.out.println("rank: " + rank); + // System.out.println("Rt"); + // System.out.println(Rt); + + StabilityMatrix L = new StabilityMatrix(this.getRowDimension(), rank); + StabilityMatrix Lo = new StabilityMatrix(this.getRowDimension() - rank, + this.getRowDimension()); + + buildReducedN(P); + + // build the conservation and the link matrix + int l = 0, n, loindex; + double value; + double[] column; + for (int i = 0; i < L.getRowDimension(); i++) { + if (i < rank) { + L.set(i, i, 1); + } else { + column = Rt.getColumn(i); + for (int j = 0; j < L.getColumnDimension(); j++) { + if (column[j] != 0d) { + value = Math.round(column[j] * 1E3d) / 1E3d; + n = permutations.get(j); + Lo.set(l, n, -value); + } + } + + m = permutations.get(i); + Lo.set(l, m, 1); + + l++; + loindex = 0; + + for (int j = 0; j < Lo.getColumnDimension(); j++) { + if (!linearDependent.contains(j)) { + if (Lo.get(i - rank, j) != 0) { + L.set(i, loindex, -Lo.get(i - rank, j)); + } + loindex++; + } + } + } + } + + this.linkMatrix = L; + this.conservationRelations = Lo; + + } + + /** + * When the number of reactions is greater than the number of metabolites, + * the LU decomposition does not work. This is circumvented by adding + * additional zero rows at the end of the matrix as described in + * "Conservation analysis of large biochemical networks" by Ravishankar Rao + * Vallabhajosyula and Herbert Sauro. + * + * @return + */ + private StabilityMatrix augmentN() { + StabilityMatrix augmentedN = new StabilityMatrix( + this.getColumnDimension(), this.getColumnDimension(), 0); + + for (int i = 0; i < this.getRowDimension(); i++) { + augmentedN.setRow(i, this.getRow(i)); + } + + return augmentedN; + } + + /** + * This method uses the permutation matrix to build the reduced + * stoichiometric matrix + * + * @param permutationMatrix + */ + private void buildReducedN(StabilityMatrix permutationMatrix) { + linearDependent = new HashSet(); + reducedMatrix = new StabilityMatrix(rank, this.getColumnDimension()); + + // save permutations of the rows due to the LU + // decomposition and add dependent rows to the hash, strictly speaking + // rows that are moved to a new position with a higher index than the + // rank + for (int i = 0; i < this.getRowDimension(); i++) { + for (int j = 0; j < this.getRowDimension(); j++) { + + if (permutationMatrix.get(i, j) == 1.0) { + if (j >= rank) { + linearDependent.add(i); + removedRows.add(i); + } + permutations.put(j, i); + continue; + + } + } + } + + int l = 0; + + // exclude linear dependent rows when building the reduced + // stoichiometric matrix + for (int i = 0; i < this.getRowDimension(); i++) { + + if (!linearDependent.contains(i)) { + reducedMatrix.setRow(l, this.getRow(i)); + l++; + } + } + } + + /** + * This method calculates the feasible steady state fluxes of the model with + * this stoichiometric matrix, referring to Palsson also known as the null + * space of N. This is achieved by performing an SVD decomposition as + * described in "Systems Biology: Properties of Reconstructed Networks" by + * Bernhard O. Palsson. + */ + private void calculateSteadyStateFluxes() { + SingularValueDecomposition svd = new SingularValueDecomposition(this); + int rank = svd.rank(); + + steadyStateFluxes = new StabilityMatrix(this.getColumnDimension(), + this.getColumnDimension() - rank); + Matrix V = svd.getV(); + + for (int i = 0; i < this.getColumnDimension() - rank; i++) { + for (int j = 0; j < this.getColumnDimension(); j++) { + steadyStateFluxes.set(j, i, V.get(j, rank + i)); + } + } + + } + + /** + * This method changes values that are as good as zero to zero due to + * numerical inaccuracy. + * + * @param matrix + * @return + */ + public static Matrix roundValues(Matrix matrix) { + for (int m = 0; m < matrix.getRowDimension(); m++) { + for (int n = 0; n < matrix.getColumnDimension(); n++) { + + if (matrix.get(m, n) < 1E-9 && matrix.get(m, n) > 0) { + matrix.set(m, n, 0); + } else if (matrix.get(m, n) > -1E-9 && matrix.get(m, n) < 0) { + matrix.set(m, n, 0); + } + + } + } + return matrix; + } + + /** + * Returns the feasible steady state fluxes of this matrix + * + * @return + */ + public StabilityMatrix getSteadyStateFluxes() { + if (steadyStateFluxes == null) { + calculateSteadyStateFluxes(); + } + return steadyStateFluxes; + } + + /** + * This method returns a linked list of integer values corresponding to the + * rows of this matrix, that are removed when building the reduced + * stoichiometric matrix. Please note that the indices correspond to the + * array notation, where e.g. 0 stands for the first row in the matrix. + * Their sequence corresponds the order of the appearance in the + * conservation relations. + * + * @return + */ + public List getLinearDependent() { + if (removedRows == null) { + reduceModel(); + } + return removedRows; + } + +} diff --git a/src/org/sbml/simulator/stability/math/package-info.java b/src/org/sbml/simulator/stability/math/package-info.java index 91a6675..baf833c 100755 --- a/src/org/sbml/simulator/stability/math/package-info.java +++ b/src/org/sbml/simulator/stability/math/package-info.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -18,7 +16,6 @@ /** * @author - * @version $Rev$ * @since */ package org.sbml.simulator.stability.math; diff --git a/test/org/sbml/simulator/gui/CSVDataImporterTest.java b/test/org/sbml/simulator/gui/CSVDataImporterTest.java index 05c61d6..0a5b33c 100644 --- a/test/org/sbml/simulator/gui/CSVDataImporterTest.java +++ b/test/org/sbml/simulator/gui/CSVDataImporterTest.java @@ -1,6 +1,4 @@ /* - * $Id: CSVDataImporterTest.java 18:15:31 draeger$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -38,7 +36,6 @@ * character-separated files. * * @author Andreas Dräger - * @version $Rev$ * @since 1.0 */ public class CSVDataImporterTest { diff --git a/test/org/sbml/simulator/gui/ChoiceFormatTest.java b/test/org/sbml/simulator/gui/ChoiceFormatTest.java index 37fe232..237295a 100644 --- a/test/org/sbml/simulator/gui/ChoiceFormatTest.java +++ b/test/org/sbml/simulator/gui/ChoiceFormatTest.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -27,7 +25,6 @@ * A test class to try some functions of Java's {@link ChoiceFormat}. * * @author Andreas Dräger - * @version $Rev$ * @since 1.0 */ public class ChoiceFormatTest { diff --git a/test/org/sbml/simulator/gui/ToolPanel.java b/test/org/sbml/simulator/gui/ToolPanel.java index 9cdb17c..bf00e7e 100644 --- a/test/org/sbml/simulator/gui/ToolPanel.java +++ b/test/org/sbml/simulator/gui/ToolPanel.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -31,7 +29,6 @@ * provides settings for user preferences about simulation options. * * @author Andreas Dräger - * @version $Rev$ * @date 07.12.2011 */ public class ToolPanel extends PreferencesPanelForKeyProvider { diff --git a/test/org/sbml/simulator/gui/XYDataSetCollection.java b/test/org/sbml/simulator/gui/XYDataSetCollection.java index a11baaa..e192ec9 100644 --- a/test/org/sbml/simulator/gui/XYDataSetCollection.java +++ b/test/org/sbml/simulator/gui/XYDataSetCollection.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -29,7 +27,6 @@ * A test class for plot data collections. * * @author Andreas Dräger - * @version $Rev$ * @since 1.0 */ public class XYDataSetCollection extends AbstractIntervalXYDataset { diff --git a/test/org/sbml/simulator/gui/graph/BugTestJSlider.java b/test/org/sbml/simulator/gui/graph/BugTestJSlider.java index 01c9ba7..3566437 100644 --- a/test/org/sbml/simulator/gui/graph/BugTestJSlider.java +++ b/test/org/sbml/simulator/gui/graph/BugTestJSlider.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -22,7 +20,6 @@ /** * @author Fabian Schwarzkopf - * @version $Rev$ */ public class BugTestJSlider{ @@ -39,6 +36,5 @@ public static void main(String[] args) { window.setSize(200, 100); window.setVisible(true); } - } diff --git a/test/org/sbml/simulator/gui/graph/Controller.java b/test/org/sbml/simulator/gui/graph/Controller.java index 5621c81..11d4415 100644 --- a/test/org/sbml/simulator/gui/graph/Controller.java +++ b/test/org/sbml/simulator/gui/graph/Controller.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -30,7 +28,6 @@ * when core existing. * * @author Fabian Schwarzkopf - * @version $Rev$ */ public class Controller implements ChangeListener, ActionListener{ diff --git a/test/org/sbml/simulator/gui/graph/JSliderTest.java b/test/org/sbml/simulator/gui/graph/JSliderTest.java index a779968..80f3e8b 100644 --- a/test/org/sbml/simulator/gui/graph/JSliderTest.java +++ b/test/org/sbml/simulator/gui/graph/JSliderTest.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -29,7 +27,6 @@ /** * @author Fabian Schwarzkopf - * @version $Rev$ */ public class JSliderTest extends JFrame implements IDynamicGraph{ private static final long serialVersionUID = -7669702948757945505L; diff --git a/test/org/sbml/simulator/gui/graph/RunTest.java b/test/org/sbml/simulator/gui/graph/RunTest.java index b0d83b5..bd364fb 100644 --- a/test/org/sbml/simulator/gui/graph/RunTest.java +++ b/test/org/sbml/simulator/gui/graph/RunTest.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -19,7 +17,6 @@ /** * @author Fabian Schwarzkopf - * @version $Rev$ */ public class RunTest { diff --git a/test/org/sbml/simulator/math/Plotter.java b/test/org/sbml/simulator/math/Plotter.java index 6d8332d..0c382ae 100644 --- a/test/org/sbml/simulator/math/Plotter.java +++ b/test/org/sbml/simulator/math/Plotter.java @@ -1,6 +1,4 @@ /* - * $Id: Plotter.java 14:26:05 keller$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -27,7 +25,7 @@ import org.simulator.math.odes.MultiTable.Block.Column; import de.zbit.gui.GUITools; -import eva2.gui.Plot; +import eva2.gui.plot.Plot; /** A runnable that generates a plot for a given simulation result and @@ -35,7 +33,6 @@ * * @author Andreas Dräger * @author Roland Keller - * @version $Rev$ * @since 1.0 */ public class Plotter implements Runnable { diff --git a/test/org/sbml/simulator/math/SimulationModeTest.java b/test/org/sbml/simulator/math/SimulationModeTest.java index dc0a70f..5fa9d09 100644 --- a/test/org/sbml/simulator/math/SimulationModeTest.java +++ b/test/org/sbml/simulator/math/SimulationModeTest.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -32,7 +30,6 @@ * A test class for SBML files from the SBML Test Suite. * * @author Andreas Dräger - * @version $Rev$ * @since 1.0 */ public class SimulationModeTest { diff --git a/test/org/sbml/simulator/math/SimulationTest.java b/test/org/sbml/simulator/math/SimulationTest.java index 6b9acbd..f2a58f2 100644 --- a/test/org/sbml/simulator/math/SimulationTest.java +++ b/test/org/sbml/simulator/math/SimulationTest.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -29,7 +27,7 @@ import org.simulator.math.odes.RosenbrockSolver; import org.simulator.sbml.SBMLinterpreter; -import eva2.gui.Plot; +import eva2.gui.plot.Plot; /** * A test program that graphically displays a plot for an SBML model that is @@ -37,7 +35,6 @@ * and draws the result in the plot. * * @author Andreas Dräger - * @version $Rev$ * @since 1.0 */ public class SimulationTest { diff --git a/test/org/sbml/simulator/math/SimulationTestAutomatic.java b/test/org/sbml/simulator/math/SimulationTestAutomatic.java index 5954033..b28620e 100644 --- a/test/org/sbml/simulator/math/SimulationTestAutomatic.java +++ b/test/org/sbml/simulator/math/SimulationTestAutomatic.java @@ -1,6 +1,4 @@ /* - * $Id$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -52,7 +50,6 @@ * through models from biomodels database and perform a simulation. * * @author Andreas Dräger - * @version $Rev$ * @since 1.0 */ public class SimulationTestAutomatic { diff --git a/test/org/sbml/simulator/math/UnitDerivitionTest.java b/test/org/sbml/simulator/math/UnitDerivitionTest.java index ec7bce1..384da22 100644 --- a/test/org/sbml/simulator/math/UnitDerivitionTest.java +++ b/test/org/sbml/simulator/math/UnitDerivitionTest.java @@ -1,6 +1,4 @@ /* - * $Id: UnitDerivitionTest.java 10:56:10 draeger$ - * $URL$ * --------------------------------------------------------------------- * This file is part of SBMLsimulator, a Java-based simulator for models * of biochemical processes encoded in the modeling language SBML. @@ -32,7 +30,6 @@ * A small test program to evaluate units in a given SBML file (file name). * * @author Andreas Dräger - * @version $Rev$ * @since 1.0 */ public class UnitDerivitionTest {