5 Replies - 3906 Views - Last Post: 24 March 2016 - 09:37 AM Rate Topic: -----

#1 tvc8   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 17-March 16

C# MATLAB Integration and MWArray Conversion

Posted 17 March 2016 - 09:15 AM

I am attempting to integrate code that was written in MATLAB into a C# program. Originally the C# code called the installed MATLAB program that was on the users computer in order to compute a result. This is to be changed so that the user does not need MATLAB installed on their computer and can simply run the C# program. The MATLAB code was compiled using MATLAb's built in .NET assembly compiler and the the .NET dll were interfaced into C#. The user would then only need to install the MATLAB runtime to use the program.

In the old version the output of the MATLAB program call was put into an object array. The object array was then converted to a double [,] array or an object[,] array and assigned to a DataRow based on an index. Some of the old code is below:
    object result = null;
    
    matlab.Feval("GetReadRates", 9, out result, str_Test_Type, str_Symbol_Set, str_Test_Name, str_Test_Scanner, str_Test_Speed, str_Test_Angle, str_Test_Distance, str_Test_Number,numScans, speedThreshold, noReadString, str_DataFilepath);
    
    object[] res = result as object[];

    newSymbolDataRow["Read_Rate"] = (res[0] as double[,])[0, symbolIndex];
    newSymbolDataRow["NoRead_Rate"] = (res[1] as double[,])[0, symbIndex];
    newSymbolDataRow["Misread_Rate"] = (res[2] as double[,])[0, symbolIndex];
    newSymbolDataRow["Misreads"] = (res[3] as object[,])[0, symbolIndex];


In the new version the output of the MATLAB class has to be stored in a MWArray. From this MWArray the data has to be converted and assigned to a DataRow just as the old code did.

The way I would like to approach this is to converted the MWArray to an object array and use the same code for the DataRows.
However, this does not seem possible and very few methods available for converting data. The MWArray class has MWArray.GetValue(int index), MWArray.toString(), and MWArray.toArray(). The MWArray.toArray() I have attempted to use as seen below.

    MWArray str_Test_TypeMW = str_Test_Type;
    MWArray str_Symbol_SetMW = str_Symbol_Set;
    MWArray numScansMW = numScans;
    MWArray speedThresholdMW = speedThreshold;
    MWArray noReadStringMW = noReadString;
    MWArray str_DataFilepathMW = str_DataFilepath;
    MWArray str_Test_NameMW = str_Test_Name;
    MWArray str_Test_ScannerMW = str_Test_Scanner;
    MWArray str_Test_SpeedMW = str_Test_Speed;
    MWArray str_Test_AngleMW = str_Test_Angle;
    MWArray str_Test_DistanceMW = str_Test_Distance;
    MWArray str_Test_NumberMW = str_Test_Number;

    MWArray [] OutResult = null;
    GRRClass matlabreplacement;

    matlabreplacement = new GRRClass();
    OutResult=matlabreplacement.GetReadRates(9, str_Test_TypeMW, str_Symbol_SetMW, str_Test_NameMW, str_Test_ScannerMW, str_Test_SpeedMW, str_Test_AngleMW, str_Test_DistanceMW, str_Test_NumberMW,numScansMW, speedThresholdMW, noReadStringMW, str_DataFilepathMW);

    Array resArray = Array.CreateInstance(typeof(object), 9, 2);
    resArray.Initialize();
    resArray = OutResult.ToArray();
    
    newSymbolDataRow["Read_Rate"] = (resArray.GetValue(0) as double[,])[0, symbolIndex];



The MWArray OutResult has this format according to Visual Studio:
    OutResult	{MathWorks.MATLAB.NET.Arrays.MWArray[9]} MathWorks.MATLAB.NET.Arrays.MWArray[]
    [0]	{0     0}	MathWorks.MATLAB.NET.Arrays.MWArray {MathWorks.MATLAB.NET.Arrays.MWNumericArray}
    [1]	{0     0}	MathWorks.MATLAB.NET.Arrays.MWArray {MathWorks.MATLAB.NET.Arrays.MWNumericArray}
    [2]	{100   100}	MathWorks.MATLAB.NET.Arrays.MWArray {MathWorks.MATLAB.NET.Arrays.MWNumericArray}
    [3]	{'10-000-001(2)'    '10-000-002(2)'}	MathWorks.MATLAB.NET.Arrays.MWArray {MathWorks.MATLAB.NET.Arrays.MWCellArray}
    [4]	{0.0150    0.0250}	MathWorks.MATLAB.NET.Arrays.MWArray {MathWorks.MATLAB.NET.Arrays.MWNumericArray}
    [5]	{0     0}	MathWorks.MATLAB.NET.Arrays.MWArray {MathWorks.MATLAB.NET.Arrays.MWNumericArray}
    [6]	{0.6205    0.6205}	MathWorks.MATLAB.NET.Arrays.MWArray {MathWorks.MATLAB.NET.Arrays.MWNumericArray}
    [7] {0     0} MathWorks.MATLAB.NET.Arrays.MWArray {MathWorks.MATLAB.NET.Arrays.MWNumericArray}
    [8]	{Analysis Completed} MathWorks.MATLAB.NET.Arrays.MWArray {MathWorks.MATLAB.NET.Arrays.MWCharArray}


With each element having indices for the two values. The Array resArray has the same format as the MWArray.

Whenever I attempt to run the program I get an exception "Object reference not set to an instance of an object" whenever the line "newSymbolDataRow" runs.

Thank you for any help, I am still a beginner at C# programming.

Is This A Good Question/Topic? 0
  • +

Replies To: C# MATLAB Integration and MWArray Conversion

#2 Curtis Rutland   User is offline

  • (╯□)╯︵ (~ .o.)~
  • member icon


Reputation: 5103
  • View blog
  • Posts: 9,283
  • Joined: 08-June 10

Re: C# MATLAB Integration and MWArray Conversion

Posted 17 March 2016 - 09:24 AM

Quote

Object reference not set to an instance of an object


This is one of the most common exceptions a .NET programmer will encounter. It's called a "Null Reference Exception". It happens when you try to "dereference a null pointer", or in our more abstracted world, when you try to access a null value.

So, if this line is crashing:

newSymbolDataRow["Read_Rate"] = (resArray.GetValue(0) as double[,])[0, symbolIndex];



There are a few things that could be null here, and you're going to have to check all of them. Learning how to use the debugger and breakpoints will vastly simplify this task.

You have to check newSymbolDataRow (unless you know it's not null, but even then it's worth checking).

Using the as operator for casting means that, if the cast fails, the result will be null. So (resArray.GetValue(0) as double[,]) itself could result in null, if you can't cast whatever GetValue(0) returns into a double[,].

If you want to make verifying that last part easier, you should do something like this:

double[,] readRate = resArray.GetValue(0) as double[,];
newSymbolDataRow["Read_Rate"] = readRate[0, symbolIndex];


Break it out onto two lines so you can inspect readRate and see if it's null.
Was This Post Helpful? 0
  • +
  • -

#3 tvc8   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 17-March 16

Re: C# MATLAB Integration and MWArray Conversion

Posted 17 March 2016 - 12:28 PM

I split up the code and the variable readRate was null whenever the code was run. This is odd because there is data in resArray. From Visual Studio the data is in the following format:
-		resArray	{MathWorks.MATLAB.NET.Arrays.MWArray[9]}	System.Array {MathWorks.MATLAB.NET.Arrays.MWArray[]}
-		[0]	{0     0}	MathWorks.MATLAB.NET.Arrays.MWArray {MathWorks.MATLAB.NET.Arrays.MWNumericArray}
		ArrayType	Numeric	MathWorks.MATLAB.NET.Arrays.MWArrayType
[indent]
-		Dimensions	{int[2]}	int[]
		[0]	1	int
		[1]	2	int
		IsByte	false	bool
		IsCellArray	false	bool
		IsCharArray	false	bool
		IsComplex	false	bool
		IsDisposed	false	bool
		IsDouble	true	bool
		IsEmpty	false	bool
		IsFloat	false	bool
+		IsInfinity	'((MathWorks.MATLAB.NET.Arrays.MWNumericArray)((MathWorks.MATLAB.NET.Arrays.MWArray[])resArray)[0]).IsInfinity' threw an exception of type 'System.Exception'	bool {System.Exception}
		IsInteger	false	bool
		IsLogicalArray	false	bool
		IsLong	false	bool
+		IsNaN	'((MathWorks.MATLAB.NET.Arrays.MWNumericArray)((MathWorks.MATLAB.NET.Arrays.MWArray[])resArray)[0]).IsNaN' threw an exception of type 'System.Exception'	bool {System.Exception}
		IsNumericArray	true	bool
		IsShort	false	bool
		IsSparse	false	bool
		IsStructArray	false	bool
		NonZeroMaxStorage	2	int
		NumberOfElements	2	int
		NumberofDimensions	2	int
		NumericType	Double	MathWorks.MATLAB.NET.Arrays.MWNumericType
+		Static members		
+		Non-Public members		
[/indent]
+		[1]	{0     0}	MathWorks.MATLAB.NET.Arrays.MWArray {MathWorks.MATLAB.NET.Arrays.MWNumericArray}
+		[2]	{100   100}	MathWorks.MATLAB.NET.Arrays.MWArray {MathWorks.MATLAB.NET.Arrays.MWNumericArray}
+		[3]	{'10-000-001(2)'    '10-000-002(2)'}	MathWorks.MATLAB.NET.Arrays.MWArray {MathWorks.MATLAB.NET.Arrays.MWCellArray}
+		[4]	{0.0150    0.0250}	MathWorks.MATLAB.NET.Arrays.MWArray {MathWorks.MATLAB.NET.Arrays.MWNumericArray}
+		[5]	{0     0}	MathWorks.MATLAB.NET.Arrays.MWArray {MathWorks.MATLAB.NET.Arrays.MWNumericArray}
+		[6]	{0.6205    0.6205}	MathWorks.MATLAB.NET.Arrays.MWArray {MathWorks.MATLAB.NET.Arrays.MWNumericArray}
+		[7]	{0     0}	MathWorks.MATLAB.NET.Arrays.MWArray {MathWorks.MATLAB.NET.Arrays.MWNumericArray}
+		[8]	{Analysis Completed}	MathWorks.MATLAB.NET.Arrays.MWArray {MathWorks.MATLAB.NET.Arrays.MWCharArray}




Was This Post Helpful? 0
  • +
  • -

#4 tlhIn`toq   User is offline

  • Xamarin Cert. Dev.
  • member icon

Reputation: 6534
  • View blog
  • Posts: 14,450
  • Joined: 02-June 10

Re: C# MATLAB Integration and MWArray Conversion

Posted 17 March 2016 - 03:43 PM

See the link to tutorials marked "What does this error mean?" below.

This looks like a very straight-forward debugging situation.

Wanting to know how and where to distribute software, what to charge, how to secure it, how to provide updates and so on is fairly common. For that reason, if you look toward the end of my FAQ below questions 48 and higher cover a lot and provide several links to existing in-dept discussions. Of course distribution channels change rapidly. Some are platform specific such as Apple's app store if you are making iOS software. If you have any new suggestions specifically on where, please let me know and I'll update this FAQ.




tlhIn`toq's FAQ list - Updated Oct 2015


Learning to debug one's own code is an essential skill. Sadly, one that apparently few college courses teach. Silly if you ask me.
Placing breakpoints and walking through the code line by line allows you to actually WATCH it execute, check the condition of each of variable's run-time value, and watch the logic unfold right before your eyes.
Visualizing what your code does will let you see why it behaves the way it does.
It would be well worth your time to do the tutorials on FAQ 2. A couple hours learning this skill will save you hundreds of hours of confusion in one project alone.

In addition to FAQ 2 in the list below, also check my signature block for a link on how to look at your variables' values at run-time.

TOP most asked:
What does this error message mean?
FAQ 2: How do I debug
FAQ 3: How do I make Class1/Form1 talk to Class2/Form2

Why are you still building in WinForms?

Quote

"old 1990's WinForms"? i just use visual studio 2015 and started up with a windows form. didn't know there was an option for a newer winform?


WinForms is OLD. Virtually 'legacy' and to many of us nearly considered end-of-life. There are still placing building new projects in it, but I wouldn't work for anyplace that wanted to hold me back by two decades. There are probably tens of thousands of legacy WinForms applications in use in countless companies. "If it ain't broke, don't fix it." in other words: If there isn't a financial gain to be made in re-writing them right now why invest the time and money?

But with decades of WinForms comes developers with decades more experience than you'll have and you have no way to compete with them. Let the legacy developer maintain the legacy applications. Many of them are too stuck in their ways to move forward to WPF. Which is why if you look at job boards, what companies are hiring for and have been looking for, for the last several years its: WPF/MVVM.

So if I were you I would just jump right to WPF. Don't worry about WinForms unless you have a deliberate need for it down the line. Otherwise you spend 10,000 hours getting good at WinForms only to find you need to spend another 7,500 hours bringing your skillset forward several years into WPF - And at the same time break all the bad habits you learned in WinForms.

If some company hires you for WPF development, but would also like it if you could maintain some legacy applications THEN learn WinForms; and take your good habits from WPF with you.


FAQ (Frequently Asked Questions - Updated Nov 2015
Spoiler



Was This Post Helpful? 0
  • +
  • -

#5 tvc8   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 17-March 16

Re: C# MATLAB Integration and MWArray Conversion

Posted 17 March 2016 - 07:14 PM

The problem with troubleshooting this exception is I am having a difficult time getting the data format correct.

From how I see the MWArray data, there is an MWArray with 8 rows of data values. Most are MWNumericArray containing double values but there is one row, OutResult[3], that is a MWCellArray and the last row is A MWCharArray. Each of the rows, according to Visual Studio, have two "cells" that have their own index values.

I would like to access the data that is in these two "cells" and put each piece of data into two dimensional double [,] and object[,]. However, I cannot seem to get the formatting correct to access this data.
Was This Post Helpful? 0
  • +
  • -

#6 tvc8   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 17-March 16

Re: C# MATLAB Integration and MWArray Conversion

Posted 24 March 2016 - 09:37 AM

View Posttvc8, on 17 March 2016 - 07:14 PM, said:

The problem with troubleshooting this exception is I am having a difficult time getting the data format correct.

From how I see the MWArray data, there is an MWArray with 8 rows of data values. Most are MWNumericArray containing double values but there is one row, OutResult[3], that is a MWCellArray and the last row is A MWCharArray. Each of the rows, according to Visual Studio, have two "cells" that have their own index values.

I would like to access the data that is in these two "cells" and put each piece of data into two dimensional double [,] and object[,]. However, I cannot seem to get the formatting correct to access this data.




So I ended up solving this problem not the most elegant way. I took the MWArray OutResult and converted each row to a string and put them in a string array. I then split each cell of the string array by whitespace and put it into a temporary string. I then converted string into the type of data I need using Double.Parse. The code is seen below:

MWArray str_Test_TypeMW = str_Test_Type;
MWArray str_Symbol_SetMW = str_Symbol_Set;
MWArray numScansMW = numScans;
MWArray speedThresholdMW = speedThreshold;
MWArray noReadStringMW = noReadString;
MWArray str_DataFilepathMW = str_DataFilepath;
MWArray str_Test_NameMW = str_Test_Name;
MWArray str_Test_ScannerMW = str_Test_Scanner;
MWArray str_Test_SpeedMW = str_Test_Speed;
MWArray str_Test_AngleMW = str_Test_Angle;
MWArray str_Test_DistanceMW = str_Test_Distance;
MWArray str_Test_NumberMW = str_Test_Number;

matlabreplacement = new GRRClass();
OutResult=matlabreplacement.GetReadRates(9, str_Test_TypeMW, str_Symbol_SetMW, str_Test_NameMW, str_Test_ScannerMW, str_Test_SpeedMW, str_Test_AngleMW, str_Test_DistanceMW, str_Test_NumberMW, numScansMW, speedThresholdMW, noReadStringMW, str_DataFilepathMW);

string[] tempString0;
string[] tempString1;
string[] tempString2;
string[] tempString3;
string[] tempString4;
string[] tempString5;
string[] tempString6;
string[] tempString7;

resObjectVals=new object[1,2];
resDoubleVals = new double[7, 2];
resStringVals =new string[8];
string[] separators = { " " };
resStringVals[0] = OutResult.GetValue(0).ToString();
resStringVals[1] = OutResult.GetValue(1).ToString();
resStringVals[2] = OutResult.GetValue(2).ToString();
resStringVals[3] = OutResult.GetValue(3).ToString(); //non numerical value
resStringVals[4] = OutResult.GetValue(4).ToString();
resStringVals[5] = OutResult.GetValue(5).ToString();
resStringVals[6] = OutResult.GetValue(6).ToString();
resStringVals[7] = OutResult.GetValue(7).ToString();

tempString0 = resStringVals[0].Split(separators, StringSplitOptions.RemoveEmptyEntries);
tempString1 = resStringVals[1].Split(separators, StringSplitOptions.RemoveEmptyEntries);
tempString2 = resStringVals[2].Split(separators, StringSplitOptions.RemoveEmptyEntries);
tempString3 = resStringVals[3].Split(separators, StringSplitOptions.RemoveEmptyEntries);
tempString4 = resStringVals[4].Split(separators, StringSplitOptions.RemoveEmptyEntries);
tempString5 = resStringVals[5].Split(separators, StringSplitOptions.RemoveEmptyEntries);
tempString6 = resStringVals[6].Split(separators, StringSplitOptions.RemoveEmptyEntries);
tempString7 = resStringVals[7].Split(separators, StringSplitOptions.RemoveEmptyEntries);

resDoubleVals[0, 0] = Double.Parse(tempString0[0]);
resDoubleVals[0, 1] = Double.Parse(tempString0[1]);
resDoubleVals[1, 0] = Double.Parse(tempString1[0]);
resDoubleVals[1, 1] = Double.Parse(tempString1[1]);
resDoubleVals[2, 0] = Double.Parse(tempString2[0]);
resDoubleVals[2, 1] = Double.Parse(tempString2[1]);
resObjectVals[0, 0] = (object)tempString3[0]; //tempString3 has object
resObjectVals[0, 1] = (object)tempString3[1]; //tempString3 has object
resDoubleVals[3, 0] = Double.Parse(tempString4[0]);
resDoubleVals[3, 1] = Double.Parse(tempString4[1]);
resDoubleVals[4, 0] = Double.Parse(tempString5[0]);
resDoubleVals[4, 1] = Double.Parse(tempString5[1]);
resDoubleVals[5, 0] = Double.Parse(tempString6[0]);
resDoubleVals[5, 1] = Double.Parse(tempString6[1]);
resDoubleVals[6, 0] = Double.Parse(tempString7[0]);
resDoubleVals[6, 1] = Double.Parse(tempString7[1]);




Then down where the new datarows are added the code was changed to:

newSymbolDataRow["Read_Rate"] = resDoubleVals[0,symbolIndex];
newSymbolDataRow["NoRead_Rate"] = resDoubleVals[1, symbolIndex];
newSymbolDataRow["Misread_Rate"] = resDoubleVals[2, symbolIndex];
newSymbolDataRow["Misreads"] = resObjectVals[0, symbolIndex];
newSymbolDataRow["Avg_Read_Time"] = resDoubleVals[3, symbolIndex];
newSymbolDataRow["Stdev_Read_Time"] = resDoubleVals[4, symbolIndex];
newSymbolDataRow["Avg_Speed"] = resDoubleVals[5, symbolIndex];
newSymbolDataRow["Stdev_Speed"] = resDoubleVals[6, symbolIndex];
newSymbolDataRow["Num_Scans"] = numScans;



Was This Post Helpful? 0
  • +
  • -

Page 1 of 1