--- /dev/null
+package org.simantics.simulation.export;\r
+\r
+import java.io.File;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.List;\r
+\r
+import org.eclipse.core.runtime.IPath;\r
+import org.eclipse.core.runtime.Platform;\r
+import org.osgi.service.prefs.Preferences;\r
+import org.simantics.NameLabelUtil;\r
+import org.simantics.databoard.Accessors;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.Datatypes;\r
+import org.simantics.databoard.accessor.Accessor;\r
+import org.simantics.databoard.accessor.BooleanAccessor;\r
+import org.simantics.databoard.accessor.RecordAccessor;\r
+import org.simantics.databoard.accessor.error.AccessorConstructionException;\r
+import org.simantics.databoard.accessor.error.AccessorException;\r
+import org.simantics.databoard.accessor.reference.ChildReference;\r
+import org.simantics.databoard.accessor.reference.LabelReference;\r
+import org.simantics.databoard.binding.mutable.Variant;\r
+import org.simantics.databoard.type.Component;\r
+import org.simantics.databoard.type.Datatype;\r
+import org.simantics.databoard.type.DoubleType;\r
+import org.simantics.databoard.type.RecordType;\r
+import org.simantics.databoard.util.URIUtil;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.request.PossibleObjectWithType;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.export.core.ExportContext;\r
+import org.simantics.export.core.error.ExportException;\r
+import org.simantics.export.core.intf.ExportClass;\r
+import org.simantics.export.core.util.ExportQueries;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.simulation.ontology.SimulationResource;\r
+import org.simantics.utils.strings.AlphanumComparator;\r
+\r
+/**\r
+ * Common mechanism for CSV and Chart exports.\r
+ *\r
+ * @author toni.kalajainen@semantum.fi\r
+ */\r
+public abstract class ExperimentExportClass implements ExportClass {\r
+\r
+ public static ChildReference P_EXPERIMENT = new LabelReference("Experiment"); \r
+ public static ChildReference P_EXPERIMENT_START = ChildReference.parsePath("Experiment/Start Time");\r
+ public static ChildReference P_EXPERIMENT_END = ChildReference.parsePath("Experiment/End Time"); \r
+\r
+ public RecordType options(ExportContext context, Collection<String> content) \r
+ throws ExportException \r
+ {\r
+ RecordType options;\r
+ RecordType experimentOptions;\r
+ \r
+ Datatype second = new DoubleType("s");\r
+\r
+ experimentOptions = new RecordType();\r
+ experimentOptions.addComponent("Start Time", second);\r
+ experimentOptions.addComponent("End Time", second);\r
+ \r
+ try {\r
+ List<Resource> models = context.session.syncRequest( ExportQueries.toModels(content) );\r
+ for (Resource model : models) {\r
+ List<Resource> runs = context.session.syncRequest( getExperimentRuns(model) );\r
+ \r
+ String modelLabel = context.session.syncRequest( ExportQueries.label( model ) );\r
+ if ( modelLabel==null ) continue;\r
+ \r
+ List<String> runLabels = new ArrayList<String>();\r
+ for ( Resource run : runs ) {\r
+ String runLabel = context.session.syncRequest( getRunLabel(run) );\r
+ if ( runLabel == null ) continue;\r
+ runLabels.add(runLabel);\r
+ } \r
+ \r
+ Collections.sort( runLabels, AlphanumComparator.CASE_INSENSITIVE_COMPARATOR );\r
+ \r
+ RecordType modelRunSelection = new RecordType();\r
+ modelRunSelection.metadata.put("style", "dialog");\r
+ for ( String runLabel : runLabels ) {\r
+ modelRunSelection.addComponent(runLabel, Datatypes.BOOLEAN);\r
+ } \r
+ \r
+ experimentOptions.addComponent(modelLabel+", experiment runs", modelRunSelection);\r
+ }\r
+ } catch (DatabaseException e) {\r
+ throw new ExportException( e );\r
+ }\r
+ \r
+ options = new RecordType();\r
+ options.addComponent("Experiment", experimentOptions);\r
+ \r
+ return options;\r
+ }\r
+\r
+ public void fillDefaultPrefs(final ExportContext ctx, final Variant options) throws ExportException {\r
+ \r
+ try {\r
+ RecordAccessor ra = Accessors.getAccessor(options);\r
+ \r
+ ra.setValue(P_EXPERIMENT_END, Bindings.DOUBLE, 86400.0);\r
+ \r
+ } catch (AccessorConstructionException e) {\r
+ throw new ExportException(e);\r
+ } catch (AccessorException e) {\r
+ throw new ExportException(e);\r
+ }\r
+ \r
+ // Select the most latest experiments\r
+ try {\r
+ Accessor ra = Accessors.getAccessor( options );\r
+ ra = ra.getComponent( P_EXPERIMENT );\r
+ for (ModelRef modelRef : getResult(ctx, options, false)) {\r
+ for (ExperimentRef experimentRef : modelRef.experiments) {\r
+ for (RunRef runRef : experimentRef.runs) {\r
+ if ( runRef.isActive ) {\r
+ try {\r
+ BooleanAccessor ba = ra.getComponent(runRef.optionsRef);\r
+ ba.setValue(true);\r
+ } catch(AccessorConstructionException ae) {}\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+ } catch (AccessorConstructionException e) {\r
+ throw new ExportException(e);\r
+ } catch (AccessorException e) {\r
+ throw new ExportException(e);\r
+ } catch (DatabaseException e1) {\r
+ throw new ExportException( e1 );\r
+ }\r
+\r
+ \r
+ }\r
+\r
+ public void savePref(Variant options, Preferences contentScopeNode, Preferences workbenchScopeNode) throws ExportException {\r
+ try {\r
+ RecordAccessor ra = Accessors.getAccessor(options);\r
+ \r
+ Double startTime = (Double) ra.getValue(P_EXPERIMENT_START, Bindings.DOUBLE );\r
+ if ( startTime != null ) contentScopeNode.putDouble(P_EXPERIMENT_START.tail().toString(), startTime); \r
+\r
+ Double endTime = (Double) ra.getValue(P_EXPERIMENT_END, Bindings.DOUBLE );\r
+ if ( endTime != null ) contentScopeNode.putDouble(P_EXPERIMENT_END.tail().toString(), endTime); \r
+ \r
+ } catch (AccessorConstructionException e) {\r
+ throw new ExportException(e);\r
+ } catch (AccessorException e) {\r
+ throw new ExportException(e);\r
+ } \r
+ }\r
+\r
+ public void loadPref(Variant options, Preferences contentScopeNode, Preferences workbenchScopeNode) throws ExportException {\r
+ try {\r
+ RecordAccessor ra = Accessors.getAccessor(options);\r
+ \r
+ double startTime = contentScopeNode.getDouble(P_EXPERIMENT_START.tail().toString(), -Double.MAX_VALUE); \r
+ if ( startTime != -Double.MAX_VALUE ) ra.setValue(P_EXPERIMENT_START, Bindings.DOUBLE, startTime ); \r
+ \r
+ double endTime = contentScopeNode.getDouble(P_EXPERIMENT_END.tail().toString(), -Double.MAX_VALUE); \r
+ if ( endTime != -Double.MAX_VALUE ) ra.setValue(P_EXPERIMENT_END, Bindings.DOUBLE, endTime ); \r
+ \r
+ } catch (AccessorConstructionException e) {\r
+ throw new ExportException(e);\r
+ } catch (AccessorException e) {\r
+ throw new ExportException(e);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Get a request that returns experiments runs in format of \r
+ * "Experiment\Experiment Runs". \r
+ * \r
+ * @param model\r
+ * @return\r
+ */\r
+ public static Read<List<Resource>> getExperimentRuns(final Resource model) {\r
+ return new Read<List<Resource>>() {\r
+ @Override\r
+ public List<Resource> perform(ReadGraph graph) throws DatabaseException {\r
+ List<Resource> result = new ArrayList<Resource>();\r
+ \r
+ Layer0 b = Layer0.getInstance(graph);\r
+ SimulationResource SIMU = SimulationResource.getInstance(graph);\r
+ for (Resource config : graph.getObjects(model, b.ConsistsOf)) {\r
+ if (graph.isInstanceOf(config, SIMU.Experiment)) {\r
+ for (Resource run : graph.getObjects(config, b.ConsistsOf)) {\r
+ if (graph.isInstanceOf(run, SIMU.Run)) {\r
+ result.add( run );\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return result;\r
+ }\r
+ }; \r
+ }\r
+ \r
+ /**\r
+ * Returns a label in format of "Experiment\Run"\r
+ * \r
+ * @param run\r
+ * @return the label or null \r
+ */\r
+ public static Read<String> getRunLabel(final Resource run) {\r
+ return new Read<String>() {\r
+ @Override\r
+ public String perform(ReadGraph graph) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ SimulationResource SIMU = SimulationResource.getInstance(graph);\r
+ Resource experiment = graph.syncRequest( new PossibleObjectWithType(run, L0.PartOf, SIMU.Experiment) );\r
+ if ( experiment == null ) return null;\r
+ \r
+ String experimentLabel = NameLabelUtil.modalName(graph, experiment);\r
+ String runLabel = NameLabelUtil.modalName(graph, run);\r
+ \r
+ if ( experimentLabel == null || runLabel == null ) return null;\r
+ \r
+ return experimentLabel+"\\"+runLabel;\r
+ }\r
+ };\r
+ }\r
+ \r
+ /**\r
+ * Get Run resource using a label "Experiment\Run"\r
+ * \r
+ * @param model\r
+ * @param runLabel\r
+ * @return resource\r
+ */\r
+ public static Read<Resource> getRunByLabel(final Resource model, final String runLabel) {\r
+ return new Read<Resource>() {\r
+ @Override\r
+ public Resource perform(ReadGraph graph) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ SimulationResource SIMU = SimulationResource.getInstance(graph);\r
+\r
+ for (Resource config : graph.getObjects(model, L0.ConsistsOf)) {\r
+ if (graph.isInstanceOf(config, SIMU.Experiment)) {\r
+ String experimentLabel = NameLabelUtil.modalName(graph, config);\r
+ if ( experimentLabel == null ) continue;\r
+ if ( !runLabel.startsWith(experimentLabel) ) continue;\r
+ for (Resource run : graph.getObjects(config, L0.ConsistsOf)) {\r
+ if (graph.isInstanceOf(run, SIMU.Run)) {\r
+ String lbl2 = NameLabelUtil.modalName(graph, run);\r
+ if ( lbl2 == null ) continue;\r
+ if ( runLabel.equals( experimentLabel+"\\"+lbl2 ) ) return run;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+ }; \r
+ }\r
+ \r
+ public static Read<List<Resource>> getChildByLabelAndType(final Resource subject, final Resource type, final String label)\r
+ {\r
+ return new Read<List<Resource>>() {\r
+ @Override\r
+ public List<Resource> perform(ReadGraph graph) throws DatabaseException {\r
+ List<Resource> result = new ArrayList<Resource>();\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ for ( Resource child : graph.getObjects(subject, L0.ConsistsOf )) {\r
+ if ( !graph.isInstanceOf(child, type) ) continue;\r
+ String lbl = NameLabelUtil.modalName(graph, child);\r
+ if ( lbl==null ) continue;\r
+ if ( lbl.equals(label)) result.add( child );\r
+ }\r
+ return result;\r
+ }\r
+ };\r
+ }\r
+\r
+ /**\r
+ * Read Model/Experiment/Run from options\r
+ * \r
+ * @param ctx\r
+ * @param optionsBinding\r
+ * @param options\r
+ * @param returnOnlyEnabledInOptions\r
+ * @return\r
+ * @throws DatabaseException \r
+ */\r
+ public static List<ModelRef> getResult(final ExportContext ctx, final Variant options, final boolean returnOnlyEnabledInOptions) throws DatabaseException {\r
+\r
+ return ctx.session.syncRequest( new Read<List<ModelRef>>() {\r
+ @Override\r
+ public List<ModelRef> perform(ReadGraph graph) throws DatabaseException {\r
+ try {\r
+ List<ModelRef> result = new ArrayList<ModelRef>();\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ SimulationResource SIMU = SimulationResource.getInstance(graph);\r
+ \r
+ Resource project = graph.getResource( ctx.project );\r
+ Accessor ra = Accessors.getAccessor(options);\r
+ ra = ra.getComponent(P_EXPERIMENT);\r
+ \r
+ RecordType type = (RecordType)((RecordType) options.type()).getComponentType("Experiment");\r
+ if ( type != null ) {\r
+ for ( Component c : type.getComponents() ) {\r
+ int endIndex = c.name.length() - ", experiment runs".length();\r
+ if ( endIndex <= 0 ) continue;\r
+ String modelName = c.name.substring(0, endIndex);\r
+ if ( modelName.isEmpty() ) continue;\r
+ List<Resource> models = graph.syncRequest( getChildByLabelAndType(project, SIMU.Model, modelName) );\r
+ for (Resource model : models ) {\r
+ ModelRef modelRef = new ModelRef();\r
+ modelRef.resource = model;\r
+ modelRef.label = modelName;\r
+ modelRef.uri = graph.getURI(model);\r
+ \r
+ if ( c.type instanceof RecordType == false ) continue;\r
+ RecordType rt = (RecordType) c.type;\r
+ for (Component cc : rt.getComponents()) {\r
+ String pp = cc.name;\r
+ String[] parts = pp.split("\\\\");\r
+ if ( parts.length!=2 ) continue;\r
+ String experimentLabel = parts[0];\r
+ String runLabel = parts[1];\r
+ \r
+ for ( Resource experiment : graph.syncRequest( getChildByLabelAndType(model, SIMU.Experiment, experimentLabel) ) )\r
+ {\r
+ ExperimentRef experimentRef = new ExperimentRef();\r
+ experimentRef.resource = experiment;\r
+ experimentRef.label = experimentLabel;\r
+ experimentRef.uri = graph.getURI(experiment);\r
+ \r
+ for ( Resource run : graph.syncRequest( getChildByLabelAndType(experiment, SIMU.Run, runLabel) ) ) \r
+ {\r
+ RunRef runRef = new RunRef(); \r
+ runRef.optionsRef = new LabelReference(c.name, new LabelReference(experimentLabel+"\\"+runLabel));;\r
+ try {\r
+ BooleanAccessor ba = ra.getComponent( runRef.optionsRef );\r
+ runRef.isEnabled = ba.getValue();\r
+ if ( !runRef.isEnabled && returnOnlyEnabledInOptions ) continue;\r
+ } catch (AccessorException e) {\r
+ if ( returnOnlyEnabledInOptions ) continue;\r
+ }\r
+ runRef.resource = run;\r
+ runRef.label = runLabel;\r
+ runRef.uri = graph.getURI(run);\r
+ runRef.isActive = graph.hasStatement(run, SIMU.IsActive);\r
+ runRef.identifier = graph.getRelatedValue(run, L0.HasName, Bindings.STRING); \r
+ runRef.historyFolder = getExperimentDirectory(modelRef.resource, experimentRef.resource, "result-" + runRef.identifier);\r
+ experimentRef.runs.add(runRef);\r
+ }\r
+ \r
+ if ( !experimentRef.runs.isEmpty() ) modelRef.experiments.add(experimentRef);\r
+ }\r
+ \r
+ }\r
+ \r
+ if ( !modelRef.experiments.isEmpty() ) result.add( modelRef );\r
+ }\r
+ }\r
+ }\r
+ \r
+ return result;\r
+ } catch (AccessorConstructionException e) {\r
+ throw new DatabaseException( e );\r
+ }\r
+ }});\r
+ }\r
+ \r
+ public static ModelRef getModelRefByResource(List<ModelRef> modelRefs, Resource model) {\r
+ for (ModelRef modelRef : modelRefs) if ( modelRef.resource.equals(model) ) return modelRef;\r
+ return null;\r
+ }\r
+ \r
+ public static File getExperimentDirectory(Resource model, Resource experiment, String... subdirs) throws DatabaseException {\r
+ String[] dirs = new String[4 + subdirs.length];\r
+ dirs[0] = "resources";\r
+ dirs[1] = "model-" + model.getResourceId();\r
+ dirs[2] = "experiments";\r
+ dirs[3] = "" + experiment.getResourceId();\r
+ System.arraycopy(subdirs, 0, dirs, 4, subdirs.length);\r
+\r
+ return getWorkspacePath(false, dirs);\r
+ }\r
+ \r
+ /**\r
+ * @param escapeNames <code>true</code> to run each path segment through\r
+ * {@link URIUtil#encodeFilename(String)}\r
+ * @param relativeSegments path segments to append to the workspace root\r
+ * path\r
+ * @return the designated path within the workspace\r
+ */\r
+ public static File getWorkspacePath(boolean escapeNames, String... relativeSegments) {\r
+ IPath finalPath = Platform.getLocation();\r
+ for (int i = 0; i < relativeSegments.length; ++i)\r
+ finalPath = finalPath.append(escapeNames ? URIUtil.encodeFilename(relativeSegments[i]) : relativeSegments[i]);\r
+\r
+ return finalPath.toFile();\r
+ } \r
+ \r
+ /**\r
+ * @return the workspace root path as a File\r
+ */\r
+ public static File getWorkspacePath() {\r
+ return getWorkspacePath(false);\r
+ }\r
+ \r
+ \r
+ public static class ModelRef {\r
+ public String uri;\r
+ public Resource resource;\r
+ public String label;\r
+ public List<ExperimentRef> experiments = new ArrayList<ExperimentRef>();\r
+ \r
+ public int runCount() {\r
+ int count = 0;\r
+ for ( ExperimentRef er : experiments ) count += er.runs.size();\r
+ return count;\r
+ }\r
+ \r
+ public int enabledRunCount() {\r
+ int count = 0;\r
+ for ( ExperimentRef er : experiments ) count += er.enabledRunCount();\r
+ return count;\r
+ }\r
+ \r
+ public List<RunRef> getRunRefs() {\r
+ List<RunRef> result = new ArrayList<RunRef>();\r
+ for ( ExperimentRef er : experiments ) result.addAll( er.runs );\r
+ return result;\r
+ }\r
+ \r
+ }\r
+ \r
+ public static class ExperimentRef {\r
+ public String uri;\r
+ public Resource resource;\r
+ public String label;\r
+ public List<RunRef> runs = new ArrayList<RunRef>();\r
+ \r
+ public int enabledRunCount() {\r
+ int count = 0;\r
+ for ( RunRef rr : runs ) if ( rr.isEnabled ) count++;\r
+ return count;\r
+ }\r
+ }\r
+ \r
+ public static class RunRef { \r
+ public String uri;\r
+ public Resource resource;\r
+ public String label;\r
+ public ChildReference optionsRef;\r
+ public boolean isActive;\r
+ public boolean isEnabled;\r
+ public File historyFolder;\r
+ public String identifier;\r
+ }\r
+ \r
+}\r