Open SuperDaveOsbourne opened 6 years ago
Not yet, but I will add one when I find some time. Is there any particular example from http://plplot.sourceforge.net/examples.php that you'd like translated to C#?
I have this so far but am confused how to pass the command line parameters in code or if they would even work. With the new .core ML stuff I wanted something in line to test with until there are GUI versions of .net core 3.x. I saw your comment on that blog about using PlplotNet.
Ideally would want to programatically select the output type (SVG) #6 and the file name, ala test.svg without having to manually select them.
using PLplot; using System;
namespace ExampleX00 { internal static class Program { private static void Main(string[] args) {
var pl = new PLStream();
const int nSize = 100;
const int yMax = 100;
const int xMin = 0;
const int xMax = 1;
const int yMin = 0;
var x = new double[nSize];
var y = new double[nSize];
for (var i = 0; i <= nSize - 1; i++)
{
x[i] = ((double)i / (double)(nSize - 1));
y[i] = yMax * x[i] * x[i];
}
string[] arg = {""};
pl.parseopts(ref arg, ParseOpts.Full & ParseOpts.NoProgram);
// Initialize plplot
pl.init();
pl.env( xMin, xMax, yMin, yMax, AxesScale.Independent, AxisBox.BoxTicksLabelsAxes );
pl.lab( "x", "y=100 x#u2#d", "Simple PLplot demo of a 2D line plot" );
pl.line( x, y );
// Plplotnet version info
pl.gver(out var verText);
Console.WriteLine("PLplot version = " + verText);
Console.WriteLine(Environment.NewLine);
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
}
Got the SVG device working but that is it. pngcairo generates empty files. wincario just hangs. Not sure if or how that GTK+ drivers are accessed through managed code. Here is my example
using PLplot; using System; using System.Reflection;
namespace ExampleSineWaves { internal static class Program { private static void Main(string[] args) { const double sineFactor = 0.012585; const int exampleCount = 1000; var phaseOffset = 125;
var x0 = new double[exampleCount];
var y0 = new double[exampleCount];
for (var j = 0; j < exampleCount; j++)
{
x0[j] = j;
y0[j] = (double)(System.Math.Sin(sineFactor * (j + phaseOffset)) * 1);
}
var x1 = new double[exampleCount];
var y1 = new double[exampleCount];
phaseOffset = 250;
for (var j = 0; j < exampleCount; j++)
{
x1[j] = j;
y1[j] = (double)(System.Math.Sin(sineFactor * (j + phaseOffset)) * 1);
}
var x2 = new double[exampleCount];
var y2 = new double[exampleCount];
phaseOffset = 375;
for (var j = 0; j < exampleCount; j++)
{
x2[j] = j;
y2[j] = (double)(System.Math.Sin(sineFactor * (j + phaseOffset)) * 1);
}
var x3 = new double[exampleCount];
var y3 = new double[exampleCount];
phaseOffset = 500;
for (var j = 0; j < exampleCount; j++)
{
x3[j] = j;
y3[j] = (double)(System.Math.Sin(sineFactor * (j + phaseOffset)) * 1);
}
var pl = new PLStream();
string[] arg = {""};
pl.parseopts(ref arg, ParseOpts.Full & ParseOpts.NoProgram);
// set background color r g b
pl.scolbg(25, 25, 25);
// ps PostScript File (monochrome)
// psc PostScript File (color)
// xfig Xfig file
// null Null device
// mem User-supplied memory device
// svg Scalable Vector Graphics (SVG 1.1)
// pdfcairo Cairo PDF Driver
// epscairo Cairo EPS Driver
// pscairo Cairo PS Driver
// svgcairo Cairo SVG Driver
// pngcairo Cairo PNG Driver
// memcairo Cairo memory driver
// extcairo Cairo external context driver
// wincairo Cairo Microsoft Windows driver
// set the device: I couldn't get any other than the vanilla svg driver to work
// do you have to install the cairo drivers or do they have to be compiled in plplot.net aready?
// I don't see any error messages.
pl.sdev("svg");
// set the output file name
pl.sfnam("test.svg");
// Initialize plplot
pl.init();
const int xMin = 0;
const int xMax = 1000;
const int yMin = -1;
const int yMax = 1;
pl.env(xMin, xMax, yMin, yMax, AxesScale.Independent, AxisBox.BoxTicksLabelsAxes);
// Set scaling for mail title text 125% size of default
pl.schr(0,1.25);
// The main title
pl.lab("X", "Y", "PLplot demo of four sine waves");
//0 black (default background)
//1 red (default foreground)
//2 yellow
//3 green
//4 aquamarine
//5 pink
//6 wheat
//7 grey
//8 brown
//9 blue
//10 BlueViolet
//11 cyan
//12 turquoise
//13 magenta
//14 salmon
//15 white
pl.col0(9);
pl.line(x0, y0);
pl.col0(1);
pl.line(x1, y1);
pl.col0(2);
pl.line(x2, y2);
pl.col0(4);
pl.line(x3, y3);
// Plplotnet version info
pl.gver(out var verText);
// tested version version = 5.13.0
Console.WriteLine("PLplot Version Number = " + verText);
Console.WriteLine(Environment.NewLine);
// Tested Net Core Version Number = 2.1.0
Console.WriteLine("Net Core Version Number = " + GetNetCoreVersion());
Console.WriteLine(Environment.NewLine);
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
public static string GetNetCoreVersion()
{
//https://github.com/dotnet/BenchmarkDotNet/issues/448
var assembly = typeof(System.Runtime.GCSettings).GetTypeInfo().Assembly;
var assemblyPath = assembly.CodeBase.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
int netCoreAppIndex = Array.IndexOf(assemblyPath, "Microsoft.NETCore.App");
if (netCoreAppIndex > 0 && netCoreAppIndex < assemblyPath.Length - 2)
return assemblyPath[netCoreAppIndex + 1];
return null;
}
}
}
I've added an example based on your code at https://github.com/surban/PLplotNet/blob/master/Samples/CSharp/SineWaves/Program.cs.
Your code is working fine on my machine after I've removed the call to parseopts
. It is only really necessary when you want to use the PLplot command options parser. I've also added a call to pl.eop
in the end to make sure that the resulting SVG is written to disk.
Are you working on Linux or Windows? On Windows all drivers are shipped in the NuGet package and you don't need to install anything. On Linux, PLplot and the necessary backend needs to be installed using your distribution's package manger.
Direct output the PNG is also working fine for me. For that I've used the following two lines:
pl.sdev("pngcairo");
pl.sfnam("SineWaves.png");
Yes since the SVG worked without pl.eop
I wasn't looking for it.
Now on my list:
Now off to work on that stuff and will update demos for those. Still something that will visually show trees in .core on Windows 10.
Thanks for the hard work!
For trees you might want to try https://www.nuget.org/packages/GraphViz.NET/. I haven’t used the NET Binding, but I know that GraphViz itself is very popular.
I ran the above example but keep running into this issue on Windows 7 with .NET Framework 4.6.2 VisualStudio2017 Pro:
System.TypeInitializationException HResult=0x80131534 Message=The type initializer for 'PLplot.Native' threw an exception. Source=PLplotNet StackTrace: at PLplot.Native.mkstrm(Int32& p_strm) at PLplot.PLStream..ctor() in PLStream.cs:line 24 at Program.Main(String[] args) in Program.cs:line 68
Inner Exception 1: InvalidOperationException: Cannot find support PLplot support files in System.String[].
More info - I installed using NuGet Package Manager
Fix - Manually copy over \packages\PLplot.5.13.7\runtimes\win-x64\native\ to the debug or release folder.
Strangely, running a console app with .Net core does not have this issue.
Fix - Manually copy over \packages\PLplot.5.13.7\runtimes\win-x64\native\ to the debug or release folder.
I tried this, but then the following line errors:
_putenv_s("PLPLOT_LIB", supPath);
(Not using .net core, fwiw)
Also having the same issue
dotnet add package PLplot
Microsoft Visual C++ Redistributable 2017 (was already installed, I clicked repair and restarted my machine).
Running via dotnet run
---> System.InvalidOperationException: Cannot find support PLplot support files in System.String[].
at PLplot.Native..cctor() in C:\projects\plplotnet\PLplotNet\NativeHelpers.cs:line 200
--- End of inner exception stack trace ---
at PLplot.Native.mkstrm(Int32& p_strm)
at PLplot.PLStream..ctor() in C:\projects\plplotnet\PLplotNet\PLStream.cs:line 24
at Program.Main(String[] args) in D:\repos\ML.Net\Program.cs:line 53
Or running in visual studio 2019
using System;
using Microsoft.ML;
using Microsoft.ML.Data;
using PLplot;
class Program
{
public class HouseData
{
public float Size { get; set; }
public float Price { get; set; }
}
public class Prediction
{
[ColumnName("Score")]
public float Price { get; set; }
}
static void Main(string[] args)
{
var mlContext = new MLContext();
{
// 1. Import or create training data
var trainingData = mlContext.Data.LoadFromEnumerable(
new HouseData[]
{
new HouseData() { Size = 1.1F, Price = 1.2F },
new HouseData() { Size = 1.9F, Price = 2.3F },
new HouseData() { Size = 2.8F, Price = 3.0F },
new HouseData() { Size = 3.4F, Price = 3.7F }
});
// 2. Specify data preparation and model training pipeline
var pipeline = mlContext.Transforms.Concatenate("Features", new[] { "Size" })
.Append(mlContext.Regression.Trainers.Sdca(
labelColumnName: "Price",
maximumNumberOfIterations: 100));
// 3. Train model
var model = pipeline.Fit(trainingData);
// 4. Make a prediction with test data
var testingData = new HouseData() { Size = 2.5F };
var price = mlContext.Model.CreatePredictionEngine<HouseData, Prediction>(model)
.Predict(testingData);
Console.WriteLine($"Predicted price for size: {testingData.Size * 1000} sq ft= {price.Price * 100:C}k");
// Predicted price for size: 2500 sq ft= $261.98k
}
// 5. Visualize our data
var pl = new PLStream();
pl.sdev("svg");
pl.sfnam("linear-regression.svg");
pl.spal0("cmap0_alternate.pal");
pl.init();
const int xMin = 0;
const int xMax = 1000;
const int yMin = -1;
const int yMax = 1;
pl.env(xMin, xMax, yMin, yMax, AxesScale.Independent, AxisBox.BoxTicksLabelsAxes);
pl.schr(0, 1.25);
pl.lab(nameof(HouseData.Size), nameof(HouseData.Price), "Linear regression plot of house price for size");
pl.eop();
}
}
I am just setting up the plotting of the linear data above, haven't set the data yet. As I cannot even get it to load the PLStream
. If your curious of what I am doing, I am doing the Hello ML.Net World example
Hi,
I had the same issue with Win10 and .NetCore 3.0 today.
---> System.InvalidOperationException: Cannot find support PLplot support files in System.String[]. at PLplot.Native..cctor() in C:\projects\plplotnet\PLplotNet\NativeHelpers.cs:line 200
My solution was to copy the runtimes folder with the dlls 2 directories upward! The init is looking 2 folders upward too.
Following up on @saskathex's correct post, here is a concrete example...
Example on my system… Copy the “runtimes” folder up 2 levels into the “bin” folder. FROM ==> M:\ProjectFolder\bin\Debug\netcoreapp3.1\ TO ==> M:\ProjectFolder\bin
See comment (cut/paste below) from this link: https://github.com/surban/PLplotNet/blob/eed9c8796c037c0df539247b9c5bbc63f10afc34/PLplotNet/NativeHelpers.cs You can see there in the NativeHelpers.cs code that it is looking for the plplot directory (via its path), 2 levels up.
// For PLplot to find its support files, the environment variable
// PLPLOT_LIB must be set accordingly.
string[] supPaths = {
Path.Combine(libDir, "plplot"),
Path.Combine(libDir, "..", "..", "runtimes", "win-x64", "native", "plplot")
};
Thank you for your research and a solution @saskathex !
Adapting the sample as a Windows Forms app and running inside Visual Studio, I also hit the exception about not finding the support files.
The two-folders-up trick didn't work for me (ProcMon didn't show that folder being searched for plplot.dll).
What worked for me was adding this Pre-Build Event to the project:
rem VS runs this in $(OutDir)
rem /E includes sub-dirs
rem /NP avoids progress updates
rem /NFL avoids listing files
Robocopy $(ProjectDir)packages\PLplot.5.13.7\runtimes\win-x64\native . /E /NP /NFL
rem Exit codes 0 to 7 mean success
IF %ERRORLEVEL% LEQ 7 exit /B 0
This copies the contents of the native folder into the same folder where the executable will be produced. Robocopy skips files that are already in the destination.
After getting past this exception I hit another because the PLplot libraries are 64-bit. The fix is to de-select "Prefer 32-bit" in Project, Properties, Build (my Platform target is 'Any CPU').
Same issue here with a .NET Core 3.1 console app. Fix copying the native PLPlot directory into bin/debug(release)/netcoreapp3.1
Quick copy/paste fix that works for me:
<Target Name="CopyFiles" AfterTargets="Build">
<ItemGroup>
<PlotFiles Include="$(TargetDir)runtimes\win-x64\native\**\*.*" />
</ItemGroup>
<Message Text="Executing AfterBuild copy files task" Importance="High" />
<Copy SourceFiles="@(PlotFiles)" DestinationFolder="$(TargetDir)%(RecursiveDir)" ContinueOnError="true" />
<Message Text="AfterBuild copy files task completed" Importance="High" />
</Target>
Paste the above into your .csproj directly inside the <Project>
tags.
The needed files are in a sub directory of the output folder after build. As others have mentioned, files for the runtime identifier need to be copied up a couple levels into the output folder.
Tested on:
Windows
VS 2019 / net 5
PLplot 5.13.7
Quick copy/paste fix that works for me:
<Target Name="CopyFiles" AfterTargets="Build"> <ItemGroup> <PlotFiles Include="$(TargetDir)runtimes\win-x64\native\**\*.*" /> </ItemGroup> <Message Text="Executing AfterBuild copy files task" Importance="High" /> <Copy SourceFiles="@(PlotFiles)" DestinationFolder="$(TargetDir)%(RecursiveDir)" ContinueOnError="true" /> <Message Text="AfterBuild copy files task completed" Importance="High" /> </Target>
Paste the above into your .csproj directly inside the
<Project>
tags.The needed files are in a sub directory of the output folder after build. As others have mentioned, files for the runtime identifier need to be copied up a couple levels into the output folder.
Tested on:
Windows
VS 2019 / net 5
PLplot 5.13.7
Works fine for me!
I see two F# examples, any chance there are any C# examples.