1

I’m using OxyPlot with F#. I have code to create a single parameter histogram and plot it. My code for dual parameter histograms in the form of a contour is too time consuming. I’d like an efficient way to map two vectors or arrays into a 2D histogram. I’m including my code for regular histogram.

let myHistogram c =
flatten dataArray.[c..c,*] 
|> Seq.toArray
|> Array.map (fun x -> round(float(x)/16.0))
|> Seq.countBy (fun x -> x)
|> Seq.sort
|> Seq.map snd

So, I’m looking to take dataArray.[a…a,], dataArray[b…b,] and place them into bins of a specific resolution to create histogram[x,y]. OxyPlot needs the histogram in order to create a contour.

Imagine two arrays of data with one being called Alexa647-H and the other BV786-H. Each array contains 100,000 integers ranging between 0 and 10,000. You could plot these arrays as a dot plot in OxyPlot. That is straight forward, simply plot one array for the X-Axis and one array for the Y-Axis. I've included a plot below.

My question involves creating a contour plot out of the same data. For that, I need to first determine a resolution, say for convenience 100x100. Therefore I want to end up with a 2D array call hist2(100,100). The array is basically 10,000 bins of 1000x1000 in size. Each bin contains the count of elements which fall into a particular range -- a 2D histogram.

Dot and Contour

The coding example in OxyPlot generates a peak array mathematically. I want to generate that contour input peak array as outline above, instead.

    var model = new PlotModel { Title = "ContourSeries" };

double x0 = -3.1;
double x1 = 3.1;
double y0 = -3;
double y1 = 3;

//generate values
Func<double, double, double> peaks = (x, y) => 3 * (1 - x) * (1 - x) * Math.Exp(-(x * x) - (y + 1) * (y + 1)) - 10 * (x / 5 - x * x * x - y * y * y * y * y) * Math.Exp(-x * x - y * y) - 1.0 / 3 * Math.Exp(-(x + 1) * (x + 1) - y * y);
var xx = ArrayBuilder.CreateVector(x0, x1, 100);
var yy = ArrayBuilder.CreateVector(y0, y1, 100);
var peaksData = ArrayBuilder.Evaluate(peaks, xx, yy);

var cs = new ContourSeries
{
        Color = OxyColors.Black,
        LabelBackground = OxyColors.White,
        ColumnCoordinates = yy,
        RowCoordinates = xx,
        Data = peaksData
};
model.Series.Add(cs);

Plot generated by OxyPlot code

I hope this clears things up.

Don

dgp
  • 13
  • 4
  • Maybe you should add the `oxyplot` tag to attract knowledgeable users. – AMieres Oct 11 '18 at 20:42
  • To get a clearer idea of what you want, could you add a mock or a sample of the input data and also the output data? – AMieres Oct 11 '18 at 20:44
  • Your `Seq.toArray` step followed by `Array.map` is unnecessary. There's a `Seq.map` function (though if you were looking at old documentation you might not know about it). So your first two steps can be replaced with `Seq.map (fun x -> round(float(x)/16.0))`. That might save you some time. – rmunn Oct 12 '18 at 04:31
  • Also, `fun x -> x` can be replaced with the built-in `id` function: `Seq.countBy (fun x -> x)` would become `Seq.countBy id`. This probably won't have any performance benefits since I think the compiler is smart enough to see that `fun x -> x` is a do-nothing function, but `Seq.countBy id` is an F# idiom that people are used to seeing, so it'll make your code clearer to make that change. – rmunn Oct 12 '18 at 04:35
  • Like @AMieres, I'm having trouble understanding what you want to do - could you perhaps give some sample input data and sample result that you'd like to get? – Tomas Petricek Oct 12 '18 at 09:29

0 Answers0