*******************************************************************************/\r
package org.simantics.modelica.data;\r
\r
+import java.io.File;\r
+import java.io.FileNotFoundException;\r
import java.io.IOException;\r
import java.io.InputStream;\r
import java.util.Map;\r
\r
+import org.simantics.modelica.reader.MatFileReader;\r
+\r
/**\r
* SimulationResult for Mat-formatted simulations results\r
* \r
* @author Teemu Lempinen\r
*\r
*/\r
+\r
public class MatSimulationResult extends SimulationResult {\r
\r
@Override\r
}\r
}\r
}\r
+ \r
+ @Override\r
+ public void initRead(File file) throws FileNotFoundException, IOException {\r
+ super.initRead(file);\r
+ resultFileReader = new MatFileReader(file);\r
+ }\r
}\r
import javax.xml.xpath.XPathExpressionException;\r
import javax.xml.xpath.XPathFactory;\r
\r
+import org.simantics.modelica.reader.ResultFileReader;\r
import org.w3c.dom.Document;\r
import org.w3c.dom.Node;\r
import org.w3c.dom.NodeList;\r
protected List<DataSet> variables = new ArrayList<DataSet>();\r
protected List<DataSet> initials = new ArrayList<DataSet>();\r
protected int numberOfLines = 0;\r
+ protected ResultFileReader resultFileReader;\r
+ protected double[] allTimes;\r
+ protected int skip;\r
\r
/**\r
* Private class used in displaying errors\r
}\r
}\r
\r
-\r
-\r
/**\r
* Read result file. Read all values in the result file.\r
* \r
read(file, 1);\r
}\r
\r
-\r
/**\r
- * Read result file\r
+ * Initialize result file reading and read the whole result file\r
* \r
* @param file result file\r
* @param interval the interval of results to be read. 1 reads all time steps, 2 reads every other time step, etc...\r
* @throws FileNotFoundException\r
* @throws IOException\r
*/\r
- public void read(File file, int interval) throws FileNotFoundException, IOException {\r
+ public void read(File file, int interval) throws FileNotFoundException, IOException {\r
+ initRead(file);\r
+ readAll(file, interval);\r
+ }\r
+\r
+ /**\r
+ * Initialize result file reading\r
+ * \r
+ * @param file result file\r
+ * @param interval the interval of results to be read. 1 reads all time steps, 2 reads every other time step, etc...\r
+ * @throws FileNotFoundException\r
+ * @throws IOException\r
+ */\r
+ public void initRead(File file) throws FileNotFoundException, IOException {\r
// First check the number of time steps.\r
// With *.mat result file this is not necessary\r
if (!(this instanceof MatSimulationResult)) {\r
lnr.close();\r
fr.close();\r
}\r
+ }\r
+ \r
+ /**\r
+ * Read the whole result file\r
+ * \r
+ * @param file result file\r
+ * @param interval the interval of results to be read. 1 reads all time steps, 2 reads every other time step, etc...\r
+ * @throws FileNotFoundException\r
+ * @throws IOException\r
+ */\r
+ public void readAll(File file, int interval) throws FileNotFoundException, IOException {\r
InputStream is = openStream(file);\r
- //InputStream is = new FileInputStream(file);\r
read(is, interval);\r
is.close();\r
}\r
\r
- private InputStream openStream(File file) throws FileNotFoundException {\r
+\r
+ protected InputStream openStream(File file) throws FileNotFoundException {\r
return new BufferedInputStream(new FileInputStream(file));\r
}\r
\r
}\r
return errorString.toString();\r
}\r
+\r
+ /**\r
+ * Read a defined variable from result file\r
+ * \r
+ * @param file result file\r
+ * @param interval the interval of results to be read. 1 reads all time steps, 2 reads every other time step, etc...\r
+ * @throws FileNotFoundException\r
+ * @throws IOException\r
+ */\r
+ public void readVariable(String variable, File file) throws FileNotFoundException, IOException {\r
+ DataSet ds;\r
+ List<String> names = resultFileReader.getNames();\r
+ if (names.contains(variable)) {\r
+ double[] resArray = resultFileReader.readData(variable, 0, allTimes.length, skip);\r
+ ds = new DataSet(variable, allTimes, resArray);\r
+ variables.add(ds);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Read time array from result file\r
+ * \r
+ * @param file result file\r
+ * @param interval the interval of results to be read. 1 reads all time steps, 2 reads every other time step, etc...\r
+ * @throws FileNotFoundException\r
+ * @throws IOException\r
+ */\r
+ public void readTime(File file, int interval) throws FileNotFoundException, IOException {\r
+ skip = interval - 1;\r
+ int totalCount = resultFileReader.getCount("time");\r
+ int count = totalCount / interval;\r
+ if (totalCount % interval != 0)\r
+ count++;\r
+ allTimes = resultFileReader.readData("time", 0, count, skip); \r
+ }\r
+\r
}\r
import org.simantics.utils.datastructures.MapList;\r
\r
public class MatFileReader implements ResultFileReader {\r
- private File file;\r
+ private final File file;\r
\r
- private List<String> names = new ArrayList<String>();\r
- private Map<String, Integer> indices = new HashMap<String, Integer>();\r
+ private final List<String> names = new ArrayList<String>();\r
+ private final Map<String, Integer> indices = new HashMap<String, Integer>();\r
+ \r
+ private HashMap<String, double[]> parameterValues;\r
\r
\r
long readBytes = 0; // tracking read data\r
readVariables();\r
}\r
\r
- public List<String> getNames() {\r
+ @Override\r
+ public List<String> getNames() {\r
return names;\r
}\r
\r
\r
- public int getCount(String item) {\r
+ @Override\r
+ public int getCount(String item) {\r
return dataHeader.columns;\r
}\r
/**\r
* Reads all data of a given item\r
*/\r
- public double[] readData(String item) throws IOException {\r
+ @Override\r
+ public double[] readData(String item) throws IOException {\r
readBytes = 0;\r
Integer index = indices.get(item);\r
if (index == null)\r
- throw new IOException("Unknown item: " + item);\r
+ if (parameterValues.containsKey(item)) {\r
+ return parameterValues.get(item);\r
+ } else {\r
+ throw new IOException("Unknown item: " + item);\r
+ }\r
InputStream in = openStream();\r
skip(dataMark, in);\r
\r
* @return\r
* @throws IOException\r
*/\r
- public double[] readData(String item, int start, int count, int skip) throws IOException {\r
+ @Override\r
+ public double[] readData(String item, int start, int count, int skip) throws IOException {\r
readBytes = 0;\r
Integer index = indices.get(item);\r
if (index == null)\r
- throw new IOException("Unknown item: " + item);\r
+ if (parameterValues.containsKey(item)) {\r
+ return parameterValues.get(item);\r
+ } else {\r
+ throw new IOException("Unknown item: " + item);\r
+ }\r
InputStream in = openStream();\r
skip(dataMark, in);\r
\r
\r
}\r
\r
- public double[][] readData(List<String> items) throws IOException {\r
- readBytes = 0;\r
+ @Override\r
+ public double[][] readData(List<String> items) throws IOException {\r
+ readBytes = 0;\r
List<Integer> indexes = new ArrayList<Integer>(items.size());\r
for (String item : items) {\r
Integer index = indices.get(item);\r
if (index == null)\r
- throw new IOException("Unknown item: " + item);\r
+ // Parameters cannot be accessed via this method; instead, \r
+ // methods with only a single item should be used\r
+ throw new IOException("Unknown item: " + item);\r
indexes.add(index);\r
}\r
\r
for (String item : items) {\r
Integer index = indices.get(item);\r
if (index == null)\r
- throw new IOException("Unknown item: " + item);\r
+ // Parameters cannot be accessed via this method; instead, \r
+ // methods with only a single item should be used\r
+ throw new IOException("Unknown item: " + item);\r
indexes.add(index);\r
}\r
\r
\r
infoData = info.data;\r
\r
- readMatrix(in); // Some result data matrix?\r
+ //Read parameters\r
+ parameterValues = new HashMap<String, double[]>();\r
+ DoubleMatrix parameters = (DoubleMatrix)readMatrix(in); // Some result data matrix?\r
+ readDoubleMatrix(parameters, names, 1, 1, info, 1, parameterValues);\r
\r
dataHeader = new MatrixHeader(in);\r
\r
// filter incompatible? data.\r
for (int i = this.names.size() -1; i >= 0; i--) {\r
if (infoData[i * 4] != 2) {\r
- String name = this.names.remove(i);\r
+ String name = this.names.get(i);\r
+ // Remove parameters from indices but not from names list\r
this.indices.remove(name);\r
}\r
\r
if (infoData[row * 4] != 2)\r
throw new IOException(); // this is checked in initialization phase.\r
int size = header.columns;\r
- if (start+count*(skip+1) > size)\r
+ if (start+count*(skip+1)-skip > size)\r
throw new IndexOutOfBoundsException(); // TODO: we could just read available data, instead of throwing exception.\r
int rows = header.rows;\r
double[] v = new double[count];\r
\r
\r
\r
- skip((long)c[0] * 8L, in);\r
+ skip(c[0] * 8L, in);\r
for (int j = 0; j < size; ++j) {\r
for (int index = 0; index < sortedRows.size(); index++) {\r
\r
\r
\r
long s = start;\r
- s *= (long)rows;\r
+ s *= rows;\r
s *= 8L;\r
skip(s, in);\r
skip(c[0] * 8, in);\r
}\r
}\r
\r
+ private static void readDoubleMatrix(DoubleMatrix matrix, StringMatrix names, int dataMatrixNumber, int startIndex, IntMatrix info, int outputInterval, HashMap<String, double[]> result) {\r
+ double[] valueData = matrix.data;\r
+ int[] infoData = info.data;\r
+ int rows = matrix.rows;\r
+ //System.out.println("cols="+values.columns+", rows=" +values.rows+ ", data.length="+valueData.length);\r
+\r
+ for(int i=startIndex;i<info.columns;++i) {\r
+ if(infoData[i*4] != dataMatrixNumber)\r
+ continue;\r
+ // If values.columns % outputInterval != 0, the value in the last time step would not be displayed without adding a +1;\r
+ int size = matrix.columns % outputInterval != 0 ? matrix.columns / outputInterval + 1 : matrix.columns; \r
+ double[] v = new double[size];\r
+ int sc = infoData[i*4+1];\r
+ int c = sc > 0 ? sc-1 : -sc-1;\r
+ //System.out.println("i=" + i + ", sc=" + sc + ", c=" + c);\r
+ for(int j=0;j<v.length;++j) {\r
+ int adjusted = j * outputInterval;\r
+ if(adjusted >= matrix.columns) adjusted = matrix.columns - 1;\r
+ v[j] = valueData[rows * adjusted + c];\r
+ } if(sc < 0)\r
+ for(int j=0;j<v.length;++j)\r
+ v[j] = -v[j];\r
+ result.put(names.data[i], v);\r
+ }\r
+ }\r
\r
private class MatrixHeader {\r
\r
String outputInterval = experimentParameters.get(ModelicaKeys.OUTPUT_INTERVAL);\r
if(outputInterval != null) {\r
String stepTime = experimentParameters.get(ModelicaKeys.STEP_VALUE);\r
-\r
+ String stopTime = experimentParameters.get(ModelicaKeys.STOP_VALUE);\r
+ \r
Double step = Double.parseDouble(stepTime);\r
+ Double stop = Double.parseDouble(stopTime);\r
Double outInterval = Double.parseDouble(outputInterval);\r
\r
- double nearest = roundUp(outInterval, step);\r
- outIntervalInt = (int)(nearest / step);\r
- if(outIntervalInt <= 0) outIntervalInt = 1;\r
+ outIntervalInt = (int)getInterval(outInterval, step);\r
+ // Actually you might be able to use an outInterval one or two longer. \r
+ int maxIntervalInt = (int)Math.round(stop / step);\r
+ if (outIntervalInt > maxIntervalInt)\r
+ outIntervalInt = maxIntervalInt;\r
}\r
\r
- result.read(simulationLocation.resFile, outIntervalInt);\r
+ result.initRead(simulationLocation.resFile);\r
+ result.readTime(simulationLocation.resFile, outIntervalInt);\r
//result.readInits(simulationLocation.initFile); // Parameter values are read from .mat\r
result.filter();\r
getCurrentResult().setResult(result);\r
+ getCurrentResult().setResultFile(simulationLocation.resFile);\r
progressMonitor.worked(1);\r
resultsChanged();\r
\r
};\r
}\r
\r
- protected static double roundUp(double numToRound, double multiple) {\r
- if(multiple == 0) {\r
- return numToRound;\r
- }\r
- double remainder = numToRound % multiple;\r
- if (remainder == 0) {\r
- return numToRound;\r
- }\r
- return numToRound + multiple - remainder;\r
+ protected static long getInterval(double outputLength, double stepLength) {\r
+ double interval = outputLength / stepLength;\r
+ if (interval <= 1)\r
+ return 1;\r
+ return Math.round(interval);\r
}\r
\r
\r
import org.simantics.db.exception.DatabaseException;\r
import org.simantics.db.procedure.AsyncListener;\r
import org.simantics.db.request.Read;\r
+import org.simantics.fmu.FMUControlJNI;\r
+import org.simantics.fmu.FMUJNIException;\r
import org.simantics.modelica.IModelicaMonitor;\r
import org.simantics.modelica.SimulationLocation;\r
import org.simantics.modelica.data.DataSet;\r
import org.simantics.modelica.data.SimulationResult;\r
-import org.simantics.fmu.FMUControlJNI;\r
-import org.simantics.fmu.FMUJNIException;\r
import org.simantics.simulation.experiment.ExperimentState;\r
import org.simantics.sysdyn.SysdynResource;\r
import org.simantics.utils.datastructures.Triple;\r
if(result.third == null) {\r
setOutputInterval(DEFAULT_OUTPUT_INTERVAL);\r
} else {\r
- double nearest = roundUp(result.third, getStepLength());\r
- int interval = (int)(nearest / getStepLength());\r
- if(interval <= 0) interval = 1;\r
+ int interval = (int)getInterval(result.third, getStepLength());\r
setOutputInterval(interval);\r
}\r
}\r
private class simulateDurationJob extends Job {\r
\r
private double duration;\r
- private SysdynGameExperiment experiment;\r
+ private final SysdynGameExperiment experiment;\r
public simulateDurationJob(String name, SysdynGameExperiment experiment, double duration) {\r
super(name);\r
this.duration = duration;\r
\r
\r
import java.io.File;\r
+import java.io.FileNotFoundException;\r
import java.io.IOException;\r
import java.util.List;\r
import java.util.TreeMap;\r
protected RecordAccessor accessor;\r
protected String resultName;\r
private SimulationResult simulationResult;\r
+ private File resultFile;\r
\r
/**\r
* Create an empty result\r
try {\r
ma = accessor.getComponent( ref );\r
} catch (AccessorConstructionException e) {\r
- // Variable was not found, so add it and try again\r
+ // Variable was not found, so read it from file\r
+ try {\r
+ simulationResult.readVariable(variable, resultFile);\r
+ } catch (FileNotFoundException e1) {\r
+ // Unable to read data from OpenModelica result file\r
+ System.err.println("Variable " + variable + " not found in OpenModelica result file");\r
+ return null;\r
+ } catch (IOException e1) {\r
+ // IoFail\r
+ e1.printStackTrace();\r
+ return null;\r
+ }\r
+ \r
+ // Add the read item\r
addDataSet(variable);\r
try {\r
ma = accessor.getComponent( ref );\r
public int numberOfVariables() {\r
return simulationResult.getVariableDataSets().size();\r
}\r
+\r
+ public void setResultFile(File resFile) {\r
+ this.resultFile = resFile;\r
+ }\r
}\r