Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2913_MatlabScriptProblemInstanceProvider/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Matlab/Api/MatlabConnector.cs

Last change on this file was 15926, checked in by rhanghof, 7 years ago

#2913:

  • Added the support for importing different Matlab datatypes.
  • Added some classes and changed the import dialog for importing double arrays.
File size: 7.1 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Linq;
5using System.Runtime.InteropServices;
6using System.Text;
7using System.Threading.Tasks;
8using HeuristicLab.Problems.Instances.DataAnalysis.Regression.Matlab.Api.Types;
9
10
11/* MLApp
12 * https://www.codeproject.com/Articles/594636/Using-Matlab-from-a-Csharp-application
13 *  string Execute(string Name)
14 *  void Feval(string bstrName, int nargout, out object pvarArgOut, [object arg1], [object arg2], [object arg3], [object arg4], [object arg5], [object arg6], [object arg7], [object arg8], [object arg9], [object arg10], [object arg11], [object arg12], [object arg13], [object arg14], [object arg15], [object arg16], [object arg17], [object arg18], [object arg19], [object arg20], [object arg21], [object arg22], [object arg23], [object arg24], [object arg25], [object arg26], [object arg27], [object arg28], [object arg29], [object arg30], [object arg31], [object arg32])
15 *  string GetCharArray(string Name, string Workspace)
16 *  void GetFullMatrix(string Name, string Workspace, ref System.Array pr, ref System.Array pi)
17 *  dynamic GetVariable(string Name, string Workspace)
18 *  void GetWorkspaceData(string Name, string Workspace, out object pdata)
19 *  void MaximizeCommandWindow()
20 *  void MinimizeCommandWindow()
21 *  void PutCharArray(string Name, string Workspace, string charArray)
22 *  void PutFullMatrix(string Name, string Workspace, System.Array pr, System.Array pi)
23 *  void PutWorkspaceData(string Name, string Workspace, object data)
24 *  void Quit()
25 * 
26 * MLEval
27 *  void XLEval(string bstrName, int nargout, ref object pvarArgOut, int nargin, object varArgIn)
28 * */
29namespace HeuristicLab.Problems.Instances.DataAnalysis.Regression.Matlab.Api {
30  public class MatlabConnector : IMatlabConnector {
31    private MLApp.MLApp matLabApi;
32    private string workspace;
33    private object locker = new object();
34
35    public event Action<string> ErrorOccuredEvent;
36
37    public MatlabConnector(bool showcommandWindow = false, string workspace = "base") {
38      this.workspace = workspace;
39      OpenMatlab(showcommandWindow);
40    }
41
42    private void OpenMatlab(bool showcommandWindow = false) {
43      Type matlabtype = Type.GetTypeFromProgID("matlab.application.single");
44      matLabApi = (MLApp.MLApp)Activator.CreateInstance(matlabtype);
45      matLabApi.Visible = showcommandWindow ? 1 : 0;
46    }
47
48    public void ExecuteScript(string script) {
49      string directoryName = Path.GetDirectoryName(script);
50      if (string.IsNullOrEmpty(directoryName)) {
51        directoryName = Environment.CurrentDirectory;
52      }
53
54      ChangeDirectory(directoryName);
55      var result = matLabApi.Execute(Path.GetFileNameWithoutExtension(script));
56      if (!string.IsNullOrEmpty(result)) {
57        throw new InvalidOperationException(result);
58      }
59    }
60
61    private void ChangeDirectory(string directoryName) {
62      var result = matLabApi.Execute(string.Format("cd '{0}'", directoryName));
63      if (!string.IsNullOrEmpty(result)) {
64        throw new InvalidOperationException(result);
65      }
66    }
67
68    public void Execute(string command) {
69      matLabApi.Execute(command);
70    }
71
72
73    public IEnumerable<MLVariableInfo> GetVariablesFromScript(string script) {
74      var variables = new List<MLVariableInfo>();
75      try {
76        ExecuteScript(script);
77      } catch(InvalidOperationException ex) {
78        if (ErrorOccuredEvent != null) {
79          ErrorOccuredEvent.Invoke(ex.Message);
80        }
81      }
82
83      Execute("variables=whos();nrOfVariables=size(variables)");
84      var len = ((double[,])GetVariable("nrOfVariables"))[0, 0];
85
86      for (int i = 1; i <= len; i++) {
87        var varName = GetVariable(string.Format("variables({0}).name", i)) as string;
88        var varSize = GetVariable(string.Format("variables({0}).size", i)) as double[,];
89        var varClass = GetVariable(string.Format("variables({0}).class", i)) as string;
90       
91        GetVariablesFromScriptRec(variables, varName, varSize, varClass);
92      }
93
94      return variables;
95    }
96
97    private void GetVariablesFromScriptRec(IList<MLVariableInfo> variables, string varName, double[,] varSize, string varClass) {
98      var variable = new MLVariableInfo() {
99        VarName = varName,
100        Row = varSize[0, 0],
101        Column = varSize[0, 1]
102      };
103      if (varClass == "timeseries") {
104        variable.Datatype = MLDatatype.Timeseries;
105        variables.Add(variable);
106      } else if (varClass == "double") {
107        if (variable.Row == 1 && variable.Column == 1) {
108          variable.Datatype = MLDatatype.Double;
109        } else {
110          variable.Datatype = MLDatatype.DoubleArray;
111        }
112        variables.Add(variable);
113      } else if (varClass == "struct") {
114        Execute(string.Format("mlFieldNames = fieldnames({0})", varName));
115        var fields = GetVariable("mlFieldNames") as object[,];
116
117        for (int i = 0; i < fields.GetLength(0); i++) {
118          var newVarName = string.Format("{0}.{1}", varName, fields[i, 0] as string);
119          Execute(string.Format("mlClass = class({0}); mlSize = size({0});", newVarName));
120          var newVarClass = GetVariable("mlClass") as string;
121          var newVarSize = GetVariable("mlSize") as double[,];
122          GetVariablesFromScriptRec(variables, newVarName, newVarSize, newVarClass);
123        }
124      }
125    }
126
127    public MLTimeseries GetTimeseries(string varName) {
128      lock (locker) {
129        object times = GetVariable(varName + ".Time");
130        object data = GetVariable(varName + ".Data");
131
132        if (times == null || data == null) {
133          return null;
134        }
135        return new MLTimeseries(varName, times, data);
136      }
137    }
138
139    public MLDouble GetDouble(string varName) {
140      return new MLDouble(varName, GetVariable(varName));
141    }
142
143
144    public MLDoubleArray GetDoubleArray(string varName) {
145      return new MLDoubleArray(varName, GetVariable(varName));
146    }
147
148    #region Helper for getting the values of variables from the matlab api.       
149    public object GetVariable(string varName) {
150      object value = null;
151      try {
152        if (IsStruct(varName)) {
153          value = GetValueOfStruct(varName);
154        } else {
155          matLabApi.GetWorkspaceData(varName, workspace, out value);
156        }
157      } catch (COMException) {
158        throw new ArgumentException(string.Format("The variable {0} does not exist in the current workspace {1}.", varName, workspace));
159      }
160      var t = value.GetType();
161      return value;
162    }
163
164
165    private bool IsStruct(string varName) {
166      return varName.Contains(".");
167    }
168
169    private object GetValueOfStruct(string varName) {
170      object value;
171      matLabApi.Execute(string.Format("tmp = {0}", varName));
172      matLabApi.GetWorkspaceData("tmp", workspace, out value);
173      return value;
174    }
175    #endregion
176
177    public void Dispose() {
178      try {
179        if (matLabApi != null) {
180          matLabApi.Execute("exit");
181        }
182      } catch (COMException) {
183      } finally {
184        matLabApi = null;
185      }
186    }
187  }
188}
189
Note: See TracBrowser for help on using the repository browser.