Extract x,y values from deldir object using RDotNet - c#

Background
I am using RDotNet to run an R script that performs a voronoi tessellation using the deldir package. After
R:tiles = tile.list(voro) I wish to extract R:tiles[[i]][c("x","y")] for the each tile i into a C#:List<Tuple<double,double>>.
Issue 1
I can extract the R:tiles object into C#-world using var tiles = engine.Evaluate("tiles").AsVector().ToList(); but I am struggling to understand how to use RDotNet to extract the x, y values for each tile from this point:
I don't know how to iterate over this object to extract the x, y values that I desire.
Issue 2
Alternatively, I attempted to create a new simpler object in R, i.e. values and attempt to extract a string and parse values from that. So far I have only created this object for one of the points:
R: e.g.
values <- tiles[[1]][c("x","y")]
C#: e.g.
var xvalues = engine.Evaluate("values[\"x\"]").AsCharacter();
var yvalues = engine.Evaluate("values[\"y\"]").AsCharacter();
// Some boring code that parses the strings, casts to double and populates the Tuple
However I can only extract one string at a time and have to split the string to obtain the values I'm after. This does not seem like the way I should be doing things.
Question
How can extract the x,y coordinates for every tile from R:tiles[[i]][c("x","y")] into a C#:List<Tuple<double,double>>?

I think you are after something like the following if I got what you seek correctly. The full code I tested is committed to a git repo I've just set up for SO queries. I've tested against the NuGet package for 1.5.5; note to later readers that subsequent versions of R.NET may let you use other idioms.
var res = new List<List<Tuple<double, double>>>();
// w is the result of tile.list as per the sample in ?tile.list
var n = engine.Evaluate("length(w)").AsInteger()[0];
for (int i = 1; i <= n; i++)
{
var x = engine.Evaluate("w[[" + i + "]]$x").AsNumeric().ToArray();
var y = engine.Evaluate("w[[" + i + "]]$y").AsNumeric().ToArray();
var t = x.Zip(y, (first, second) => Tuple.Create(first, second)).ToList();
res.Add(t);
}

Related

Point-wise Multiply Column Array and Matrix using Math.Net Numerics with C#

I want to perform a point-wise multiplication of a column array with each column array/vector in a given Matrix in C# using the Math.Net Numerics library.
There is little documentation on operations like this, so far I have the code below which doesn't work. I am trying to use LINQ as I prefer that over for loops. the problem I'm having with LINQ is I can't reassign my matrix when I try to enumerate each column of my matrix as a vector and do the PointwiseMultiply() method.
Matrix fitKernel is my matrix, and I want to point-wise multiply each column by the wF column array and update my matrix fitKernel using LINQ. fitKernel is 9 x 5 Matrix, and wF is a 9 x 1 double[] array that I convert to a Vector in the LINQ below.
Matrix<double> fitKernel = Matrix<double>.Build.DenseOfColumnArrays(c1, c2, c3, c4, ones);
double[] wF = Enumerable.Repeat(1.0, 9).ToArray();
fitKernel = fitKernel.EnumerateColumns()
.Select(v => v.PointwiseMultiply(Vector<double>.Build.DenseOfArray(wF)));
The above code using the EnumerateColumns() returns an IEnumerable of vectors, but when I try to assign the value to fitKernel it complains about assigning a type of Enumerable to a Matrix.
If you are going to write a for loop, you might as well write two.
// a = double[9];
// c = Matrix<double>
for (int ic = 0; ic < c.ColumnCount; ic++)
{
for (int ir = 0; ir < c.RowCount; ir++) c[ir, ic] = a[ir] * c[ir, ic];
}
It's probably the quickest and briefest solution, but I understand it doesn't tell the reader what you have in mind. OTOH, if you going to use an enumerator, it makes sense to let it control the loop.
var va = Vector<double>.Build.DenseOfArray(a);
var ColEnum = c.EnumerateColumnsIndexed() ;
foreach (System.Tuple<int,Vector<double>> col in ColEnum)
{
Vector<double> v = (Vector<double>)col.Item2.PointwiseMultiply((Vector<double>)va);
c.SetColumn(col.Item1, v);
}
The closest I could get to your first formulation is this:
var r = c.EnumerateColumns().Select(v => v.PointwiseMultiply(va));
int i = 0;
foreach (Vector ri in r) c.SetColumn(i++, ri);
The first line returns your new columns, but you still have to insert them into your Matrix. Note that we are trusting the enumerator to bring back the columns in their natural order. It's possible to reduce this to two lines using EnumerateColumnsIndexed. It requires more detail, but eliminates possible ambiguity about column order.
By the way, it does not work to combine the PointwiseMultiply and the SetColumn in one statement like this:
var r = c.EnumerateColumnsIndexed().Select((v) => c.SetColumn(v.Item1, v.Item2.PointwiseMultiply(va)));
apparently because SetColumn is void. If anyone has a workaround, please post it.
I think I figured it out but you have to use a for loop; doesn't seem to be any easy way using LINQ:
for (int i = 0; i < fitKernel.ColumnCount; i++)
{
var v = fitKernel.Column(i);
v = v.PointwiseMultiply(Vector<double>.Build.DenseOfArray(wF));
fitKernel.SetColumn(i, v);
}

chart control - string on x axis

How do I show string values on the x axis of a chart control ? the datapoints (x & y) are both double. I have an IEnumerable containing a list of objects with 2 properties. The name of a report and an integer value indicating how many times it was run. so the integer is on the y axis and the report name is on the x axis. But I only seem to have double options for the value types. So when I create my datapoint, Im geting an error
DataPoint p1 = new DataPoint();
p1.XValue = log.ReportName; ---> this is invalid
p1.YValues = new Double[] { log.ReportTotal };
how can this be done ?
Ive tried this
reportTotal.XValueType = ChartValueType.String;
and when I plot my datapoints, Ive done this
int i = 1;
foreach (var log in this._reportLogs)
{
DataPoint p1 = new DataPoint();
p1.XValue = (double)i;
p1.YValues = new Double[] { log.ReportFrequency };
i++;
reportTotal.Points.Add(p1);
}
but now all im getting along the x axis are the number of the i varaible, how on earth do I just get the content of the text property ?
this is how I made it work
Dictionary<string, int> ReportLogs = new Dictionary<string, int>();
foreach (var log in this._reportLogs)
ReportLogs.Add(log.ReportName, log.ReportFrequency);
foreach (KeyValuePair<string, int> log in ReportLogs)
reportTotal.Points.AddXY(log.Key, log.Value);
The labels along the axis are created from the x-values and their number is determined either automatically as they fit or by setting the Interval property of the x-axis.
So their placement will not necessarily coincide with the actual DataPoints.
And you can format them but only within the normal formatting rules, ie you can't get creative with expressions to convert a number to a custom string, which seems to be just what you want: show a report name according to its number.
Other examples could be show a city from its zip code or a person name acording to emp.ID..
To gain full control you may need to use CustomLabels. They are a little bit tricky but quite useful. See several of these posts for numerous examples!
Also note: If you change the x-value type to string (which is possible : yourseries.XValueType = ChartValueType.String) these strings would show directly but you would loose the actual x-values! Usually not recommended (but possibly fine in your case)!
So if you want to can do it; however you can't prepare the DataPoint like you did. Instead you need to use the Points.AddXY method.
This will convert the strings to double (resulting in zeroes) and copy the string into the labels..:
reportTotal.Points.AddXY(log.ReportName, new Double[] { log.ReportTotal });
Update
Another way would be to set the AxisLabel of each DataPoint. For all of these to show up you may need to set the yourxaxis.Interval = 1.
So in your loop simply add
p1.AxisLabel = log.ReportName;

Microsoft Computer Vision OCR : Disable grouping text by regions

I've been using Microsoft Computer Vision to read receipts, trying to find an alternative to Abby's OCR as there is a substantial price difference.
The results I get are always grouped by regions. This obviously makes it much harder to identify the corresponding fields with their amounts.
Is there a way through Microsoft Vision or anyway at all that I can achieve the same aligned output as Abby's?
Here's an image with both results and the receipt
Ocr Results
I realize this is not a complete solution but I think it's enough to get you started.
The Computer Vision API returns a JSON result with a lines property that is just an array of objects with a boundingBox property.
These boundingBoxes are the X,Y coordinates of the top-left and bottom-right coordinates of the "square" of each phrase.
You basically need to process this array and "sort" the items based on this property.
In this JSFiddle you'll see that I'm sorting the lines by Y coordinate and then grouping them.
What's left to do is be "smarter" about the grouping - if the Y coordinates are 201 and 202 you can assume that they are on the same line and just add them to one same line, sorted by ascending X coordinate.
Code:
if (jsonResponse.status == 'Succeeded') {
var result = '';
// Sort lines by Y coordinate
jsonResponse.recognitionResult.lines.sort(function(a, b) {
var topLeftYCoordA = a.boundingBox[1];
var topLeftYCoordB = b.boundingBox[1];
if (topLeftYCoordA > topLeftYCoordB) {
return 1;
}
if (topLeftYCoordA < topLeftYCoordB) {
return -1;
}
return 0;
})
// group lines by Y coordinate
var grouped = {};
jsonResponse.recognitionResult.lines.map(function(line) {
var topLeftYcoordinate = line.boundingBox[1];
if (!grouped[topLeftYcoordinate]) {
grouped[topLeftYcoordinate] = line;
} else {
grouped[topLeftYcoordinate] += line;
}
});
Object.keys(grouped).forEach(function(yCoordinate) {
result += yCoordinate + ' - ' + grouped[yCoordinate].text + '</br>';
})
$(".right").html(result);
}
Result:

How do I bring in numbers from a text file and do math on them in c#

I am new to C#.
I am trying to bring numbers from a txt file into my program and multiply them.
The text file would be formatted like this:
1
2
3
4
5
6
7
8
9
10
I need the program to do 1x2x3x4x5x6x7x8x9x10=3628800.
This is a list of 2 million different numbers.
I can get it to output to a text file, just not input.
I have looked around and can't really see an answer.
Thanks.
You can do this with few lines of code.
var lines = File.ReadLines(fileName);
var collection = new List<int>();
foreach (var line in lines)
{
collection.AddRange(line.Split(' ').Select(n => Convert.ToInt32(n)));
}
var result = collection.Distinct().Aggregate((i, j) => i * j); // remove distinct if you don't want eliminate duplicates.
You can try this
string value1 = File.ReadAllText("file.txt");
int res = 1;
var numbers = value1.Split(' ').Select(Int32.Parse).ToList();
for(int i=0;i<numbers.Count;i++)
{
res = res * numbers[i];
}
Console.WriteLine(res);
var numbers = File.ReadAllText("filename.txt").Split(' ').Select(int.Parse); // Read file, split values and parse to integer
var result = numbers.Aggregate(1, (x, y) => x * y); // Perform multiplication
You want to multiply 2 million numbers all together, but there is a problem.
The problem is memory limitation. to hold a big number you have to use BigInteger class inside System.Numerics namespace.
You can use this reference by adding Using keyword in top of your project.
using System.Numerics;
If the compiler did not recognize Numerics then You need to add an assembly reference to System.Numerics.dll.
Your code should look like this.
string inputFilename = #"C:\intput.txt"; // put the full input file path and name here.
var lines = File.ReadAllLines(inputFilename); // put text lines into array of string.
BigInteger big = new BigInteger(1); // create the bigInt with value 1.
foreach (var line in lines) // iterate through lines
{
big *= Convert.ToInt32(line); // Multiply bigInt with each line.
}
string outputFilename = #"C:\output.txt"; // put the full output file path and name here
File.WriteAllText(outputFilename, big.ToString()); // write the result into text file
This may take a long time to complete. but this all depends on hardware that is operating. You may get memory overflow exception during this task which depends on amount of memory you have.

ILNumerics using subarrays and matfiles with structs

First question: Can ILNumerics read matfiles with struct? I couldnt make it work.
I then split the file in matlab and I would like to use it for calculations. but i have problems with the subarray function. I would like to do this:
using (ILMatFile matRead = new ILMatFile(#"C:\Temp\Dates.mat"))
{
ILArray<double> Dates = matRead.GetArray<double>("Dates");
double x = 736055-1;
double y = 736237+1;
ILArray<ILLogical> LogDates = (Dates > x && Dates < y);
}
using (ILMatFile matRead = new ILMatFile(#"C:\Temp\Power.mat"))
{
ILArray<double> power = matRead.GetArray<double>("Power");
ILArray<double> tpower = power[LogDates, full];
double avgpower = tpower.Average();
Console.WriteLine(avgpower.ToString());
Console.ReadKey();
}
This doesnt work for a number of reasons. The logical doesnt take my syntax and I dont really get why. But also the subarry in the second block doesnt work, it doesnt know the full keyword (even though the documentation says it shouldand also it doesnt like the logical. obviously I want to average tpower over all columns and only those rows where the logical condition is one.
thanks.
nik
ILLogical is an array itself. You use it like that:
ILLogical LogDates = ILMath.and(Dates > x, Dates < y);
If you still experiencing problems with the subarray, try:
ILArray<double> tpower = power[ILMath.find(LogDates), ILMath.full];
Only, if your class is derived from ILMath, you can ommit the ILMath. identifier! Otherwise, string subarray definitions are sometimes shorter:
ILArray<double> tpower = power[ILMath.find(LogDates), ":"]
In order to take the average over selected rows, reducing to one:
double avgpower = tpower.Average(); // Linq version
double avgpower = (double)ILMath.sumall(tpower) / tpower.S.NumberOfElements; // prob. faster on large data

Categories