1 package org.simantics.simulation.export;
\r
4 import java.util.ArrayList;
\r
5 import java.util.Collection;
\r
6 import java.util.Collections;
\r
7 import java.util.List;
\r
9 import org.eclipse.core.runtime.IPath;
\r
10 import org.eclipse.core.runtime.Platform;
\r
11 import org.osgi.service.prefs.Preferences;
\r
12 import org.simantics.NameLabelUtil;
\r
13 import org.simantics.databoard.Accessors;
\r
14 import org.simantics.databoard.Bindings;
\r
15 import org.simantics.databoard.Datatypes;
\r
16 import org.simantics.databoard.accessor.Accessor;
\r
17 import org.simantics.databoard.accessor.BooleanAccessor;
\r
18 import org.simantics.databoard.accessor.RecordAccessor;
\r
19 import org.simantics.databoard.accessor.error.AccessorConstructionException;
\r
20 import org.simantics.databoard.accessor.error.AccessorException;
\r
21 import org.simantics.databoard.accessor.reference.ChildReference;
\r
22 import org.simantics.databoard.accessor.reference.LabelReference;
\r
23 import org.simantics.databoard.binding.mutable.Variant;
\r
24 import org.simantics.databoard.type.Component;
\r
25 import org.simantics.databoard.type.Datatype;
\r
26 import org.simantics.databoard.type.DoubleType;
\r
27 import org.simantics.databoard.type.RecordType;
\r
28 import org.simantics.databoard.util.URIUtil;
\r
29 import org.simantics.db.ReadGraph;
\r
30 import org.simantics.db.Resource;
\r
31 import org.simantics.db.common.request.PossibleObjectWithType;
\r
32 import org.simantics.db.exception.DatabaseException;
\r
33 import org.simantics.db.request.Read;
\r
34 import org.simantics.export.core.ExportContext;
\r
35 import org.simantics.export.core.error.ExportException;
\r
36 import org.simantics.export.core.intf.ExportClass;
\r
37 import org.simantics.export.core.util.ExportQueries;
\r
38 import org.simantics.layer0.Layer0;
\r
39 import org.simantics.simulation.ontology.SimulationResource;
\r
40 import org.simantics.utils.strings.AlphanumComparator;
\r
43 * Common mechanism for CSV and Chart exports.
\r
45 * @author toni.kalajainen@semantum.fi
\r
47 public abstract class ExperimentExportClass implements ExportClass {
\r
49 public static ChildReference P_EXPERIMENT = new LabelReference("Experiment");
\r
50 public static ChildReference P_EXPERIMENT_START = ChildReference.parsePath("Experiment/Start Time");
\r
51 public static ChildReference P_EXPERIMENT_END = ChildReference.parsePath("Experiment/End Time");
\r
53 public RecordType options(ExportContext context, Collection<String> content)
\r
54 throws ExportException
\r
57 RecordType experimentOptions;
\r
59 Datatype second = new DoubleType("s");
\r
61 experimentOptions = new RecordType();
\r
62 experimentOptions.addComponent("Start Time", second);
\r
63 experimentOptions.addComponent("End Time", second);
\r
66 List<Resource> models = context.session.syncRequest( ExportQueries.toModels(content) );
\r
67 for (Resource model : models) {
\r
68 List<Resource> runs = context.session.syncRequest( getExperimentRuns(model) );
\r
70 String modelLabel = context.session.syncRequest( ExportQueries.label( model ) );
\r
71 if ( modelLabel==null ) continue;
\r
73 List<String> runLabels = new ArrayList<String>();
\r
74 for ( Resource run : runs ) {
\r
75 String runLabel = context.session.syncRequest( getRunLabel(run) );
\r
76 if ( runLabel == null ) continue;
\r
77 runLabels.add(runLabel);
\r
80 Collections.sort( runLabels, AlphanumComparator.CASE_INSENSITIVE_COMPARATOR );
\r
82 RecordType modelRunSelection = new RecordType();
\r
83 modelRunSelection.metadata.put("style", "dialog");
\r
84 for ( String runLabel : runLabels ) {
\r
85 modelRunSelection.addComponent(runLabel, Datatypes.BOOLEAN);
\r
88 experimentOptions.addComponent(modelLabel+", experiment runs", modelRunSelection);
\r
90 } catch (DatabaseException e) {
\r
91 throw new ExportException( e );
\r
94 options = new RecordType();
\r
95 options.addComponent("Experiment", experimentOptions);
\r
100 public void fillDefaultPrefs(final ExportContext ctx, final Variant options) throws ExportException {
\r
103 RecordAccessor ra = Accessors.getAccessor(options);
\r
105 ra.setValue(P_EXPERIMENT_END, Bindings.DOUBLE, 86400.0);
\r
107 } catch (AccessorConstructionException e) {
\r
108 throw new ExportException(e);
\r
109 } catch (AccessorException e) {
\r
110 throw new ExportException(e);
\r
113 // Select the most latest experiments
\r
115 Accessor ra = Accessors.getAccessor( options );
\r
116 ra = ra.getComponent( P_EXPERIMENT );
\r
117 for (ModelRef modelRef : getResult(ctx, options, false)) {
\r
118 for (ExperimentRef experimentRef : modelRef.experiments) {
\r
119 for (RunRef runRef : experimentRef.runs) {
\r
120 if ( runRef.isActive ) {
\r
122 BooleanAccessor ba = ra.getComponent(runRef.optionsRef);
\r
124 } catch(AccessorConstructionException ae) {}
\r
130 } catch (AccessorConstructionException e) {
\r
131 throw new ExportException(e);
\r
132 } catch (AccessorException e) {
\r
133 throw new ExportException(e);
\r
134 } catch (DatabaseException e1) {
\r
135 throw new ExportException( e1 );
\r
141 public void savePref(Variant options, Preferences contentScopeNode, Preferences workbenchScopeNode) throws ExportException {
\r
143 RecordAccessor ra = Accessors.getAccessor(options);
\r
145 Double startTime = (Double) ra.getValue(P_EXPERIMENT_START, Bindings.DOUBLE );
\r
146 if ( startTime != null ) contentScopeNode.putDouble(P_EXPERIMENT_START.tail().toString(), startTime);
\r
148 Double endTime = (Double) ra.getValue(P_EXPERIMENT_END, Bindings.DOUBLE );
\r
149 if ( endTime != null ) contentScopeNode.putDouble(P_EXPERIMENT_END.tail().toString(), endTime);
\r
151 } catch (AccessorConstructionException e) {
\r
152 throw new ExportException(e);
\r
153 } catch (AccessorException e) {
\r
154 throw new ExportException(e);
\r
158 public void loadPref(Variant options, Preferences contentScopeNode, Preferences workbenchScopeNode) throws ExportException {
\r
160 RecordAccessor ra = Accessors.getAccessor(options);
\r
162 double startTime = contentScopeNode.getDouble(P_EXPERIMENT_START.tail().toString(), -Double.MAX_VALUE);
\r
163 if ( startTime != -Double.MAX_VALUE ) ra.setValue(P_EXPERIMENT_START, Bindings.DOUBLE, startTime );
\r
165 double endTime = contentScopeNode.getDouble(P_EXPERIMENT_END.tail().toString(), -Double.MAX_VALUE);
\r
166 if ( endTime != -Double.MAX_VALUE ) ra.setValue(P_EXPERIMENT_END, Bindings.DOUBLE, endTime );
\r
168 } catch (AccessorConstructionException e) {
\r
169 throw new ExportException(e);
\r
170 } catch (AccessorException e) {
\r
171 throw new ExportException(e);
\r
176 * Get a request that returns experiments runs in format of
\r
177 * "Experiment\Experiment Runs".
\r
182 public static Read<List<Resource>> getExperimentRuns(final Resource model) {
\r
183 return new Read<List<Resource>>() {
\r
185 public List<Resource> perform(ReadGraph graph) throws DatabaseException {
\r
186 List<Resource> result = new ArrayList<Resource>();
\r
188 Layer0 b = Layer0.getInstance(graph);
\r
189 SimulationResource SIMU = SimulationResource.getInstance(graph);
\r
190 for (Resource config : graph.getObjects(model, b.ConsistsOf)) {
\r
191 if (graph.isInstanceOf(config, SIMU.Experiment)) {
\r
192 for (Resource run : graph.getObjects(config, b.ConsistsOf)) {
\r
193 if (graph.isInstanceOf(run, SIMU.Run)) {
\r
205 * Returns a label in format of "Experiment\Run"
\r
208 * @return the label or null
\r
210 public static Read<String> getRunLabel(final Resource run) {
\r
211 return new Read<String>() {
\r
213 public String perform(ReadGraph graph) throws DatabaseException {
\r
214 Layer0 L0 = Layer0.getInstance(graph);
\r
215 SimulationResource SIMU = SimulationResource.getInstance(graph);
\r
216 Resource experiment = graph.syncRequest( new PossibleObjectWithType(run, L0.PartOf, SIMU.Experiment) );
\r
217 if ( experiment == null ) return null;
\r
219 String experimentLabel = NameLabelUtil.modalName(graph, experiment);
\r
220 String runLabel = NameLabelUtil.modalName(graph, run);
\r
222 if ( experimentLabel == null || runLabel == null ) return null;
\r
224 return experimentLabel+"\\"+runLabel;
\r
230 * Get Run resource using a label "Experiment\Run"
\r
236 public static Read<Resource> getRunByLabel(final Resource model, final String runLabel) {
\r
237 return new Read<Resource>() {
\r
239 public Resource perform(ReadGraph graph) throws DatabaseException {
\r
240 Layer0 L0 = Layer0.getInstance(graph);
\r
241 SimulationResource SIMU = SimulationResource.getInstance(graph);
\r
243 for (Resource config : graph.getObjects(model, L0.ConsistsOf)) {
\r
244 if (graph.isInstanceOf(config, SIMU.Experiment)) {
\r
245 String experimentLabel = NameLabelUtil.modalName(graph, config);
\r
246 if ( experimentLabel == null ) continue;
\r
247 if ( !runLabel.startsWith(experimentLabel) ) continue;
\r
248 for (Resource run : graph.getObjects(config, L0.ConsistsOf)) {
\r
249 if (graph.isInstanceOf(run, SIMU.Run)) {
\r
250 String lbl2 = NameLabelUtil.modalName(graph, run);
\r
251 if ( lbl2 == null ) continue;
\r
252 if ( runLabel.equals( experimentLabel+"\\"+lbl2 ) ) return run;
\r
262 public static Read<List<Resource>> getChildByLabelAndType(final Resource subject, final Resource type, final String label)
\r
264 return new Read<List<Resource>>() {
\r
266 public List<Resource> perform(ReadGraph graph) throws DatabaseException {
\r
267 List<Resource> result = new ArrayList<Resource>();
\r
268 Layer0 L0 = Layer0.getInstance(graph);
\r
269 for ( Resource child : graph.getObjects(subject, L0.ConsistsOf )) {
\r
270 if ( !graph.isInstanceOf(child, type) ) continue;
\r
271 String lbl = NameLabelUtil.modalName(graph, child);
\r
272 if ( lbl==null ) continue;
\r
273 if ( lbl.equals(label)) result.add( child );
\r
281 * Read Model/Experiment/Run from options
\r
284 * @param optionsBinding
\r
286 * @param returnOnlyEnabledInOptions
\r
288 * @throws DatabaseException
\r
290 public static List<ModelRef> getResult(final ExportContext ctx, final Variant options, final boolean returnOnlyEnabledInOptions) throws DatabaseException {
\r
292 return ctx.session.syncRequest( new Read<List<ModelRef>>() {
\r
294 public List<ModelRef> perform(ReadGraph graph) throws DatabaseException {
\r
296 List<ModelRef> result = new ArrayList<ModelRef>();
\r
297 Layer0 L0 = Layer0.getInstance(graph);
\r
298 SimulationResource SIMU = SimulationResource.getInstance(graph);
\r
300 Resource project = graph.getResource( ctx.project );
\r
301 Accessor ra = Accessors.getAccessor(options);
\r
302 ra = ra.getComponent(P_EXPERIMENT);
\r
304 RecordType type = (RecordType)((RecordType) options.type()).getComponentType("Experiment");
\r
305 if ( type != null ) {
\r
306 for ( Component c : type.getComponents() ) {
\r
307 int endIndex = c.name.length() - ", experiment runs".length();
\r
308 if ( endIndex <= 0 ) continue;
\r
309 String modelName = c.name.substring(0, endIndex);
\r
310 if ( modelName.isEmpty() ) continue;
\r
311 List<Resource> models = graph.syncRequest( getChildByLabelAndType(project, SIMU.Model, modelName) );
\r
312 for (Resource model : models ) {
\r
313 ModelRef modelRef = new ModelRef();
\r
314 modelRef.resource = model;
\r
315 modelRef.label = modelName;
\r
316 modelRef.uri = graph.getURI(model);
\r
318 if ( c.type instanceof RecordType == false ) continue;
\r
319 RecordType rt = (RecordType) c.type;
\r
320 for (Component cc : rt.getComponents()) {
\r
321 String pp = cc.name;
\r
322 String[] parts = pp.split("\\\\");
\r
323 if ( parts.length!=2 ) continue;
\r
324 String experimentLabel = parts[0];
\r
325 String runLabel = parts[1];
\r
327 for ( Resource experiment : graph.syncRequest( getChildByLabelAndType(model, SIMU.Experiment, experimentLabel) ) )
\r
329 ExperimentRef experimentRef = new ExperimentRef();
\r
330 experimentRef.resource = experiment;
\r
331 experimentRef.label = experimentLabel;
\r
332 experimentRef.uri = graph.getURI(experiment);
\r
334 for ( Resource run : graph.syncRequest( getChildByLabelAndType(experiment, SIMU.Run, runLabel) ) )
\r
336 RunRef runRef = new RunRef();
\r
337 runRef.optionsRef = new LabelReference(c.name, new LabelReference(experimentLabel+"\\"+runLabel));;
\r
339 BooleanAccessor ba = ra.getComponent( runRef.optionsRef );
\r
340 runRef.isEnabled = ba.getValue();
\r
341 if ( !runRef.isEnabled && returnOnlyEnabledInOptions ) continue;
\r
342 } catch (AccessorException e) {
\r
343 if ( returnOnlyEnabledInOptions ) continue;
\r
345 runRef.resource = run;
\r
346 runRef.label = runLabel;
\r
347 runRef.uri = graph.getURI(run);
\r
348 runRef.isActive = graph.hasStatement(run, SIMU.IsActive);
\r
349 runRef.identifier = graph.getRelatedValue(run, L0.HasName, Bindings.STRING);
\r
350 runRef.historyFolder = getExperimentDirectory(modelRef.resource, experimentRef.resource, "result-" + runRef.identifier);
\r
351 experimentRef.runs.add(runRef);
\r
354 if ( !experimentRef.runs.isEmpty() ) modelRef.experiments.add(experimentRef);
\r
359 if ( !modelRef.experiments.isEmpty() ) result.add( modelRef );
\r
365 } catch (AccessorConstructionException e) {
\r
366 throw new DatabaseException( e );
\r
371 public static ModelRef getModelRefByResource(List<ModelRef> modelRefs, Resource model) {
\r
372 for (ModelRef modelRef : modelRefs) if ( modelRef.resource.equals(model) ) return modelRef;
\r
376 public static File getExperimentDirectory(Resource model, Resource experiment, String... subdirs) throws DatabaseException {
\r
377 String[] dirs = new String[4 + subdirs.length];
\r
378 dirs[0] = "resources";
\r
379 dirs[1] = "model-" + model.getResourceId();
\r
380 dirs[2] = "experiments";
\r
381 dirs[3] = "" + experiment.getResourceId();
\r
382 System.arraycopy(subdirs, 0, dirs, 4, subdirs.length);
\r
384 return getWorkspacePath(false, dirs);
\r
388 * @param escapeNames <code>true</code> to run each path segment through
\r
389 * {@link URIUtil#encodeFilename(String)}
\r
390 * @param relativeSegments path segments to append to the workspace root
\r
392 * @return the designated path within the workspace
\r
394 public static File getWorkspacePath(boolean escapeNames, String... relativeSegments) {
\r
395 IPath finalPath = Platform.getLocation();
\r
396 for (int i = 0; i < relativeSegments.length; ++i)
\r
397 finalPath = finalPath.append(escapeNames ? URIUtil.encodeFilename(relativeSegments[i]) : relativeSegments[i]);
\r
399 return finalPath.toFile();
\r
403 * @return the workspace root path as a File
\r
405 public static File getWorkspacePath() {
\r
406 return getWorkspacePath(false);
\r
410 public static class ModelRef {
\r
412 public Resource resource;
\r
413 public String label;
\r
414 public List<ExperimentRef> experiments = new ArrayList<ExperimentRef>();
\r
416 public int runCount() {
\r
418 for ( ExperimentRef er : experiments ) count += er.runs.size();
\r
422 public int enabledRunCount() {
\r
424 for ( ExperimentRef er : experiments ) count += er.enabledRunCount();
\r
428 public List<RunRef> getRunRefs() {
\r
429 List<RunRef> result = new ArrayList<RunRef>();
\r
430 for ( ExperimentRef er : experiments ) result.addAll( er.runs );
\r
436 public static class ExperimentRef {
\r
438 public Resource resource;
\r
439 public String label;
\r
440 public List<RunRef> runs = new ArrayList<RunRef>();
\r
442 public int enabledRunCount() {
\r
444 for ( RunRef rr : runs ) if ( rr.isEnabled ) count++;
\r
449 public static class RunRef {
\r
451 public Resource resource;
\r
452 public String label;
\r
453 public ChildReference optionsRef;
\r
454 public boolean isActive;
\r
455 public boolean isEnabled;
\r
456 public File historyFolder;
\r
457 public String identifier;
\r