From: lehtonen Date: Fri, 12 Apr 2013 01:12:44 +0000 (+0000) Subject: Merged changes from r27124 through r27280 from trunk to branches/simantics-1.10 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=d0db128759b0d2e7773629e303f5d7fae3fd4cc8;p=simantics%2Fsysdyn.git Merged changes from r27124 through r27280 from trunk to branches/simantics-1.10 in preparation for the Simantics 1.10 release. refs #4189 The merged changes include fixes for the following issues:
	2013-07 (22)
		#4219	Transferable graph with resource literals can only be imported once
		#4223	Remove stdout printing option from issues to CSV export action
		#4231	Wordwrap/Horizontal scrollbar for document editor StyledText widget
		#4233	FileUtils.copyFile/copy do not close file descriptors properly
		#4234	File handle leakage in PDF export
		#4246	Problems in FastLZ stream implementations
		#4248	Query collector fails to collect some discarded parents
		#4249	Subscription collection initialization fails if a subscription item is broken (has no name)
		#4250	ContextualHelp should attempt help context resolution on diagrams even when selected element is not mapped
		#4224	Allow GraphExplorer item selection by keys / labels to use other than primary column for matching.
		#4189	Branch and release Simantics 1.10
		#4235	Drawing template changes
		#4065	Fix annotation user interfaces
		#4218	Color edit support for DnD monitors
		#4220	Change EntityRemover to not remove L0.HasProperty objects as composed properties if they are an L0.PartOf something else
		#4225	Show resource ID in issue view if there's nothing else to show for the issue context
		#4226	Make low level Layer0 validation produce fatal issues so that they don't go unnoticed.
		#4228	Allow CSV export number format specification through preferences
		#4229	Customizable clipboard logic in CopyPasteHandler
		#4230	Prevent RouteGraphNode from starting connection rerouting if there are more than one other elements selected
		#4247	Primarily look for workbench search function from active model, resort to project only secondarily.
		#4251	Allow tree columns in TreeDialog
	2013-06 (28)
		#4113	ResourceBinding cleanup
		#4181	Caching prevents some valid renames
		#4182	Dependency index gets out of sync
		#4185	undo(int numberOfOperations)
		#4186	PDF export leaks memory
		#4190	Do not allow entity names to be modified to begin with one or more dots ('.')
		#4191	AdaptationUtils.adaptToCollection fails to adapt, if class implements IAdaptable
		#4193	Selection view input throttling produces wrong tabs for user
		#4195	Deleting terminal element in symbol editor fails to remove diagram connection points from symbol
		#4202	SWTKeyEventAdapter produces wrong modifier state mask for key event when AltGr is pressed
		#4210	Simulation time HMS mode viewing fails to show time beyond 5 965 hours
		#4211	Problems with session reconnect
		#4212	setImmutable failed if cluster was not resident
		#4215	Safety fixes for monitor formatting
		#2897	As a developer, I want to use GraphExplorer as non-virtual
		#3219	Lazy updating of model browser and graph explorer are problematic
		#3994	Get Resource -> Resource map in SCL based mapping
		#4184	TreeViewer based GraphExplorer
		#4206	Save work done for team feature movie.
		#3984	Import sources for SimanticsExcel.dll
		#4197	If mouse doesn't move between subsequent diagram copy-paste operations, offset the pasted elements as when using Edit / Paste main menu
		#4203	Migration framework enhancement
		#4204	Temp file management in Simantics facade
		#4205	Refactor issues to allow reporting of L0 issues
		#4213	Make recovery work silently.
		#4214	GraphExplorerImpl image decorations should be offloaded from the UI thread into the image loader job
		#4216	BoxSelectionMode should be cancelable by pressing ESC
		#4217	Extend BasicExpression lexer to support 8-bit ASCII characters in quoted strings
	2013-05 (29)
		#4114	Flag type not verified for newly created flags
		#4132	Workspace persistent virtual graph loading robustness / safety enhancements
		#4144	Spreadsheet loses selection while editing cell
		#4145	Useless error messages when pasting PNG image on top of image node in a drawing template
		#4151	Issues are not updated in some removal cases
		#4157	Diagram loading can cause weird exceptions if editor is disposed during loading
		#4158	Manual activation of mapping messes up undo
		#4159	Removal of connected diagram reference elements corrupts database
		#4161	RouteGraph.makePersistent behaves incorrectly when the connection is simple
		#4163	Minor bug in connect tool
		#4164	Component modification metadata missing for some removed connections
		#4166	Session does not close properly
		#4169	Modelled views fail to show content at startup
		#4173	Random access values can corrupt the database session
		#4174	AwtFocusHandler.hidePopups race condition
		#4178	Move tryRemover from DeleteNodeHandler to RemoverUtil
		#4153	Exporting GraphFiles
		#4160	Minor modifications to SCL documentation
		#4165	Support session reconnect in SimanticsPlatform
		#3519	Change Sysdyn jenkins builds to bundle JRE 6
		#4142	Simantics 1.9 release
		#4147	Store SCL console command history into preferences
		#4148	Add undo into DB.scl
		#4150	Batch issue validation performance enhancements
		#4155	Allow overriding oleEditor's title.
		#4162	runTest command for SCL console
		#4167	Remove resources from index updates
		#4170	Set exported PDF Application metadata based on IProduct information
		#4179	Support multiple tg roots in migration framework
git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/branches@27281 ac1ea38d-2e2b-0410-8846-a27921b304fc --- diff --git a/simantics-1.10/org.simantics.jfreechart.ontology/graph.tg b/simantics-1.10/org.simantics.jfreechart.ontology/graph.tg index 5cc13db4..3abaa9be 100644 Binary files a/simantics-1.10/org.simantics.jfreechart.ontology/graph.tg and b/simantics-1.10/org.simantics.jfreechart.ontology/graph.tg differ diff --git a/simantics-1.10/org.simantics.jfreechart.ontology/graph/JFreeChart.pgraph b/simantics-1.10/org.simantics.jfreechart.ontology/graph/JFreeChart.pgraph index c83c6743..aaf0a275 100644 --- a/simantics-1.10/org.simantics.jfreechart.ontology/graph/JFreeChart.pgraph +++ b/simantics-1.10/org.simantics.jfreechart.ontology/graph/JFreeChart.pgraph @@ -111,6 +111,8 @@ JFREE.XYAreaRenderer - + + + + + \ No newline at end of file diff --git a/simantics-1.10/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/DeviationRenderer.java b/simantics-1.10/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/DeviationRenderer.java new file mode 100644 index 00000000..716bb682 --- /dev/null +++ b/simantics-1.10/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/DeviationRenderer.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2013 Association for Decentralized Information Management in + * Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Semantum Oy - initial API and implementation + *******************************************************************************/ +package org.simantics.jfreechart.chart; + +import org.jfree.chart.labels.StandardXYToolTipGenerator; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; + +public class DeviationRenderer extends AbstractRenderer { + + public DeviationRenderer(ReadGraph graph, Resource resource) { + super(graph, resource); + } + + private org.jfree.chart.renderer.xy.DeviationRenderer renderer; + + @Override + public org.jfree.chart.renderer.AbstractRenderer getRenderer() { + if(renderer == null) { + renderer = new org.jfree.chart.renderer.xy.DeviationRenderer(); + renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator()); + } + return renderer; + } + +} diff --git a/simantics-1.10/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/ColorPicker.java b/simantics-1.10/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/ColorPicker.java index 2901c270..c51a8feb 100644 --- a/simantics-1.10/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/ColorPicker.java +++ b/simantics-1.10/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/ColorPicker.java @@ -13,12 +13,10 @@ package org.simantics.jfreechart.chart.properties; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Device; -import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.widgets.ColorDialog; @@ -44,6 +42,7 @@ import org.simantics.ui.SimanticsUI; import org.simantics.ui.utils.AdaptionUtils; import org.simantics.utils.RunnableWithObject; import org.simantics.utils.datastructures.Triple; +import org.simantics.utils.ui.gfx.ColorImageDescriptor; /** * Composite for selecting a color for a chart component @@ -165,12 +164,12 @@ public class ColorPicker extends Composite implements Widget { * @param blue Blue 0-255 * @return */ - private Image getColorPickerImage(Device device, int red, int green, int blue) { - Image image = new Image(device, 20, 20); - GC gc = new GC (image); - gc.setBackground (new Color(device, red, green, blue)); - gc.fillRectangle (image.getBounds ()); - gc.dispose (); + private ImageDescriptor getColorPickerImage(Device device, int red, int green, int blue) { + ImageDescriptor image = new ColorImageDescriptor(red, green, blue, 20, 20, true); + //GC gc = new GC (image); + //gc.setBackground (new Color(device, red, green, blue)); + //gc.fillRectangle (image.getBounds ()); + //gc.dispose (); return image; } @@ -179,7 +178,7 @@ public class ColorPicker extends Composite implements Widget { * @author Teemu Lempinen * */ - private class ColorImageFactoryFactory extends ReadFactoryImpl { + private class ColorImageFactoryFactory extends ReadFactoryImpl { Button button; @@ -188,12 +187,13 @@ public class ColorPicker extends Composite implements Widget { this.button = button; } + @Override public Object getIdentity(Object inputContents) { return new Triple, Button>(inputContents, getClass(), button); } @Override - public Image perform(ReadGraph graph, Resource input) throws DatabaseException { + public ImageDescriptor perform(ReadGraph graph, Resource input) throws DatabaseException { if(button.getWidget().isDisposed()) return null; Display device = button.getWidget().getDisplay(); @@ -263,6 +263,7 @@ public class ColorPicker extends Composite implements Widget { final RGB oldRGB = getColor(graph, resource); display.asyncExec(new RunnableWithObject(oldRGB) { + @Override public void run() { // Use color dialog to select a color Shell shell = new Shell(display); @@ -280,7 +281,7 @@ public class ColorPicker extends Composite implements Widget { @Override public void perform(WriteGraph graph) throws DatabaseException { G2DResource g2d = G2DResource.getInstance(graph); - float[] components = new float[] {(float)rgb.red / 255.0f, (float)rgb.green / 255.0f, (float)rgb.blue / 255.0f, 1.0f}; + float[] components = new float[] {rgb.red / 255.0f, rgb.green / 255.0f, rgb.blue / 255.0f, 1.0f}; graph.claimLiteral(resource, getColorRelation(graph), g2d.Color, components); } }); @@ -301,7 +302,7 @@ public class ColorPicker extends Composite implements Widget { */ private class DefaultColorSelectionFactory extends ReadFactoryImpl { - private Boolean isCustom; + private final Boolean isCustom; /** * diff --git a/simantics-1.10/org.simantics.modelica/src/org/simantics/modelica/ModelicaManager.java b/simantics-1.10/org.simantics.modelica/src/org/simantics/modelica/ModelicaManager.java index 5364078e..2de275d8 100644 --- a/simantics-1.10/org.simantics.modelica/src/org/simantics/modelica/ModelicaManager.java +++ b/simantics-1.10/org.simantics.modelica/src/org/simantics/modelica/ModelicaManager.java @@ -68,7 +68,10 @@ public class ModelicaManager { public enum OSType { APPLE, LINUX, SUN, WINDOWS, UNKNOWN } - + + public static String OMC_VERSION = "OMC_VERSION"; + public static String RESULT_FILE_NAME = "RESULT_FILE_NAME"; + /** * Get operating system type * @return OSType @@ -538,12 +541,23 @@ public class ModelicaManager { ArrayList commands = new ArrayList(); commands.add(simulationLocation.executableFile.getAbsolutePath()); + + if(experimentParameters.get(RESULT_FILE_NAME) != null) { + commands.add("-r="+experimentParameters.get(RESULT_FILE_NAME)); + } + // Write new initial values (parameters). No need to update xml if structure has changed. In that case also xml is up-to-date if(parameterChanges != null) { - String version = getOMCVersion(simulationLocation.omcHome); + String version = experimentParameters.get(OMC_VERSION); + if(version == null) + version = getOMCVersion(simulationLocation.omcHome); if(version.startsWith("1.9")) { // Handled in experiment - updateInitFile(simulationLocation, experimentParameters, parameterChanges); + if(parameterChanges.size() == 1) { + commands.add("-override"); + commands.add(parameterChanges.keySet().iterator().next() + "=" + parameterChanges.values().iterator().next()); + } else + updateInitFile(simulationLocation, experimentParameters, parameterChanges); } else { writeInits(simulationLocation, experimentParameters, monitor); } diff --git a/simantics-1.10/org.simantics.modelica/src/org/simantics/modelica/SimulationLocation.java b/simantics-1.10/org.simantics.modelica/src/org/simantics/modelica/SimulationLocation.java index 91ef37b8..98f5cdd0 100644 --- a/simantics-1.10/org.simantics.modelica/src/org/simantics/modelica/SimulationLocation.java +++ b/simantics-1.10/org.simantics.modelica/src/org/simantics/modelica/SimulationLocation.java @@ -16,6 +16,7 @@ import java.io.File; /** * * @author Teemu Lempinen + * @author Tuomas Miettinen * */ public class SimulationLocation { diff --git a/simantics-1.10/org.simantics.objmap/src/org/simantics/objmap/impl/Mapping.java b/simantics-1.10/org.simantics.objmap/src/org/simantics/objmap/impl/Mapping.java index cf4c33c9..abb726e7 100644 --- a/simantics-1.10/org.simantics.objmap/src/org/simantics/objmap/impl/Mapping.java +++ b/simantics-1.10/org.simantics.objmap/src/org/simantics/objmap/impl/Mapping.java @@ -275,12 +275,14 @@ public class Mapping implements IMapping { if(listensDomain) { RangeUpdateRequest request = new RangeUpdateRequest(link, map, this); try { - g.syncRequest(request, request); + boolean modified = g.syncRequest(request, request); + if(modified) { + updated.add(link.rangeElement); + } } catch (DatabaseException e) { throw new MappingException(e); } - // TODO check if really modified - updated.add(link.rangeElement); + } else if(link.type.updateRange(g, map, link.domainElement, link.rangeElement)) diff --git a/simantics-1.10/org.simantics.objmap/src/org/simantics/objmap/impl/RangeUpdateRequest.java b/simantics-1.10/org.simantics.objmap/src/org/simantics/objmap/impl/RangeUpdateRequest.java index 3268d9e2..4c190658 100644 --- a/simantics-1.10/org.simantics.objmap/src/org/simantics/objmap/impl/RangeUpdateRequest.java +++ b/simantics-1.10/org.simantics.objmap/src/org/simantics/objmap/impl/RangeUpdateRequest.java @@ -38,9 +38,9 @@ public class RangeUpdateRequest implements Read, SyncListener @Override public Boolean perform(ReadGraph g) throws DatabaseException { if(map != null) { - link.type.updateRange(g, map, link.domainElement, link.rangeElement); + boolean updated = link.type.updateRange(g, map, link.domainElement, link.rangeElement); map = null; - return Boolean.TRUE; + return updated; } else if(mapping != null) { mapping.domainModified(link); diff --git a/simantics-1.10/org.simantics.sysdyn.ontology/graph.tg b/simantics-1.10/org.simantics.sysdyn.ontology/graph.tg index a7b7d77e..eba5af9c 100644 Binary files a/simantics-1.10/org.simantics.sysdyn.ontology/graph.tg and b/simantics-1.10/org.simantics.sysdyn.ontology/graph.tg differ diff --git a/simantics-1.10/org.simantics.sysdyn.ontology/graph/Migration.pgraph b/simantics-1.10/org.simantics.sysdyn.ontology/graph/Migration.pgraph index 42345d31..7d135469 100644 --- a/simantics-1.10/org.simantics.sysdyn.ontology/graph/Migration.pgraph +++ b/simantics-1.10/org.simantics.sysdyn.ontology/graph/Migration.pgraph @@ -8,14 +8,34 @@ move : L0.Template L0.NamespaceMigrationStep.Prefix.from %from L0.NamespaceMigrationStep.Prefix.to %to -MIGRATION = SYSDYN."from1.6to1.7" : L0.MigrationSequence +MIGRATION = SYSDYN.Migration : L0.Library + +MIGRATION.fromModel1 : L0.Migration + L0.Migration.format "sysdynModel" + L0.Migration.from 1 + L0.Migration.step FROM16TO17 + L0.Migration.priority 1.0 + +MIGRATION.fromModule1 : L0.Migration + L0.Migration.format "sysdynModule" + L0.Migration.from 1 + L0.Migration.step FROM16TO17 + L0.Migration.priority 1.0 + +MIGRATION.fromFunctionLibrary1 : L0.Migration + L0.Migration.format "sysdynFunctionLibrary" + L0.Migration.from 1 + L0.Migration.step FROM16TO17 + L0.Migration.priority 1.0 + +FROM16TO17 = MIGRATION."from1.6to1.7" : L0.MigrationSequence @L0.list - MIGRATION.Ontologies - MIGRATION.Spreadsheets - MIGRATION.SysdynChanges - MIGRATION.OrderedSetsToLists + FROM16TO17.Ontologies + FROM16TO17.Spreadsheets + FROM16TO17.SysdynChanges + FROM16TO17.OrderedSetsToLists -MIGRATION.Ontologies : L0.NamespaceMigrationStep +FROM16TO17.Ontologies : L0.NamespaceMigrationStep @L0.list _ @move "http://www.simantics.org/Layer0-" "1.0" "1.1" @@ -60,7 +80,7 @@ MIGRATION.Ontologies : L0.NamespaceMigrationStep _ @move"http://www.simantics.org/SelectionView-" "1.1" "1.2" -MIGRATION.Spreadsheets : L0.NamespaceMigrationStep +FROM16TO17.Spreadsheets : L0.NamespaceMigrationStep @L0.list _ @move "http://www.simantics.org/Spreadsheet-1.2/" "HasContent" "Cell/content" @@ -91,7 +111,7 @@ MIGRATION.Spreadsheets : L0.NamespaceMigrationStep _ @move "http://www.simantics.org/Spreadsheet-1.2/" "ColumnWidthsOf" "Headers/columnWidths/Inverse" -MIGRATION.SysdynChanges : L0.NamespaceMigrationStep +FROM16TO17.SysdynChanges : L0.NamespaceMigrationStep @L0.list _ @move "http://www.simantics.org/Sysdyn-1.1/" "HasTail" "Variable/HasTail" @@ -101,7 +121,7 @@ MIGRATION.SysdynChanges : L0.NamespaceMigrationStep @move "http://www.simantics.org/Sysdyn-1.1/" "SharedModuleOntolofgy" "SharedModuleOntology" -MIGRATION.OrderedSetsToLists : L0.OrderedSetToListMigrationStep +FROM16TO17.OrderedSetsToLists : L0.OrderedSetToListMigrationStep @L0.list _ : L0.OrderedSetToListMigrationStep.Change L0.OrderedSetToListMigrationStep.entityType "http://www.simantics.org/Sysdyn-1.1/Variable" diff --git a/simantics-1.10/org.simantics.sysdyn.ontology/graph/Sysdyn.pgraph b/simantics-1.10/org.simantics.sysdyn.ontology/graph/Sysdyn.pgraph index 30c5641a..109a1df9 100644 --- a/simantics-1.10/org.simantics.sysdyn.ontology/graph/Sysdyn.pgraph +++ b/simantics-1.10/org.simantics.sysdyn.ontology/graph/Sysdyn.pgraph @@ -44,6 +44,8 @@ SYSDYN.SysdynModel -- SYSDYN.SysdynModel.tolerance --> L0.Double -- SYSDYN.SysdynModel.solver --> L0.String -- SYSDYN.SysdynModel.variableFilter --> L0.String -- SYSDYN.SysdynModel.fmuFile --> L0.ByteArray -- SYSDYN.SysdynModel.exeFile --> L0.ByteArray -- SYSDYN.SensitivityAnalysisExperiment.minValue --> L0.Double -- SYSDYN.SensitivityAnalysisExperiment.maxValue --> L0.Double -- SYSDYN.SensitivityAnalysisExperiment.numValues --> L0.Integer -- SYSDYN.SensitivityAnalysisExperiment.mean --> L0.Double -- SYSDYN.SensitivityAnalysisExperiment.stdDeviation --> L0.Double - none 0 fill 1 + none 0 fill 1 \ No newline at end of file diff --git a/simantics-1.10/org.simantics.sysdyn.ui/icons/bullet_gray.png b/simantics-1.10/org.simantics.sysdyn.ui/icons/bullet_gray.png new file mode 100644 index 00000000..6f58b930 Binary files /dev/null and b/simantics-1.10/org.simantics.sysdyn.ui/icons/bullet_gray.png differ diff --git a/simantics-1.10/org.simantics.sysdyn.ui/icons/bullet_green.png b/simantics-1.10/org.simantics.sysdyn.ui/icons/bullet_green.png new file mode 100644 index 00000000..1b5409f3 Binary files /dev/null and b/simantics-1.10/org.simantics.sysdyn.ui/icons/bullet_green.png differ diff --git a/simantics-1.10/org.simantics.sysdyn.ui/plugin.xml b/simantics-1.10/org.simantics.sysdyn.ui/plugin.xml index 46659c96..b03868c1 100644 --- a/simantics-1.10/org.simantics.sysdyn.ui/plugin.xml +++ b/simantics-1.10/org.simantics.sysdyn.ui/plugin.xml @@ -801,6 +801,23 @@ + + + + + + + + + + ()), + jfree.Dataset_renderer, renderer); + + GraphUtils.create2(g, jfree.XYPlot, + l0.HasName, "XYPlot" + UUID.randomUUID().toString(), + l0.PartOf, jfreechart, + jfree.Plot_domainAxis, domainAxis, + jfree.Plot_rangeAxis, rangeAxis, + jfree.Plot_rangeAxisList, ListUtils.create(g, Collections.singletonList(rangeAxis)), + l0.ConsistsOf, dataset, + l0.ConsistsOf, domainAxis, + l0.ConsistsOf, rangeAxis); + } + + }); + + + + return null; + } +} \ No newline at end of file diff --git a/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/newComponents/NewSharedFunctionLibraryHandler.java b/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/newComponents/NewSharedFunctionLibraryHandler.java index 5eba69cd..ab79d1f8 100644 --- a/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/newComponents/NewSharedFunctionLibraryHandler.java +++ b/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/newComponents/NewSharedFunctionLibraryHandler.java @@ -17,7 +17,7 @@ import org.eclipse.jface.viewers.ISelection; import org.eclipse.ui.handlers.HandlerUtil; import org.simantics.browsing.ui.common.node.AbstractNode; import org.simantics.db.Resource; -import org.simantics.ui.utils.AdaptionUtils; +import org.simantics.utils.ui.AdaptionUtils; /** * Creates a new shared function library. diff --git a/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/newComponents/NewXYLineChartHandler.java b/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/newComponents/NewXYLineChartHandler.java index c2aac244..bb872cf2 100644 --- a/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/newComponents/NewXYLineChartHandler.java +++ b/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/newComponents/NewXYLineChartHandler.java @@ -32,7 +32,7 @@ import org.simantics.layer0.utils.direct.GraphUtils; import org.simantics.sysdyn.JFreeChartResource; import org.simantics.sysdyn.ui.browser.nodes.ChartsFolder; import org.simantics.ui.SimanticsUI; -import org.simantics.ui.utils.AdaptionUtils; +import org.simantics.utils.ui.AdaptionUtils; /** * Handler for creating a new XYLineChart in model browser diff --git a/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ModuleInputTab.java b/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ModuleInputTab.java index c4c92ac2..0b5b3d68 100644 --- a/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ModuleInputTab.java +++ b/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ModuleInputTab.java @@ -68,6 +68,9 @@ public class ModuleInputTab extends LabelPropertyTabContributor { if(instanceOf == null) return result; Resource configuration = graph.getSingleObject(instanceOf, sr2.IsDefinedBy); for(Resource input : graph.syncRequest(new ObjectsWithType(configuration, l0.ConsistsOf, sr.Input))) { + if(!graph.getObjects(input, sr.Variable_isHeadOf).isEmpty()) + continue; // Only inputs with tail dependencies allowed. + Resource dependency = null; for(Resource dep : graph.getObjects(module, sr.Variable_isHeadOf)) { Resource refersTo = graph.getPossibleObject(dep, sr.Dependency_refersTo); diff --git a/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/SensitivityAnalysisExperimentTab.java b/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/SensitivityAnalysisExperimentTab.java index 701e0cb8..f3caa587 100644 --- a/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/SensitivityAnalysisExperimentTab.java +++ b/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/SensitivityAnalysisExperimentTab.java @@ -104,6 +104,26 @@ public class SensitivityAnalysisExperimentTab extends LabelPropertyTabContributo numValues.setInputValidator(new IntegerValidator()); numValues.setColorProvider(new SysdynBasicColorProvider(new LocalResourceManager(JFaceResources.getResources(), numValues.getWidget()))); + // mean + label = new Label(composite, SWT.NONE); + label.setText("Mean"); + + TrackedText mean = new TrackedText(composite, support, SWT.BORDER); + mean.setTextFactory(new DoublePropertyFactory(SysdynResource.URIs.SensitivityAnalysisExperiment_mean)); + mean.addModifyListener(new DoublePropertyModifier(context, SysdynResource.URIs.SensitivityAnalysisExperiment_mean)); + mean.setInputValidator(new DoubleValidator()); + mean.setColorProvider(new SysdynBasicColorProvider(new LocalResourceManager(JFaceResources.getResources(), mean.getWidget()))); + + // standard deviation + label = new Label(composite, SWT.NONE); + label.setText("Standard deviation"); + + TrackedText stdDeviation = new TrackedText(composite, support, SWT.BORDER); + stdDeviation.setTextFactory(new DoublePropertyFactory(SysdynResource.URIs.SensitivityAnalysisExperiment_stdDeviation)); + stdDeviation.addModifyListener(new DoublePropertyModifier(context, SysdynResource.URIs.SensitivityAnalysisExperiment_stdDeviation)); + stdDeviation.setInputValidator(new DoubleValidator()); + stdDeviation.setColorProvider(new SysdynBasicColorProvider(new LocalResourceManager(JFaceResources.getResources(), stdDeviation.getWidget()))); + // Scrolled composite settings sc.setContent(composite); sc.setMinSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT)); diff --git a/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/StockExpression.java b/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/StockExpression.java index 23ef6ea1..0c8d1c63 100644 --- a/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/StockExpression.java +++ b/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/StockExpression.java @@ -138,7 +138,7 @@ public class StockExpression implements IExpression { @Override public void save(final Resource expression, Map data) { final String currentText = this.expression.getExpression(); - if(currentText != null) { + if(currentText != null && !currentText.equals(data.get("initialEquation"))) { SimanticsUI.getSession().asyncRequest(new WriteRequest() { @Override diff --git a/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/SensitivityDataset.java b/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/SensitivityDataset.java new file mode 100644 index 00000000..970185eb --- /dev/null +++ b/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/SensitivityDataset.java @@ -0,0 +1,189 @@ +/******************************************************************************* + * Copyright (c) 2013 Association for Decentralized Information Management in + * Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Semantum Oy - initial API and implementation + *******************************************************************************/ +package org.simantics.sysdyn.ui.trend; + +import java.awt.BasicStroke; +import java.awt.Paint; +import java.util.ArrayList; +import java.util.Collections; + +import javax.swing.SwingUtilities; + +import org.jfree.chart.ChartColor; +import org.jfree.chart.renderer.AbstractRenderer; +import org.jfree.chart.renderer.xy.DeviationRenderer; +import org.jfree.data.general.Dataset; +import org.jfree.data.xy.YIntervalSeries; +import org.jfree.data.xy.YIntervalSeriesCollection; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.procedure.adapter.DisposableListener; +import org.simantics.db.exception.DatabaseException; +import org.simantics.jfreechart.chart.IRenderer; +import org.simantics.ui.SimanticsUI; +import org.simantics.utils.datastructures.Pair; + +public class SensitivityDataset extends XYDataset { + + DeviationRenderer renderer; + + public SensitivityDataset(ReadGraph graph, Resource resource) throws DatabaseException { + super(graph, resource); + } + + @Override + public Dataset getDataset() { + if(dataset == null) { + dataset = new YIntervalSeriesCollection(); + } + + if(datasetListener == null || datasetListener.isDisposed()) { + SimanticsUI.getSession().asyncRequest(getDatasetRequest(), getDatasetListener()); + } + + if(timeListener == null || timeListener.isDisposed()) { + SimanticsUI.getSession().asyncRequest(getTimeRequest(), getTimeListener()); + } + return dataset; + } + + @Override + public AbstractRenderer getRenderer() { + if(renderer == null) + renderer = new DeviationRenderer(true, false); + return renderer; + } + + @Override + protected DisposableListener, IRenderer>> getDatasetListener() { + if(datasetListener == null || datasetListener.isDisposed()) { + datasetListener = new SensitivityDatasetListener(); + } + return datasetListener; + } + + private class SensitivityDatasetListener extends DisposableListener, IRenderer>> { + + @Override + public void execute(Pair, IRenderer> result) { + final ArrayList series = result.first; + + // Modify series in AWT thread to avoid synchronization problems + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + + if(dataset == null || !(dataset instanceof YIntervalSeriesCollection)) + return; + + YIntervalSeriesCollection ds = (YIntervalSeriesCollection)dataset; + + DeviationRenderer dr = (DeviationRenderer)getRenderer(); + Paint[] paints = { + ChartColor.LIGHT_RED, + ChartColor.LIGHT_YELLOW, + ChartColor.LIGHT_GREEN, + ChartColor.LIGHT_BLUE, + ChartColor.LIGHT_GRAY + }; + for(int i = 0; i < paints.length; i++) { + dr.setSeriesStroke(i, new BasicStroke(2F, 1, 1)); + dr.setSeriesPaint(i, paints[i]); + dr.setSeriesFillPaint(i, paints[i]); + } + dr.setAlpha(1); + + // Remove all series + for(int i = ds.getSeriesCount() - 1; i >= 0; i-- ) { + ds.removeSeries(ds.getSeries(i)); + } + + int n = series.size(); + if(n < 1) + return; + + int length = series.get(0).values[0].length; + + YIntervalSeries median = new YIntervalSeries("Median"); + YIntervalSeries p100 = new YIntervalSeries("100%"); + YIntervalSeries p75 = new YIntervalSeries("75%"); + YIntervalSeries p50 = new YIntervalSeries("50%"); + YIntervalSeries p25 = new YIntervalSeries("25%"); + + ArrayList sorter = new ArrayList(); + for(int i = 0; i < length; i++) { + sorter.clear(); + for(int j = 0; j < n; j++) { + sorter.add(series.get(j).values[1][i]); // values is a two-dimensional array. 0 dimension == times, 1 == values + } + Collections.sort(sorter); + + median.add( + series.get(0).values[0][i], + sorter.get(sorter.size()/2), + sorter.get(sorter.size()/2), + sorter.get(sorter.size()/2) + ); + + if(n > 8) + p25.add( + series.get(0).values[0][i], + sorter.get(sorter.size()/2), + sorter.get(sorter.size() / 2 - (int)(sorter.size() * 0.25) / 2), + sorter.get(sorter.size() / 2 + (int)(sorter.size() * 0.25) / 2) + ); + + if(n > 4) + p50.add( + series.get(0).values[0][i], + sorter.get(sorter.size()/2), + sorter.get(sorter.size() / 2 - (int)(sorter.size() * 0.5) / 2), + sorter.get(sorter.size() / 2 + (int)(sorter.size() * 0.5) / 2) + ); + + if(n > 8) + p75.add( + series.get(0).values[0][i], + sorter.get(sorter.size()/2), + sorter.get(sorter.size() / 2 - (int)(sorter.size() * 0.75) / 2), + sorter.get(sorter.size() / 2 + (int)(sorter.size() * 0.75) / 2) + ); + + p100.add( + series.get(0).values[0][i], + sorter.get(sorter.size()/2), + sorter.get(0), + sorter.get(sorter.size() - 1) + ); + } + + ds.addSeries(median); + if(n > 8) + ds.addSeries(p25); + if(n > 4) + ds.addSeries(p50); + if(n > 8) + ds.addSeries(p75); + ds.addSeries(p100); + + } + }); + } + + @Override + public void exception(Throwable t) { + t.printStackTrace(); + } + + } +} diff --git a/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/XYDataset.java b/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/XYDataset.java index f6a275c2..9eac19cf 100644 --- a/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/XYDataset.java +++ b/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/XYDataset.java @@ -39,7 +39,7 @@ import org.simantics.db.layer0.exception.MissingVariableException; import org.simantics.db.layer0.request.PossibleActiveExperiment; import org.simantics.db.layer0.variable.Variable; import org.simantics.db.layer0.variable.Variables; -import org.simantics.db.procedure.Listener; +import org.simantics.db.common.procedure.adapter.DisposableListener; import org.simantics.db.request.Read; import org.simantics.diagram.G2DUtils; import org.simantics.jfreechart.chart.AbstractDataset; @@ -62,198 +62,217 @@ import org.simantics.utils.datastructures.Pair; */ public class XYDataset extends AbstractDataset implements org.simantics.jfreechart.chart.XYDataset{ - private IRenderer renderer; + protected IRenderer renderer; public XYDataset(ReadGraph graph, final Resource datasetResource) throws DatabaseException { super(graph, datasetResource); } - private DefaultXYDataset dataset; - private DataSetListener datasetListener; - private TimeListener timeListener; - - @Override - public Dataset getDataset() { - if(dataset == null) { - dataset = new DefaultXYDataset(); - } - + protected Dataset dataset; + protected DisposableListener, IRenderer>> datasetListener; + protected DisposableListener timeListener; + + protected DisposableListener, IRenderer>> getDatasetListener() { if(datasetListener == null || datasetListener.isDisposed()) { datasetListener = new DataSetListener(); - SimanticsUI.getSession().asyncRequest(new Read, IRenderer>>() { - - @Override - public Pair, IRenderer> perform(ReadGraph graph) throws DatabaseException { - JFreeChartResource jfree = JFreeChartResource.getInstance(graph); - - // Renderer - IRenderer renderer = null; - Resource rendererResource = graph.getPossibleObject(resource, jfree.Dataset_renderer); - if(rendererResource != null) - renderer = graph.adapt(rendererResource, IRenderer.class); - - ArrayList series = new ArrayList(); - - String realizationURI = getRealizationURI(graph); - - if(realizationURI == null) - return new Pair, IRenderer>(series, renderer); // No experiment -> No results + } + return datasetListener; + } - // Get a variable for the x-axis (if not time) - double[] domainValues = null; - Resource domainAxis = graph.getPossibleObject(resource, jfree.Dataset_mapToDomainAxis); - if(domainAxis != null) { - String rvi = graph.getPossibleRelatedValue(domainAxis, jfree.variableRVI); - if(rvi != null && !rvi.isEmpty()) { - try { - Variable domainVariable = Variables.getVariable(graph, realizationURI + rvi); - Variable valuesVariable = domainVariable.browsePossible(graph, "#" + Functions.VALUES +"#"); - if(valuesVariable != null) { - double[][] valuesArray = valuesVariable.getValue(graph); - if(valuesArray.length > 0) - domainValues = valuesArray[0]; - } - } catch(MissingVariableException e) { - //Do nothing, use time as domain axis + protected DisposableListener getTimeListener() { + if(timeListener == null || timeListener.isDisposed()) { + timeListener = new TimeListener(); + } + return timeListener; + } + + protected Read, IRenderer>> getDatasetRequest() { + return new Read, IRenderer>>() { + + @Override + public Pair, IRenderer> perform(ReadGraph graph) throws DatabaseException { + JFreeChartResource jfree = JFreeChartResource.getInstance(graph); + + // Renderer + IRenderer renderer = null; + Resource rendererResource = graph.getPossibleObject(resource, jfree.Dataset_renderer); + if(rendererResource != null) + renderer = graph.adapt(rendererResource, IRenderer.class); + + ArrayList series = new ArrayList(); + + String realizationURI = getRealizationURI(graph); + + if(realizationURI == null) + return new Pair, IRenderer>(series, renderer); // No experiment -> No results + + // Get a variable for the x-axis (if not time) + double[] domainValues = null; + Resource domainAxis = graph.getPossibleObject(resource, jfree.Dataset_mapToDomainAxis); + if(domainAxis != null) { + String rvi = graph.getPossibleRelatedValue(domainAxis, jfree.variableRVI); + if(rvi != null && !rvi.isEmpty()) { + try { + Variable domainVariable = Variables.getVariable(graph, realizationURI + rvi); + Variable valuesVariable = domainVariable.browsePossible(graph, "#" + Functions.VALUES +"#"); + if(valuesVariable != null) { + double[][] valuesArray = valuesVariable.getValue(graph); + if(valuesArray.length > 0) + domainValues = valuesArray[0]; } + } catch(MissingVariableException e) { + //Do nothing, use time as domain axis } } + } - Resource seriesList = graph.getPossibleObject(resource, jfree.Dataset_seriesList); + Resource seriesList = graph.getPossibleObject(resource, jfree.Dataset_seriesList); - // Get properties for all series - if(seriesList != null) { - for(Resource r : ListUtils.toList(graph, seriesList)) { - String rvi = graph.getPossibleRelatedValue(r, jfree.variableRVI); - if(rvi == null) - continue; + // Get properties for all series + if(seriesList != null) { + for(Resource r : ListUtils.toList(graph, seriesList)) { + String rvi = graph.getPossibleRelatedValue(r, jfree.variableRVI); + if(rvi == null) + continue; - try { - // Get visual properties - Integer width = graph.getPossibleRelatedValue(r, jfree.Series_lineWidth, Bindings.INTEGER); - if(width == null) width = 1; + try { + // Get visual properties + Integer width = graph.getPossibleRelatedValue(r, jfree.Series_lineWidth, Bindings.INTEGER); + if(width == null) width = 1; - Resource c = graph.getPossibleObject(r, jfree.color); - Color color = c == null ? null : G2DUtils.getColor(graph, c); - - String label = graph.getPossibleRelatedValue(r, Layer0.getInstance(graph).HasLabel); + Resource c = graph.getPossibleObject(r, jfree.color); + Color color = c == null ? null : G2DUtils.getColor(graph, c); + + String label = graph.getPossibleRelatedValue(r, Layer0.getInstance(graph).HasLabel); - // Get a variable for the series - Variable v = Variables.getVariable(graph, realizationURI + rvi); - if(v == null) - return new Pair, IRenderer>(series, renderer); + // Get a variable for the series + Variable v = Variables.getVariable(graph, realizationURI + rvi); + if(v == null) + return new Pair, IRenderer>(series, renderer); - // Get values - Variable dsVariable = v.browsePossible(graph, "#" + Functions.ACTIVE_DATASETS + "#"); - Object object = null; - if(dsVariable != null) - object = dsVariable.getValue(graph); + // Get values + Variable dsVariable = v.browsePossible(graph, "#" + Functions.ACTIVE_DATASETS + "#"); + Object object = null; + if(dsVariable != null) + object = dsVariable.getValue(graph); - if(object == null || !(object instanceof ArrayList)) - return new Pair, IRenderer>(series, renderer); + if(object == null || !(object instanceof ArrayList)) + return new Pair, IRenderer>(series, renderer); - ArrayList datasets = new ArrayList(); + ArrayList datasets = new ArrayList(); - for(Object o : (ArrayList)object) { - if(o instanceof SysdynDataSet) - datasets.add((SysdynDataSet)o); - } + for(Object o : (ArrayList)object) { + if(o instanceof SysdynDataSet) + datasets.add((SysdynDataSet)o); + } - String[] filter = graph.getPossibleRelatedValue(r, jfree.variableFilter); - if(filter != null) { - ArrayList result2 = VariableRVIUtils.getDataset(datasets, filter); - if(result2 != null) { - datasets = result2; - } + String[] filter = graph.getPossibleRelatedValue(r, jfree.variableFilter); + if(filter != null) { + ArrayList result2 = VariableRVIUtils.getDataset(datasets, filter); + if(result2 != null) { + datasets = result2; } + } + + for(SysdynDataSet dataset : datasets) { + double[] va = dataset.values; - for(SysdynDataSet dataset : datasets) { - double[] va = dataset.values; - - // Get domain axis values (time OR other variable) - double[] ta; - if(domainValues != null) { - ta = domainValues; - - // If domainAxis is other than time, parameter values size is different. - if(domainValues.length > va.length) { - double value = va[0]; - va = new double[domainValues.length]; - for(int i = 0; i < domainValues.length; i++) - va[i] = value; - } - - // If domainAxis is a parameter, the domainValues array is too short - if(domainValues.length < va.length && domainValues.length == 2 && domainValues[0] == domainValues[1]) { - double value = domainValues[0]; - ta = new double[va.length]; - for(int i = 0; i < va.length; i++) - ta[i] = value; - } - - } else { - ta = dataset.times; + // Get domain axis values (time OR other variable) + double[] ta; + if(domainValues != null) { + ta = domainValues; + + // If domainAxis is other than time, parameter values size is different. + if(domainValues.length > va.length) { + double value = va[0]; + va = new double[domainValues.length]; + for(int i = 0; i < domainValues.length; i++) + va[i] = value; } - if(ta!=null && va!=null && (va.length == ta.length)) { - // Add series if everything OK - String name = dataset.name; - if(label != null) - name = label; - if(dataset.result != null && !dataset.result.isEmpty()) - name = name + " : " + dataset.result; - series.add(new TempSeries(name, new double[][] {ta, va}, width, color)); - if(ta.length == 0 || va.length == 0) - System.out.println(dataset.name + " : " + dataset.result + ". Sizes: " + va.length + " and " + ta.length); + // If domainAxis is a parameter, the domainValues array is too short + if(domainValues.length < va.length && domainValues.length == 2 && domainValues[0] == domainValues[1]) { + double value = domainValues[0]; + ta = new double[va.length]; + for(int i = 0; i < va.length; i++) + ta[i] = value; } + + } else { + ta = dataset.times; } - } catch (MissingVariableException e) { - // Do nothing, if variable was not found. Move on to the next series + if(ta!=null && va!=null && (va.length == ta.length)) { + // Add series if everything OK + String name = dataset.name; + if(label != null) + name = label; + if(dataset.result != null && !dataset.result.isEmpty()) + name = name + " : " + dataset.result; + series.add(new TempSeries(name, new double[][] {ta, va}, width, color)); + if(ta.length == 0 || va.length == 0) + System.out.println(dataset.name + " : " + dataset.result + ". Sizes: " + va.length + " and " + ta.length); + } } + + } catch (MissingVariableException e) { + // Do nothing, if variable was not found. Move on to the next series } } - return new Pair, IRenderer>(series, renderer); } - - }, datasetListener); - } - - if(timeListener == null || timeListener.isDisposed()) { - timeListener = new TimeListener(); - SimanticsUI.getSession().asyncRequest(new Read() { - @Override - public Double perform(ReadGraph graph) throws DatabaseException { - JFreeChartResource jfree = JFreeChartResource.getInstance(graph); - // Get properties for all series - Resource series = graph.getPossibleObject(resource, jfree.Dataset_seriesList); - if(series != null) { - List seriesList = ListUtils.toList(graph, series); - if(seriesList != null) { - String realizationURI = getRealizationURI(graph); - for(Resource r : seriesList) { - String rvi = graph.getPossibleRelatedValue(r, jfree.variableRVI); - if(rvi == null) - continue; - try { - // Get a variable for the experiment run - Variable v = Variables.getVariable(graph, realizationURI); - if(v == null) - return null; - Variable timeVar = v.browsePossible(graph, "#" + Functions.TIME + "#"); - if(timeVar != null) - return timeVar.getValue(graph, Bindings.DOUBLE); - } catch (MissingVariableException e) { - // Do nothing, if variable was not found. - } + return new Pair, IRenderer>(series, renderer); + } + }; + } + + protected Read getTimeRequest() { + return new Read() { + @Override + public Double perform(ReadGraph graph) throws DatabaseException { + JFreeChartResource jfree = JFreeChartResource.getInstance(graph); + // Get properties for all series + Resource series = graph.getPossibleObject(resource, jfree.Dataset_seriesList); + if(series != null) { + List seriesList = ListUtils.toList(graph, series); + if(seriesList != null) { + String realizationURI = getRealizationURI(graph); + for(Resource r : seriesList) { + String rvi = graph.getPossibleRelatedValue(r, jfree.variableRVI); + if(rvi == null) + continue; + try { + // Get a variable for the experiment run + Variable v = Variables.getVariable(graph, realizationURI); + if(v == null) + return null; + Variable timeVar = v.browsePossible(graph, "#" + Functions.TIME + "#"); + if(timeVar != null) + return timeVar.getValue(graph, Bindings.DOUBLE); + } catch (MissingVariableException e) { + // Do nothing, if variable was not found. } } } - return null; } + return null; + } + + }; + } - }, timeListener); + @Override + public Dataset getDataset() { + if(dataset == null) { + dataset = new DefaultXYDataset(); + } + + if(datasetListener == null || datasetListener.isDisposed()) { + SimanticsUI.getSession().asyncRequest(getDatasetRequest(), getDatasetListener()); + } + + if(timeListener == null || timeListener.isDisposed()) { + SimanticsUI.getSession().asyncRequest(getTimeRequest(), getTimeListener()); } return dataset; } @@ -263,7 +282,7 @@ public class XYDataset extends AbstractDataset implements org.simantics.jfreecha * @author Teemu Lempinen * */ - private class TimeMarker extends ValueMarker { + protected class TimeMarker extends ValueMarker { private static final long serialVersionUID = 2018755066561629172L; public TimeMarker(double value, Paint paint, Stroke stroke) { @@ -271,18 +290,7 @@ public class XYDataset extends AbstractDataset implements org.simantics.jfreecha } } - private class DataSetListener implements Listener, IRenderer>> { - - private boolean disposed = false; - - public void dispose() { - disposed = true; - } - - @Override - public boolean isDisposed() { - return disposed; - } + private class DataSetListener extends DisposableListener, IRenderer>> { @Override public void execute(Pair, IRenderer> result) { @@ -295,7 +303,12 @@ public class XYDataset extends AbstractDataset implements org.simantics.jfreecha @Override public void run() { + if(dataset == null || !(dataset instanceof DefaultXYDataset)) + return; + + DefaultXYDataset ds = (DefaultXYDataset)dataset; org.jfree.chart.plot.XYPlot plot = ((AbstractXYItemRenderer)getRenderer()).getPlot(); + if(plot != null) { /* * Drawing supplier with a modified first yellow. The default first @@ -313,14 +326,14 @@ public class XYDataset extends AbstractDataset implements org.simantics.jfreecha plot.setDrawingSupplier(drawingsupplier); } // Remove all series - for(int i = dataset.getSeriesCount() - 1; i >= 0; i-- ) { - dataset.removeSeries(dataset.getSeriesKey(i)); + for(int i = ds.getSeriesCount() - 1; i >= 0; i-- ) { + ds.removeSeries(ds.getSeriesKey(i)); } // Add found series for(int i = 0; i < series.size(); i++) { TempSeries s = series.get(i); - dataset.addSeries(s.name, s.values); + ds.addSeries(s.name, s.values); getRenderer().setSeriesStroke(i, new BasicStroke((float)s.width)); getRenderer().setSeriesPaint(i, s.color); } @@ -341,10 +354,9 @@ public class XYDataset extends AbstractDataset implements org.simantics.jfreecha * @author Teemu Lempinen * */ - private class TimeListener implements Listener { + protected class TimeListener extends DisposableListener { private ValueMarker marker; - private boolean disposed = false; private Stroke dashStroke = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, new float[] {5.0f, 3.0f, 1.0f, 3.0f}, 0.0f); @@ -353,7 +365,7 @@ public class XYDataset extends AbstractDataset implements org.simantics.jfreecha } public void dispose() { - this.disposed = true; + super.dispose(); if(marker != null) { org.jfree.chart.plot.XYPlot plot = ((AbstractXYItemRenderer)getRenderer()).getPlot(); if(plot != null) @@ -361,11 +373,6 @@ public class XYDataset extends AbstractDataset implements org.simantics.jfreecha } } - @Override - public boolean isDisposed() { - return disposed; - } - @Override public void execute(final Double time) { // Modify in AWT thread to avoid synchronization problems @@ -421,7 +428,7 @@ public class XYDataset extends AbstractDataset implements org.simantics.jfreecha * @author Teemu Lempinen * */ - private class TempSeries { + protected class TempSeries { public double[][] values; public String name; public int width; @@ -472,7 +479,7 @@ public class XYDataset extends AbstractDataset implements org.simantics.jfreecha * @return realization uri for current dataset resource * @throws DatabaseException */ - private String getRealizationURI(ReadGraph graph) throws DatabaseException { + protected String getRealizationURI(ReadGraph graph) throws DatabaseException { if(resource == null) return null; diff --git a/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/ExpressionUtils.java b/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/ExpressionUtils.java index 7fcf67c1..c6a513d1 100644 --- a/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/ExpressionUtils.java +++ b/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/ExpressionUtils.java @@ -570,8 +570,8 @@ public class ExpressionUtils { return ReferenceOption.DOES_NOT_EXIST; else if(Boolean.TRUE.equals(element)) return ReferenceOption.CANNOT_BE_CONNECTED; - else if(element instanceof Variable) { - if(element instanceof Enumeration || element instanceof Sheet) + else if(element instanceof Variable || element instanceof Module) { + if(element instanceof Enumeration || element instanceof Sheet || element instanceof Module || parts.length > 1) return ReferenceOption.CANNOT_BE_CONNECTED; else return ReferenceOption.CAN_BE_CONNECTED; diff --git a/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/imports/ImportUtils.java b/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/imports/ImportUtils.java index d69272b1..c576dd7c 100644 --- a/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/imports/ImportUtils.java +++ b/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/utils/imports/ImportUtils.java @@ -8,6 +8,7 @@ * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation + * Semantum Oy - Bug #4192 *******************************************************************************/ package org.simantics.sysdyn.ui.utils.imports; @@ -40,6 +41,10 @@ import org.simantics.db.common.request.WriteResultRequest; import org.simantics.db.common.utils.NameUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.db.exception.ResourceNotFoundException; +import org.simantics.db.layer0.adapter.impl.DefaultPasteImportAdvisor; +import org.simantics.db.layer0.migration.MigrationState; +import org.simantics.db.layer0.migration.MigrationStateKeys; +import org.simantics.db.layer0.migration.MigrationUtils; import org.simantics.db.layer0.util.RemoverUtil; import org.simantics.db.request.Read; import org.simantics.issues.common.AllBatchIssueSources; @@ -138,18 +143,22 @@ public class ImportUtils { Activator.getDefault().getPreferenceStore().setValue(IMPORTMODELTPATH, (new File(path)).getParent()); + MigrationState state = MigrationUtils.newState(); + state.setProperty(MigrationStateKeys.BASE_URI, SysdynResource.URIs.Migration); + state.setProperty(MigrationStateKeys.UPDATE_DEPENDENCIES, Boolean.FALSE); - - HashMap> handlers = new HashMap>(); - handlers.put("sysdynModel:1", new SysdynImportFormatHandler(project, SysdynResource.URIs.from1$6to1$7, monitor)); - - Object result = ImportUtils.readFile(path, handlers); + Resource result = null; + try { + result = MigrationUtils.importMigrated(monitor, SimanticsUI.getSession(), new File(path), state, new DefaultPasteImportAdvisor(project), project); + } catch (Exception e1) { + e1.printStackTrace(); + } if(result == null || !(result instanceof Resource)) { return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Import model failed: File could not be read.", null); } else { try { - final Resource ModelRoot = (Resource) result; + final Resource ModelRoot = result; IStatus status = SimanticsUI.getSession().syncRequest(new WriteResultRequest() { @Override @@ -352,18 +361,22 @@ public class ImportUtils { Activator.getDefault().getPreferenceStore().setValue(IMPORTMODULETPATH, (new File(path)).getParent()); - // Handler for importing modules - HashMap> handlers = new HashMap>(); - handlers.put("sysdynModule:1", new SysdynImportFormatHandler(model, SysdynResource.URIs.from1$6to1$7, monitor)); + MigrationState state = MigrationUtils.newState(); + state.setProperty(MigrationStateKeys.BASE_URI, SysdynResource.URIs.Migration); + state.setProperty(MigrationStateKeys.UPDATE_DEPENDENCIES, Boolean.FALSE); - // Read module file - Object result = ImportUtils.readFile(path, handlers); + Resource result = null; + try { + result = MigrationUtils.importMigrated(monitor, SimanticsUI.getSession(), new File(path), state, new DefaultPasteImportAdvisor(model), model); + } catch (Exception e1) { + e1.printStackTrace(); + } - if(result == null || !(result instanceof Resource)) { + if(result == null) { return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Import module failed: Module could not be imported.", null); } else { - final Resource ModuleRoot = (Resource) result; + final Resource ModuleRoot = result; // Check that the imported file actually was a module. Display error message otherwise. try { subTask(monitor, "Validate model"); @@ -415,15 +428,19 @@ public class ImportUtils { // Ensure that shared functions ontology exists ensureSharedOntologies(); + + MigrationState state = MigrationUtils.newState(); + state.setProperty(MigrationStateKeys.BASE_URI, SysdynResource.URIs.Migration); + state.setProperty(MigrationStateKeys.UPDATE_DEPENDENCIES, Boolean.FALSE); - // Handler for importing function libraries - HashMap> handlers = new HashMap>(); - handlers.put("sysdynFunctionLibrary:1", new SysdynImportFormatHandler(functionLibrary, SysdynResource.URIs.from1$6to1$7, monitor, new SysdynFunctionLibraryImportAdvisor(functionLibrary))); - - // Read function library file - Object result = ImportUtils.readFile(path, handlers); + Resource result = null; + try { + result = MigrationUtils.importMigrated(monitor, SimanticsUI.getSession(), new File(path), state, new DefaultPasteImportAdvisor(functionLibrary), functionLibrary); + } catch (Exception e1) { + e1.printStackTrace(); + } - if(result == null || !(result instanceof Resource)) { + if(result == null) { return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Import Function library failed: Function library not be imported.", null); } else { final Resource FunctionLibraryRoot = (Resource) result; diff --git a/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/EnumerationFunction.java b/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/EnumerationFunction.java index a6aab02e..96b687ca 100644 --- a/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/EnumerationFunction.java +++ b/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/EnumerationFunction.java @@ -17,10 +17,10 @@ import java.util.List; import org.simantics.db.Issue; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; +import org.simantics.db.common.issue.StandardIssue; import org.simantics.db.common.utils.ListUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.variable.Variable; -import org.simantics.issues.common.StandardIssue; import org.simantics.scl.reflection.annotations.SCLValue; import org.simantics.sysdyn.SysdynResource; diff --git a/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/ExpressionIssueFunction.java b/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/ExpressionIssueFunction.java index 782fb3cf..8a55a522 100644 --- a/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/ExpressionIssueFunction.java +++ b/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/ExpressionIssueFunction.java @@ -17,10 +17,10 @@ import java.util.List; import org.simantics.db.Issue; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; +import org.simantics.db.common.issue.StandardIssue; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.variable.Variable; import org.simantics.issues.common.IssueUtils; -import org.simantics.issues.common.StandardIssue; import org.simantics.scl.reflection.annotations.SCLValue; import org.simantics.sysdyn.SysdynResource; diff --git a/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/IssueWithStringContext.java b/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/IssueWithStringContext.java index a491add4..906124fb 100644 --- a/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/IssueWithStringContext.java +++ b/simantics-1.10/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/IssueWithStringContext.java @@ -19,10 +19,10 @@ import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.WriteGraph; +import org.simantics.db.common.issue.StandardIssue; import org.simantics.db.common.utils.ListUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.variable.Variable; -import org.simantics.issues.common.StandardIssue; import org.simantics.layer0.Layer0; import org.simantics.sysdyn.SysdynResource; diff --git a/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/IndexVariable.java b/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/IndexVariable.java index f56bc881..7a336dc2 100644 --- a/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/IndexVariable.java +++ b/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/IndexVariable.java @@ -104,8 +104,10 @@ public abstract class IndexVariable extends AbstractPropertyVariable { } @Override public void unregistered() { - unregisterSubscription(subscription); - subscription = null; + if(subscription != null) { + unregisterSubscription(subscription); + subscription = null; + } } @SuppressWarnings("unchecked") diff --git a/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/ValueIndexVariable.java b/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/ValueIndexVariable.java index 9ce2169b..9834ff5d 100644 --- a/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/ValueIndexVariable.java +++ b/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/ValueIndexVariable.java @@ -36,7 +36,8 @@ public class ValueIndexVariable extends IndexVariable { for(int i = 0; i < variableNames.size(); i++) { for(SysdynResult r : results) { if(experiment instanceof SysdynGameExperiment) { - result[i] = ((SysdynGameExperiment)experiment).getCurrentValue(variableNames.get(i)); + Double d = ((SysdynGameExperiment)experiment).getCurrentValue(variableNames.get(i)); + result[i] = d != null ? d : 0; } else { SysdynDataSet ds = r.getDataSet(variableNames.get(i)); if(ds != null && ds.values != null && ds.values.length > 0) { diff --git a/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/VariableValueSubscription.java b/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/VariableValueSubscription.java index 1f918aa7..716fd588 100644 --- a/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/VariableValueSubscription.java +++ b/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/adapter/VariableValueSubscription.java @@ -18,6 +18,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import org.simantics.db.Session; import org.simantics.db.WriteGraph; import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.common.utils.Logger; import org.simantics.db.exception.DatabaseException; import org.simantics.db.procedure.Listener; import org.simantics.db.request.ExternalRead; @@ -48,11 +49,14 @@ public class VariableValueSubscription { return request; } - - public void update() { - T value = variable.getValue(); - fireValue(value); - } + public void update() { + try { + T value = variable.getValue(); + fireValue(value); + } catch (Throwable e) { + fireException(e); + } + } void fireValue(T value) { if (listener != null) @@ -62,8 +66,12 @@ public class VariableValueSubscription { void fireException(Throwable t) { if (listener != null && excepted.compareAndSet(false, true)) listener.exception(t); + else + // Can't invoke listener.exception multiple times, but logging + // further exceptions anyway. + Logger.defaultLogError(t); } - + public void setListener(Listener listener) { this.listener = listener; } diff --git a/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynExperiment.java b/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynExperiment.java index 093baadf..46433abd 100644 --- a/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynExperiment.java +++ b/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynExperiment.java @@ -449,23 +449,18 @@ public class SysdynExperiment extends Experiment implements IDynamicExperiment, */ public synchronized void simulate(final IModelicaMonitor monitor, final IProgressMonitor progressMonitor) throws IOException { canceled = false; - progressMonitor.subTask("Write modelica classes"); // Write Modelica files - - String modelText = getModelicaCode(monitor, false, getOpenModelicaVersion()); if(modelText == null) return; - progressMonitor.worked(1); // Write initial files and add init-parameters progressMonitor.subTask("Write simulation files"); HashMap experimentParameters = getExperimentParameters(monitor); - // add loadFile script to load all related functions and function libraries String additionalScript = getAdditionalScripts(); @@ -473,7 +468,6 @@ public class SysdynExperiment extends Experiment implements IDynamicExperiment, SimulationLocation simulationLocation = createSimulationFiles(sysdynModel, modelText, experimentParameters, additionalScript, false); progressMonitor.worked(1); - // Build the model and store previous model structure and inits that affect the building // If there is no exe file OR the model structure has not changed, no need to build boolean structureChanged = hasStructureChanged(modelText); @@ -501,7 +495,6 @@ public class SysdynExperiment extends Experiment implements IDynamicExperiment, e.printStackTrace(); } } - progressMonitor.worked(1); if(simulationLocation != null && !canceled) { @@ -852,6 +845,17 @@ public class SysdynExperiment extends Experiment implements IDynamicExperiment, subscription.update(); skippedVariableUpdate = false; } + + public int numberOfSimulationRunSteps() { + /* + * 1. Write modelica files + * 2. Write other simulation files + * 3. Build model OR update parameters + * 4. Run modelica + * 5. Read results + */ + return 5; + } /* Experiment methods that are not used in this experiment */ diff --git a/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynGameExperiment.java b/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynGameExperiment.java index dd8ffe26..c3c2e6f0 100644 --- a/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynGameExperiment.java +++ b/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynGameExperiment.java @@ -11,6 +11,10 @@ *******************************************************************************/ package org.simantics.sysdyn.manager; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; @@ -19,10 +23,13 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; +import org.simantics.databoard.Bindings; import org.simantics.db.AsyncReadGraph; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.Session; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; import org.simantics.db.exception.DatabaseException; import org.simantics.db.procedure.AsyncListener; import org.simantics.db.request.Read; @@ -175,13 +182,23 @@ public class SysdynGameExperiment extends SysdynExperiment { SimulationLocation simulationLocation = createSimulationFiles(sysdynModel, modelText, inits, additionalScript, true); progressMonitor.worked(1); - + // Load precompiled fmu if structure has not changed and it has not yet been loaded + File fmu = null; + if(!sysdynModel.isStructureModified()) { + if(!simulationLocation.executableFile.isFile()) { + fmu = loadModelFmu(simulationLocation); + } else { + fmu = simulationLocation.executableFile; + } + } // Build the model and store previous model structure and inits that affect the building // If there is no exe file OR the model structure has not changed, no need to build - if (!simulationLocation.executableFile.isFile() || hasStructureChanged(modelText)) { + if (fmu == null && (!simulationLocation.executableFile.isFile() || hasStructureChanged(modelText))) { progressMonitor.subTask("Build model"); buildModel(simulationLocation, modelText, monitor); previousModelStructure = modelText; + + saveModelFmu(simulationLocation); } progressMonitor.worked(1); @@ -202,6 +219,81 @@ public class SysdynGameExperiment extends SysdynExperiment { simulate(false); } + /** + * Load fmu file from database, if it exists for the model of this experiment + * + * @param simulationLocation SimulationLocation indicating where the fmu should be loaded + * @return Loaded fmu or null if it was not loaded from database + */ + private File loadModelFmu(SimulationLocation simulationLocation) { + File fmu = null; + try { + final String fmuLocation = simulationLocation.executableFile.getAbsolutePath(); + fmu = session.syncRequest(new Read() { + @Override + public File perform(ReadGraph graph) throws DatabaseException { + File result = null; + FileOutputStream fos; + try { + fos = new FileOutputStream(fmuLocation); + byte[] fileBArray = graph.getPossibleRelatedValue( + getModel(), SysdynResource.getInstance(graph).SysdynModel_fmuFile, Bindings.BYTE_ARRAY); + + if(fileBArray != null) { + fos.write(fileBArray); + fos.close(); + result = new File(fmuLocation); + } else { + fos.close(); + return null; + } + + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return result; + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + + return fmu; + } + + /** + * Save fmu file from simulationLocation to database + * @param simulationLocation Location for finding fmu + */ + private void saveModelFmu(SimulationLocation simulationLocation) { + final String fmuLocation = simulationLocation.executableFile.getAbsolutePath(); + session.asyncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph graph) throws DatabaseException { + File file = new File(fmuLocation); + byte[] fileBArray = new byte[(int)file.length()]; + FileInputStream fis; + try { + fis = new FileInputStream(file); + + fis.read(fileBArray); + graph.claimLiteral( + getModel(), + SysdynResource.getInstance(graph).SysdynModel_fmuFile, + fileBArray, Bindings.BYTE_ARRAY); + fis.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + }); + } + @Override public void simulateDuration(double duration) { @@ -414,11 +506,12 @@ public class SysdynGameExperiment extends SysdynExperiment { } public Double getCurrentValue(String name) { - Integer index = subscriptionIndexes.get(name); - if(index != null) { - return currentValues[index]; - } else { - return null; + if(subscriptionIndexes != null && name != null) { + Integer index = subscriptionIndexes.get(name); + if(index != null) { + return currentValues[index]; + } } + return null; } } diff --git a/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynModel.java b/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynModel.java index 55a72243..29f9fc72 100644 --- a/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynModel.java +++ b/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynModel.java @@ -53,6 +53,7 @@ import org.simantics.sysdyn.adapter.VariableValueSubscription; import org.simantics.sysdyn.representation.Configuration; import org.simantics.sysdyn.representation.IElement; import org.simantics.sysdyn.representation.IndependentVariable; +import org.simantics.sysdyn.representation.Model; import org.simantics.sysdyn.representation.Module; import org.simantics.sysdyn.representation.ParameterOverride; import org.simantics.sysdyn.representation.Sheet; @@ -271,10 +272,19 @@ public class SysdynModel implements IMappingListener, IModel, VariableSubscripti */ public synchronized boolean update(ReadGraph graph) throws DatabaseException { if(mapping.isDomainModified()) { - structureModified = true; + + try { - mapping.updateRange(graph); + Collection updated = mapping.updateRange(graph); + + for(Object o : updated) { + if(!(o instanceof Model)) { + setStructureModified(true); + break; + } + } + } catch (MappingException e) { SysdynConsole.INSTANCE.message( "Error: Mapping is broken! Find the problem, " + @@ -305,7 +315,7 @@ public class SysdynModel implements IMappingListener, IModel, VariableSubscripti } else return false; - } + } /** * Update mapping. @@ -560,7 +570,7 @@ public class SysdynModel implements IMappingListener, IModel, VariableSubscripti return structureModified; } - public void setStructureModeified(boolean structureModified) { + public void setStructureModified(boolean structureModified) { this.structureModified = structureModified; } } diff --git a/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynSensitivityAnalysisExperiment.java b/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynSensitivityAnalysisExperiment.java index c7da1528..0d3d096b 100644 --- a/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynSensitivityAnalysisExperiment.java +++ b/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynSensitivityAnalysisExperiment.java @@ -11,148 +11,304 @@ *******************************************************************************/ package org.simantics.sysdyn.manager; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; +import java.util.Random; import java.util.concurrent.ScheduledExecutorService; +import org.eclipse.core.runtime.IProgressMonitor; +import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; -import org.simantics.simulation.experiment.IDynamicExperiment; +import org.simantics.db.common.request.ReadRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.modelica.IModelicaMonitor; +import org.simantics.modelica.ModelicaKeys; +import org.simantics.modelica.ModelicaManager; +import org.simantics.modelica.SimulationLocation; +import org.simantics.modelica.data.CSVSimulationResult; +import org.simantics.modelica.data.MatSimulationResult; +import org.simantics.modelica.data.SimulationResult; +import org.simantics.sysdyn.SysdynResource; /** * Sensitivity analysis experiment * @author Tuomas Miettinen * */ -public class SysdynSensitivityAnalysisExperiment extends SysdynExperiment implements IDynamicExperiment { +public class SysdynSensitivityAnalysisExperiment extends SysdynExperiment { public enum Distribution { UNIFORM, NORMAL } - private final Distribution propabilityDistribution = DEFAULT_PROPABILITY_DISTRIBUTION; + private Distribution propabilityDistribution = DEFAULT_PROPABILITY_DISTRIBUTION; + private double minValue = DEFAULT_MIN_VALUE; + private double maxValue = DEFAULT_MAX_VALUE; + private int numValues = DEFAULT_NUM_VALUES; + private String variedParameter = "Auxiliary1"; + private double mean = DEFAULT_MEAN; + public double stdDeviation = DEFAULT_STD_DEVIATION; + public static Distribution DEFAULT_PROPABILITY_DISTRIBUTION = Distribution.UNIFORM; public static double DEFAULT_MIN_VALUE = 1.0; public static double DEFAULT_MAX_VALUE = 3.0; public static int DEFAULT_NUM_VALUES = 3; - - private final Collection timeListeners = new ArrayList(); + public static double DEFAULT_MEAN = 0.0; + public static double DEFAULT_STD_DEVIATION = 1.0; ScheduledExecutorService playbackExecutionService; - //SensitivityAnalysisConfiguration playbackConfiguration; + private ArrayList results = null; public SysdynSensitivityAnalysisExperiment(Resource experiment, Resource model) { super(experiment, model); } + @Override + protected void runModelica(SimulationLocation simulationLocation, String modelText, IModelicaMonitor monitor, IProgressMonitor progressMonitor, HashMap experimentParameters, HashMap changes) throws IOException { + results = null; + + loadConfiguration(); + if (changes == null) { + changes = new HashMap(); + } + + String version = ModelicaManager.getOMCVersion(simulationLocation.omcHome); + experimentParameters.put(ModelicaManager.OMC_VERSION, version); - /** - * Interrupts a possible ongoing playback - * - * @param time - */ -// public void setTimeInterrupting(double time) { -// stopPlayback(); -// setTime(time); -// } -// -// /** -// * Sets a new time and continues playback from that point if -// * playback was running -// * @param time -// */ -// public void setTimeAndContinue(double time) { -// if(isPlaybackRunning()) { -// stopPlayback(); -// setTime(time); -// startPlayback(500); -// } else { -// setTime(time); -// } -// } -/* - private void setTime(double time) { - this.time = time; - resultsChanged(); - } + for (int i = 0; i < numValues; ++i) { + progressMonitor.subTask("Simulation iteration " + (i+1)); - public double getTime() { - return this.time; - } + double value = 0; - public double getStartTime() { - return this.startTime; - } + if (propabilityDistribution == Distribution.UNIFORM) { + double intervalLength = (maxValue - minValue) / (numValues - 1); + value = minValue + (intervalLength * i); + } else if (propabilityDistribution == Distribution.NORMAL) { + Random random = new Random(); + do { + value = random.nextGaussian() * stdDeviation + mean; + } while (mean > minValue && mean < maxValue && (value < minValue || value > maxValue)); + } else { + break; + } + + // TODO: What if changes already include similarly named variable? + /* If the changes is altered, it affects also to the next simulation. So, + * All the parameters that are to be altered need to be defined explicitly + * before each new simulation. + */ + changes.put(variedParameter, Double.toString(value)); - public double getEndTime() { - return this.endTime; - } - public void setPlaybackDuration(long duration) { - this.playbackDuration = duration; - if(isPlaybackRunning()) { - //Restart playback with different time settings - startPlayback(); + // Specify result file name + + int indexOfDot = simulationLocation.resFile.toString().lastIndexOf('.'); + if (indexOfDot > 1) { + String resFile = simulationLocation.resFile.toString(); + String newResFile = resFile.substring(0, indexOfDot) + i + resFile.substring(indexOfDot); + experimentParameters.put(ModelicaManager.RESULT_FILE_NAME, newResFile); + } + // Simulate the model for one parameter set + runModelica(simulationLocation, modelText, monitor, progressMonitor, experimentParameters, changes, i); + progressMonitor.worked(1); } } - public long getPlaybackDuration() { - return this.playbackDuration; + private void loadConfiguration(){ + try { + session.syncRequest(new ReadRequest() { + @Override + public void run(ReadGraph graph) throws DatabaseException { + + SysdynResource sr = SysdynResource.getInstance(graph); + maxValue = graph.getPossibleRelatedValue(experiment, sr.SensitivityAnalysisExperiment_maxValue, Bindings.DOUBLE); + minValue = graph.getPossibleRelatedValue(experiment, sr.SensitivityAnalysisExperiment_minValue, Bindings.DOUBLE); + numValues = graph.getPossibleRelatedValue(experiment, sr.SensitivityAnalysisExperiment_numValues, Bindings.INTEGER); + variedParameter = graph.getPossibleRelatedValue(experiment, sr.SensitivityAnalysisExperiment_variedParameter, Bindings.STRING); + String propabilityDistributionTemp = graph.getPossibleRelatedValue(experiment, sr.SensitivityAnalysisExperiment_propabilityDistribution, Bindings.STRING); + if (propabilityDistributionTemp.equalsIgnoreCase("uniform")) + propabilityDistribution = Distribution.UNIFORM; + else if (propabilityDistributionTemp.equalsIgnoreCase("normal")) + propabilityDistribution = Distribution.NORMAL; + else + propabilityDistribution = DEFAULT_PROPABILITY_DISTRIBUTION; + + mean = graph.getPossibleRelatedValue(experiment, sr.SensitivityAnalysisExperiment_mean, Bindings.DOUBLE); + stdDeviation = graph.getPossibleRelatedValue(experiment, sr.SensitivityAnalysisExperiment_stdDeviation, Bindings.DOUBLE); + + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } } + + protected void runModelica(SimulationLocation simulationLocation, + String modelText, + IModelicaMonitor monitor, + IProgressMonitor progressMonitor, + HashMap experimentParameters, + HashMap changes, + int resFileIndex) throws IOException { + process = ModelicaManager.runModelica( + simulationLocation, + monitor, + experimentParameters, + changes + ); - @Override - public void init(ReadGraph g) { - super.init(g); - this.session = g.getSession(); - session.asyncRequest(new ReadRequest() { + ModelicaManager.printProcessOutput(process, monitor); - @Override - public void run(ReadGraph graph) throws DatabaseException { - changeState(ExperimentState.RUNNING); - final Resource configuration = graph.getPossibleObject(model, SimulationResource.getInstance(graph).HasConfiguration); - sysdynModel = SysdynModelManager.getInstance(session).getModel(graph, configuration); - toggleActivation(graph, true); - //getPlaybackConfiguration(graph); - startSimulationJob(); - } - }); + File resFile = new File(experimentParameters.get(ModelicaManager.RESULT_FILE_NAME)); + Thread resultThread = getResultThread(resFile, experimentParameters, monitor, progressMonitor); + resultThread.run(); + + process = null; } + + /** + * Get a thread for reading and saving reuslts from a normal simulation + * @param simulationLocation + * @param inits + * @param monitor + * @param progressMonitor + * @param resFileIndex + * @return + */ + protected Thread getResultThread(final File resFile, + final HashMap experimentParameters, + final IModelicaMonitor monitor, + final IProgressMonitor progressMonitor) { + return new Thread() { + @Override + public void run() { + try { + process.waitFor(); + if(!canceled) { + // Get and store results + SimulationResult result; + if(resFile.getName().endsWith(".csv")) + result = new CSVSimulationResult(); + else if(resFile.getName().endsWith(".plt")) + result = new SimulationResult(); + else + result = new MatSimulationResult(); // The latest format + // The interval of results saved. Every result? Every other result? etc... + int outIntervalInt = 1; + String outputInterval = experimentParameters.get(ModelicaKeys.OUTPUT_INTERVAL); + if(outputInterval != null) { + String stepTime = experimentParameters.get(ModelicaKeys.STEP_VALUE); + String stopTime = experimentParameters.get(ModelicaKeys.STOP_VALUE); + + Double step = Double.parseDouble(stepTime); + Double stop = Double.parseDouble(stopTime); + Double outInterval = Double.parseDouble(outputInterval); - private class SensitivityAnalysisConfiguration { - public double simulationDuration, simulationStepLength, intervals, endTime, startTime; - public long playbackDuration; - } + outIntervalInt = (int)getInterval(outInterval, step); + // Actually you might be able to use an outInterval one or two longer. + int maxIntervalInt = (int)Math.round(stop / step); + if (outIntervalInt > maxIntervalInt) + outIntervalInt = maxIntervalInt; + } - @Override - protected void localStateChange() { - super.localStateChange(); - } + result.initRead(resFile); + result.readTime(resFile, outIntervalInt); + //result.readInits(simulationLocation.initFile); // Parameter values are read from .mat + result.filter(); + + MemoryResult currentResult = new MemoryResult(null, null); + getCurrentResults().add(currentResult); + currentResult.setResult(result); + currentResult.setResultFile(resFile); + + resultsChanged(); - // TIME LISTENERS - public void addTimeListener(Runnable timeListener) { - if(!this.timeListeners.contains(timeListener)) - this.timeListeners.add(timeListener); - } + simulate(false); - public Collection getTimeListeners() { - return this.timeListeners; + String errorString = result.getResultReadErrors(); + if(errorString != null && !errorString.isEmpty()) + monitor.message(errorString); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }; } - - public void removeTimeListener(Runnable timeListener) { - this.timeListeners.remove(timeListener); + + public ArrayList getCurrentResults() { + if(this.results == null) { + this.results = new ArrayList(); + } + return this.results; } - + @Override - public void resultsChanged() { - for(Runnable listener : timeListeners) { - listener.run(); + public Collection getActiveResults() { + ArrayList result = new ArrayList(); + result.addAll(getCurrentResults()); + result.addAll(sysdynModel.getDisplayedResults()); + return result; + } + + @Override + public MemoryResult getCurrentResult() { + if (this.results == null || this.results.size() < 1) + return null; + /* There should be a better alternative solution for this. Currently + * the return value is next to nonsense. + */ + return this.results.get(0); + } + + @Override + public void saveState() { + if(results == null || !(results instanceof ArrayList)) + return; + //SaveResultJob saveResultJob = new SaveResultJob(SysdynSensitivityAnalysisExperiment.this, session, results); + //saveResultJob.schedule(); + } + + @Override + public int numberOfSimulationRunSteps() { + /* + * From normal experiment: + * 1. Write modelica files + * 2. Write other simulation files + * 3. Build model OR update parameters + * + * Sensitivity: + * 4 - n. Number of iterations + */ + try { + Integer numberOfIterations = session.syncRequest(new Read() { + @Override + public Integer perform(ReadGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + return graph.getPossibleRelatedValue(experiment, sr.SensitivityAnalysisExperiment_numValues, Bindings.INTEGER); + } + }); + return 3 + numberOfIterations; + } catch (DatabaseException e) { + e.printStackTrace(); } - super.resultsChanged(); + + return super.numberOfSimulationRunSteps(); } -*/ + } diff --git a/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/refactoring/TGRefactoring.java b/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/refactoring/TGRefactoring.java index 0c9a0e53..3e19f43c 100644 --- a/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/refactoring/TGRefactoring.java +++ b/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/refactoring/TGRefactoring.java @@ -45,7 +45,7 @@ public class TGRefactoring { boolean fixed = GraphRefactoringUtils.fixIncorrectRoot(tg1.identities); IdentityStore idStore = TransferableGraphConversion.extractIdentities(tg1); TIntHashSet parentsAffected = new TIntHashSet(); - GraphRefactoringUtils.refactor(idStore, spec, parentsAffected); + GraphRefactoringUtils.refactor(tg1, idStore, spec, parentsAffected); tg1.resourceCount = idStore.getResourceCount(); tg1.identities = idStore.toArray(); // GraphRefactoringUtils.compactify(tg1, parentsAffected); diff --git a/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Sheet.java b/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Sheet.java index 92226cc8..db41a5bb 100644 --- a/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Sheet.java +++ b/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Sheet.java @@ -11,8 +11,10 @@ *******************************************************************************/ package org.simantics.sysdyn.representation; +import gnu.trove.map.hash.THashMap; +import gnu.trove.set.hash.THashSet; + import java.util.ArrayList; -import java.util.HashMap; import java.util.HashSet; import org.simantics.Simantics; @@ -41,8 +43,8 @@ public class Sheet extends org.simantics.sysdyn.representation.Variable { @RelatedElement(Layer0.URIs.PartOf) protected Book book; - HashMap cells = new HashMap(); - HashSet usedRanges = new HashSet(); + THashMap cells = new THashMap(); + THashSet usedRanges = new THashSet(); Resource resource; @@ -52,12 +54,10 @@ public class Sheet extends org.simantics.sysdyn.representation.Variable { @UpdateMethod public boolean updateCells(ReadGraph g, Resource r) throws DatabaseException { - cells.clear(); - usedRanges.clear(); - this.resource = null; - if(g.hasStatement(r)) { this.resource = r; + THashMap newCells = new THashMap(); + g.getObjects(r, Layer0.getInstance(g).ConsistsOf); Variable v = g.adapt(r, Variable.class); for(Variable child : v.getChildren(g)) { @@ -65,14 +65,33 @@ public class Sheet extends org.simantics.sysdyn.representation.Variable { try { SpreadsheetUtils.decodeCellAbsolute(name); Variant value = child.getPropertyValue(g, SheetVariables.CONTENT, Bindings.VARIANT); - cells.put(name, value.getValue()); + newCells.put(name, value.getValue()); } catch (CellParseException e) { } catch (MissingVariableException e) { System.out.println("missing content for: " + name); } } + + boolean update = false; + if(newCells.size() == this.cells.size()) { + // Cells are the same size. There might not be changes. Next up: content + for(String key : this.cells.keySet()) { + if(!this.cells.get(key).equals(newCells.get(key))) { + update = true; + break; + } + } + } else { + update = true; + } + + if(update) { + this.cells = newCells; + this.usedRanges.clear(); + return true; + } } - return true; + return false; } public String getStringRepresentation() { @@ -200,7 +219,7 @@ public class Sheet extends org.simantics.sysdyn.representation.Variable { } - public HashMap getCells() { + public THashMap getCells() { return cells; } diff --git a/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/simulation/SimulationJob.java b/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/simulation/SimulationJob.java index f61c40c1..2823b33e 100644 --- a/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/simulation/SimulationJob.java +++ b/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/simulation/SimulationJob.java @@ -20,7 +20,6 @@ import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.ui.PlatformUI; import org.simantics.modelica.IModelicaMonitor; -import org.simantics.simulation.experiment.Experiment; import org.simantics.sysdyn.manager.SysdynConsole; import org.simantics.sysdyn.manager.SysdynExperiment; import org.simantics.sysdyn.manager.SysdynModel; @@ -28,10 +27,10 @@ import org.simantics.sysdyn.manager.SysdynModel; public class SimulationJob extends Job { private SysdynModel model; - private Experiment experiment; + private SysdynExperiment experiment; private IModelicaMonitor monitor; - public SimulationJob(SysdynModel model, Experiment experiment) { + public SimulationJob(SysdynModel model, SysdynExperiment experiment) { super("Simulate " + model.getConfiguration().getLabel()); this.model = model; this.experiment = experiment; @@ -45,13 +44,14 @@ public class SimulationJob extends Job { @Override protected IStatus run(IProgressMonitor monitor) { - monitor.beginTask("Simulate " + model.getConfiguration().getLabel(), 5); + monitor.beginTask("Simulate " + model.getConfiguration().getLabel(), experiment.numberOfSimulationRunSteps()); this.monitor.message("Simulate " + model.getConfiguration().getLabel()); try { model.update(); - if(experiment instanceof SysdynExperiment) + if(experiment instanceof SysdynExperiment) { ((SysdynExperiment)experiment).simulate(this.monitor, monitor); -// model.simulate(this.monitor, monitor, experiment); + model.setStructureModified(false); + } } catch (Exception e) { e.printStackTrace(); this.monitor.showConsole(); diff --git a/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/simulation/SimulationScheduler.java b/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/simulation/SimulationScheduler.java index eb9ac911..0ee92dc8 100644 --- a/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/simulation/SimulationScheduler.java +++ b/simantics-1.10/org.simantics.sysdyn/src/org/simantics/sysdyn/simulation/SimulationScheduler.java @@ -11,15 +11,15 @@ *******************************************************************************/ package org.simantics.sysdyn.simulation; -import org.simantics.simulation.experiment.Experiment; +import org.simantics.sysdyn.manager.SysdynExperiment; import org.simantics.sysdyn.manager.SysdynModel; public class SimulationScheduler { SysdynModel model; - Experiment experiment; + SysdynExperiment experiment; SimulationJob job; - private SimulationScheduler(SysdynModel model, Experiment experiment) { + private SimulationScheduler(SysdynModel model, SysdynExperiment experiment) { this.model = model; this.experiment = experiment; this.job = new SimulationJob(model, experiment); @@ -29,7 +29,7 @@ public class SimulationScheduler { job.schedule(); } - public static synchronized SimulationScheduler start(SysdynModel model, Experiment experiment) { + public static synchronized SimulationScheduler start(SysdynModel model, SysdynExperiment experiment) { SimulationScheduler scheduler = model.getService(SimulationScheduler.class); if(scheduler == null || !scheduler.experiment.equals(experiment)) { scheduler = new SimulationScheduler(model, experiment);