unit test with actual method in c# - c#

Hi I’m working on unit test for my project and I want to check a getmin method in an abstract class that is named Measurementool. That method return a minimum value of selectedarea matrix from current matrix. my project has a rectangle area that is really N*N matrix .
and I need minimum value inside of matrix. I write unit test for debug and test the getmin value but I don’t see desired value for actual value. selectedarea matrix filled with zero and not set with expected value in test method. I think, it considers two matrix. matrix with zero value is wrong when new matrix created as follow:
MatrixHolder selectedArea =
new MatrixHolder(new double[areaHeight * areaWidth], areaWidth);
unit test code:
[TestMethod()]
public void GetMinTest()
{
AreaMeasurmentTool target = new Rectangle();
double[,] MatrixResult = new double[,] {
{10, 0, 20, 10, 10},
{12, 2, 30, 15, 16},
{19, 0, 43, 10, 17},
{80, 0, 65, 18, 13},
{70, 4, 10, 10, 10}};
double []SelectedArea1 = new double[9]{2, 30, 15, 1, 43, 10, 2, 65, 18};
MatrixHolder currentMatrix = new MatrixHolder(SelectedArea1, 3);
double expected = 1;
double actual;
actual = target.GetMin(currentMatrix);
Assert.AreEqual(expected, actual);
}
and class MeasurementTool:
public virtual double GetMin(MatrixHolder currentMatrix)
{
if (currentMatrix == null)
{
throw new Exception("the image Matrix cannot be null.");
}
double minValue = 0;
SetSelectArea(currentMatrix);
minValue = CalculateMin();
minValue = Math.Round(minValue, 2);
return minValue;
}
private void SetSelectArea(MatrixHolder currentMatrix)
{
PointHolder start = new PointHolder(0, 0);
PointHolder end = new PointHolder(0, 0);
SetBoundries(start, end);
int areaHeight = (end.Y - start.Y);
int areaWidth = (end.X - start.X);
MatrixHolder selectedArea = new MatrixHolder(new double[areaHeight * areaWidth], areaWidth);
for (int i = 0; i < areaHeight; i++)
{
int sourceIndex = start.X + (currentMatrix.Witdh * (i + start.Y));
int targetIndex = areaWidth * i;
Array.Copy(currentMatrix.Values, sourceIndex
, selectedArea.Values, targetIndex
, areaWidth);
}
SelectedAreas = selectedArea;
}

Related

Expand dimension of "EmguCV.Mat" or "Onnx Tensor"

I am using Onnxruntime in C# for yolov4.
Here is the pretrained yolo model:
https://github.com/onnx/models/tree/main/vision/object_detection_segmentation/yolov4/model
EmguCV is used to get an image, and then preprocess it to suit Yolo's input.
This is my preprocessing code:
static List<NamedOnnxValue> preprocess_CV(Mat im)
{
CvInvoke.Resize(im, im, new Size(416, 416));
var imData = im.ToImage<Bgr, Byte>().Data;
Tensor<float> input = new DenseTensor<float>(new[] {1, im.Height, im.Width, 3});
for (int x = 0; x < im.Width; x++)
for (int y = 0; y < im.Height; y++)
{
input[0, x, y, 0] = imData[x, y, 2] / (float)255.0;
input[0, x, y, 1] = imData[x, y, 1] / (float)255.0;
input[0, x, y, 2] = imData[x, y, 0] / (float)255.0;
}
List<NamedOnnxValue> inputs = new List<NamedOnnxValue> { NamedOnnxValue.CreateFromTensor("input_1:0", input) };
return inputs;
}
It works fine, but it is really slow, definitely because of nested fors.
So I decide to change it to the following code:
static List<NamedOnnxValue> preprocess_CV_v2(Mat im)
{
CvInvoke.Resize(im, im, new Size(416, 416));
im.ConvertTo(im, DepthType.Cv32F, 1 / 255.0);
CvInvoke.CvtColor(im, im, ColorConversion.Bgr2Rgb);
var imData = im.ToImage<Bgr, Byte>().Data;
var input = imData.ToTensor<float>();
List<NamedOnnxValue> inputs = new List<NamedOnnxValue> { NamedOnnxValue.CreateFromTensor("input_1:0", input) };
return inputs;
}
It does not use nested for and runs faster, but...
Output tensor shape of this code is (416,416,3), but yoloV4 need input tensor with shape (1,416,416,3).
How can I add a single dimension to onnx tensor or CV.Mat image, to fit my tensor to yoloV4 input?
It would be nice of you if you would help me with this problem.
Thanks in advance
Mary
I found one solution myself :D
It may help somebody else, with the same problem.
For me, this code is about 10 times faster than the original code (preprocess_CV function in the question).
static List<NamedOnnxValue> preprocess_CV_v2(Mat im)
{
CvInvoke.Resize(im, im, new Size(416, 416));
im.ConvertTo(im, DepthType.Cv32F, 1 / 255.0);
CvInvoke.CvtColor(im, im, ColorConversion.Bgr2Rgb);
var imData = im.ToImage<Bgr, float>().Data;
float[] imDataFlat = new float[imData.Length];
Buffer.BlockCopy(imData, 0, imDataFlat, 0, imData.Length * 4);
var inputTensor = new DenseTensor<float>(imDataFlat, new int[] { 1, im.Height, im.Width, 3 });
List<NamedOnnxValue> inputs = new List<NamedOnnxValue> { NamedOnnxValue.CreateFromTensor("input_1:0", inputTensor) };
return inputs;
}

Return number from 1 to 10 based on the number size

Let's say I have some random numbers between 1 and 20 like this:
{3,7,14,8,17,6,12}
Now, I need to obtain a number between 1 and 10 for every number, based on the number size.
So for example the smaller number must return 1 and the greatest must return 10.
How can I achieve this?
EDIT
Here the solution that suits with some small changes, I found here : https://stackoverflow.com/a/7989299/16356535
List<int> list = new List<int> { 3, 7, 14, 8, 17, 6, 12 };
int scaleMin = 10; //the normalized minimum desired
int scaleMax = 1; //the normalized maximum desired
int valueMax = list.Max();
int valueMin = list.Min();
int valueRange = valueMax - valueMin;
int scaleRange = scaleMax - scaleMin;
IEnumerable<int> normalized =
list.Select(i =>
((scaleRange * (i - valueMin))
/ valueRange)
+ scaleMin);
Console.WriteLine(normalized);
You almost have it.
List<int> list = new List<int> { 3, 7, 14, 8, 17, 6, 12 };
int scaleMin = 1; //the normalized minimum desired
int scaleMax = 10; //the normalized maximum desired
int valueMax = list.Max();
int valueMin = list.Min();
int valueRange = valueMax - valueMin;
int scaleRange = scaleMax - scaleMin;
IEnumerable<int> normalized =
list.Select(i =>
((scaleRange * (i - valueMin)) / valueRange) + scaleMin);
Console.WriteLine(string.Join(',', normalized));

How to test more than one variable in an if statement?

I am trying to test more than one variable in an if statement.
double firstPlot = RMMA(MultiMA1types.VWMA, 2, 160, 10, 2, 128, 0.75, 0.5).Values[15][0];
double secondPlot = RMMA(MultiMA1types.VWMA, 2, 160, 10, 2, 128, 0.75, 0.5).Values[14][0];
In fact their will be more than one variable:
thirdPlot
fourthPlot
…
if(firstPlot < highPrice && firstPlot > lowPrice)
Is it possible to test each variable in one shot inside the if statement without having to repeat the if statement the same number of times as the number of variables? Like creating one variable that will gather all Plot and be tested all at the same time separately inside the if statement?
Thank you
Looks like Values is a jagged array from which you want to extract the first element of each underlying array, so the following should work:
using System.Collections.Generic;
using System.Linq;
...
double[][] plots = RMMA(MultiMA1types.VWMA, 2, 160, 10, 2, 128, 0.75, 0.5).Values;
IEnumerable<double> firstValues = plots.Select(a => a[0]);
bool allValuesInRange = firstValues.All(v => v < highPrice && v > lowPrice);
EDIT after your comment:
NinjaTrader.NinjaScript.Series<double>[] series =
RMMA(MultiMA1types.VWMA, 2, 160, 10, 2, 128, 0.75, 0.5).Values;
IEnumerable<double> firstValues = series.Select(s => s[0]);
foreach (double firstValue in firstValues)
{
Console.WriteLine(firstValue);
}
Can you iterate through your array instead? E.g., something like this:
private bool CheckValues(/*params here*/)
{
var RMMAVals = RMMA(MultiMA1types.VWMA, 2, 160, 10, 2, 128, 0.75, 0.5);
for (int k = 0; k<RMMAVals.Length; k++)
{
if (RMMAVals[k][0] >= highPrice || RMMAVals[k][0] <= lowPrice)
return false;
}
return true;
}

Random value without duplicates

Random r = new Random();
int randomvalue = r.Next(1,20);
*
*
if(randomvalue == 1) something
if(randomvalue == 2) something
*
*
if(randomvalue == 19) something
What is the best way to make that randomvalue without repeat? Btw: Its WPF, not console.
Try something like below :
Random randomInstance = new Random();
List<int> NumList = new List<int>();
NumList.AddRange(new int[] { 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30 });
int index = randomInstance.Next(0, NumList.Count - 1);
int randomNumber = NumList[index];
NumList.RemoveAt(index);
// This will work
class Program
{
static void Main(string[] args)
{
List<int> i = new List<int>(new int[] { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20});
List<int> r;
r = ShuffleList(i);
}
private static List<E> ShuffleList<E>(List<E> unshuffledList)
{
List<E> sList = new List<E>();
Random r = new Random();
int randomIndex = 0;
while (unshuffledList.Count > 0)
{
randomIndex = r.Next(0, unshuffledList.Count);
sList.Add(unshuffledList[randomIndex]);
unshuffledList.RemoveAt(randomIndex); //remove so wont be added a second time
}
return sList; //return the new shuffled list
}
}
Try this:
var rnd = new Random();
var shuffled =
Enumerable
.Range(1, 20)
.OrderBy(x => rnd.Next())
.ToArray();
using System;
using System.Collections;
using System.Collections.Generic;
namespace SOFAcrobatics
{
public static class Launcher
{
public static void Main ()
{
// 1 to 20 without duplicates
List<Int32> ns = new List<Int32>();
Random r = new Random();
Int32 ph = 0;
while (ns.Count < 20)
{
while (ns.Contains (ph = r.Next(1, 21))) {}
ns.Add(ph);
}
// ns is now populated with random unique numbers (1 to 20)
}
}
}
You need to store random value is the only way to make it unique.
Try this:
Random r = new Random();
public List<int> randomList = new List<int>();
int randomvalue = 0;
Public void newNumber()
{
randomvalue = r.Next(0, 20);
if (!randomList.Contains(randomvalue))
{
randomList.Add(randomvalue);
if(randomvalue == 1)
//do something
if(randomvalue == N)
// do something
}
}
It is not clear what you mean by repeat. If you don't want to see the same number in a row then just keep a hash table or Dictionary<int,int> which keeps the last integer that came out. Then check if the next number is same with last number. If not, remove last number from dictionary and put the current one. If they are same then request another random integer from Random.
var myDictionary = new Dictionary<int,int>;
var randomvalue = r.Next(1,20);
while(myDictionary.ContainsKey(randomvalue))
{
randomvalue = r.Next(1,20);
}
myDictionary.Clear();
myDictionary.Add(randomvalue, 123); //123 is just a number. Doesn't matter.
This guarantees that two same integer will never come consecutively.
NOTE:: Other answers are creative, but "know your data structure". Don't use a list for look up. Hash is what we use for it.

Compare variable with hundreds values

I pass a variable with a value of millivolts acquired by a microprocessor connected via serial port, to a class in my app.
The class has to compare the received value "milliV" to many values corresponding to 10 °C increments. I have to do this for accuracy of the output because the output of a thermocouple is not linear. When the value of "milliV is lower than a specific value, then an integration calculation is made between the top and bottom closer values and returns a new value "_tempEx".
This class is working and returns the correct value but I think that beside if/if else and switch, there should be better way to achieve the same result. I have not coded the entire class which should contain approx. 150 comparison values in the range I need to cover.
Moreover, having to do the same for a thermocouple type K, I would end up with hundreds of strings to compare.
Is there a better way to achieve the same result of the method in this class?
public class Termocoppia
{
//milliV#temperature for thermocouple type "J"
double t10=1.019, t20=1.537, t30=2.059, t40=2.585, t50=3.116;
double t60=3.650, t70=4.187, t80=4.726, t90=5.269, t100=5.814;
double t110=6.360, t120=6.909, t130=7.459, t140=8.010, t150=8.562;
double t160=9.115, t170=9.669, t180=10.224, t190=10.779, t200=11.334;
double t210=11.889, t220=12.445, t230=13.000, t240=13.555, t250=14.110;
double t260=14.665, t270=15.219, t280=15.773, t290=16.327, t300=16.881;
//Temperature References
double d10 = 10.00, d20 = 20.00, d30 = 30, d40 = 40, d50 = 50;
double d60 = 60, d70 = 70, d80 = 80, d90 = 90, d100 = 100;
double d110 = 110, d120 = 120, d130 = 130, d140 = 140, d150 = 150;
double d160 = 160, d170 = 170, d180 = 180, d190 = 190, d200 = 200;
double d210=210, d220=220, d230=230, d240=240, d250=250, d260=260;
double d270=270, d280=280, d290=290, d300=300;
// find the highest value and the bottom one to integrate in between withthe received milliV
// returns the value with _tempEx
public double Calcola(double milliV, double _tempEx)
{
if (milliV <= t10)
{
_tempEx = d10;
}
else if (milliV <= t20)
{
_tempEx = d20 - ((t20 - milliV) / ((t20 - t10) / 10));//Questa formula è corretta
}
else if (milliV <= t30)
{
_tempEx = d30 - ((t30 - milliV) / ((t30 - t20) / 10));
}
else if (milliV <= t40)
{
_tempEx = d40 - ((t40 - milliV) / ((t40 - t30) / 10));
}
else if (milliV <= t50)
{
_tempEx = d50 - ((t50 - milliV) / ((t50 - t40) / 10));
}
...........
...........
else if (milliV <= t300)
{
_tempEx = d300 - ((t300 - milliV) / ((t300 - t290) / 10));
}
else
{
}
return _tempEx;
}
I would appreciate answers with sample codes and/or pointing to usable references.
As has been pointed out, you could use arrays:
class Termocoppia
{
// be sure to add all of your values here...
double[] t = { 1.019, 1.537, 2.059, ... };
double[] d = { 10, 20, 30, ... };
public double Calcola(double milliV, double _tempEx)
{
if (milliV <= t[0])
{
// handle first case
_tempEx = d[0];
}
else
{
bool success = false;
int count = t.Length;
// loop through all t values, test, and then calculate
for (int idx = 1; idx < count; idx++)
{
if (milliV <= t[idx])
{
_tempEx = d[idx] -
((t[idx] - milliV) / ((t[idx] - t[idx - 1]) / 10));
success = true;
break;
}
}
if (success == false)
throw new Exception("Unable to calculate _tempEX");
}
return _tempEx;
}
}
The t and d values store the values in an array. The code then just loops through the t array and checks for the condition (milliV <= t[idx]). If this is true, then it uses the corresponding d[idx] and t[idx-1] value to calculate the result.

Categories