Showing posts with label data visulization. Show all posts
Showing posts with label data visulization. Show all posts

Dec 29, 2014

How to Call Gnuplot from C# (WPF)

Two years ago, I've written a post on how to call gnuplot from C++. It turns out the most viewed post of my posts. If you're missing it, click here.

Now as I am developing an UI for my program, I begin to use C# now. And here the old problem comes back again: how to call gnuplot from C#.

Instead of using Foms of C#, I get used to using WPF. However, as we are talking about the C#, so it should work in both structures.

Here we go -- How to call gnuplot from C#.

I'll skip the basics of C# and assume that you all know how to start a project (here I use desktop WPF) or create a button click event.

1 At you design view, create a button click, all the coding we're going to do is just within this event. So it has the most flexibility for using elsewhere.







2  Preparation. Only two preparation we need: 


a, add " using System.IO;" and "using System.Diagnostics" at the top of the file (as you can see in the previous picture). In WPF, these are not added by default. So don't forget to add them before you procceed.


b. download and copy the gnuplot folder to the location where your setup would be. I recommend download the "gp466-win32.zip" and unzip it then you get a folder named "gnuplot". I put it under the debug folder as shown in this picture. You can put it any where as you like, later in the code we have to specify the location of it.


3 set up a new process and specify the path of gnuplot, using StreamWriter to communicate with gnuplot. I will give three examples here to show the usage.


3.1 Simple case: function plot:


 private void Button_Click(object sender, RoutedEventArgs e)
       {
           Process plotProcess = new Process();
           plotProcess.StartInfo.FileName = @"D:\Project\VisualGnuplot\VisualGnuplot\bin\Debug\gnuplot\bin\gnuplot.exe";
           plotProcess.StartInfo.UseShellExecute = false;
           plotProcess.StartInfo.RedirectStandardInput = true;        
           plotProcess.Start();
           StreamWriter sw = plotProcess.StandardInput;
           String strInputText = "plot sin(x)\n";
           sw.WriteLine(strInputText);
           sw.Flush();
           

      MessageBox.Show("Close the gnuplot Window? " );
      sw.Close();           
      plotProcess.Close();
}
Then debug it. if you click on the button, it should appear like this:


notice that if I added a MessageBox to keep the gnuplot window. If you omit it, there will be only a flash and you can't see anything. Another thing is that here the output terminal for gnuplot is the interactive mode, so it's very convenient for a single plot use. For example, in 3D plot you could change the view with mouse.

3.2 normal case: plot external data file.


here suppose that we have a "3d.txt" file whose content is like (don't forget to include # as comment and blank line for 3D plot in gnuplot! I put this data file under the Debug folder as well, you can see this from previous screenshot):
# X Y Z
0 1 2
0 2 4
0 3 8
0 4 16
0 5 32
1 1 5
1 2 3
1 3 5
1 4 3
1 5 5
2 1 32
2 2 16
2 3 8
2 4 4
2 5 2
3 1 3
3 2 9
3 3 27
3 4 81
I purposedly write only four elements in "3" while for "0" to "2" each of them has five element to indicate that you don't have to have the same shape in 3D line plot.

what we need to do is modify the code sent to gnuplot. Simply as it is:

private void Button_Click(object sender, RoutedEventArgs e)
       {
           Process plotProcess = new Process();
           plotProcess.StartInfo.FileName = @"D:\Project\VisualGnuplot\VisualGnuplot\bin\Debug\gnuplot\bin\gnuplot.exe";
           plotProcess.StartInfo.UseShellExecute = false;
           plotProcess.StartInfo.RedirectStandardInput = true;        
           plotProcess.Start();
           StreamWriter sw = plotProcess.StandardInput;
           //String strInputText = "plot sin(x)\n";
           String strInputText = "splot \"3d.txt\" using 1:2:3 with lines\n";
           sw.WriteLine(strInputText);
           sw.Flush();        
           MessageBox.Show("Close the gnuplot Window? " );
           sw.Close();
           plotProcess.Close();
                  } 

Now the result is:


I think now you have get a sense on how to use it now. Like in the C++ case, we sent all the commands to the gnuplot and let it work. But pratically, we need lots of settings to plot a graph we want, such as colors, labels and legends. Most of the case, we'd like the ability to derectly output the image itself. I think now you should know how to do it. So let's give a simple last example to show how to do it: plot an external data file and output the image.

3.3 plot an external data file and with external plot setting file

suppose we write another file "sp.plt" like this:

set terminal pngset output "plot.png"
splot "3d.txt" using 1:2:3 with lines
and now we read in these commands with StreamReader (not StringReader as I was cheated by the auto correction!)
       private void Button_Click(object sender, RoutedEventArgs e)
       {
           Process plotProcess = new Process();
           plotProcess.StartInfo.FileName = @"D:\Project\VisualGnuplot\VisualGnuplot\bin\Debug\gnuplot\bin\gnuplot.exe";
           plotProcess.StartInfo.UseShellExecute = false;
           plotProcess.StartInfo.RedirectStandardInput = true;        
           plotProcess.Start();
           StreamWriter sw = plotProcess.StandardInput;
           //String strInputText = "plot sin(x)\n";
           //String strInputText = "splot \"3d.txt\" using 1:2:3 with lines\n";
           String strInputText;
           StreamReader sr = new StreamReader("sp.plt");
           strInputText = sr.ReadToEnd();
           sr.Close();
           sw.WriteLine(strInputText);
           sw.Flush();        
          // MessageBox.Show("Close the gnuplot Window? " );
           sw.Close();
           plotProcess.Close();
           }

note that because we output the image, so we don't need the gnuplot window again. This will be handful when we have lots of files to plot. And there should be a png file generated now.
(a window flashed and disappeared)



Summary:


Now we could use the gnuplot from C# in a flexible way. Further thing you might be interested is as following: a. on the designer view design the setting pannel; b, write the setting parameters from the user and save it to a plot setting file; c, plot the data (ouput from code or external ones) to image; d, display the image as you want to the window.

PS. I'm quite busy with my work so I didn't check the comments very often. But you can still leave your comments there that might be helpful for other readers or I will reply to it when I see it.







May 14, 2012

How to call Gnuplot from C++

When I have do the simulation to our physics problem, I have many data files that I want to visualize. It's not an easy work, if you are a new C++ user like me. After searching around the internet, finally I got the solution pretty nice. Here is how.

1 download and intall

go to  gnuplot.info to download the windows installer and install it (The newest edition is 4.6 till this document). Make sure that you choose "add PATH to my system" in the process of installation, or you have to add by your own. (Thanks the gnuplot team adding this for us).

2 create a general purpose head file

create a new .h file with this following content(or you can download it here):

#ifndef GNUPLOT_H_
#define GNUPLOT_H_
#include <string>
#include <iostream>
using namespace std;
class Gnuplot {
public:
Gnuplot() ;
~Gnuplot();
void operator ()(const string & command);
// send any command to gnuplot
protected:
FILE *gnuplotpipe;
};
Gnuplot::Gnuplot() {
// with -persist option you will see the windows as your program ends
//gnuplotpipe=_popen("gnuplot -persist","w");
//without that option you will not see the window
 // because I choose the terminal to output files so I don't want to see the window
 gnuplotpipe=_popen("gnuplot","w");
if (!gnuplotpipe) {
cerr<< ("Gnuplot not found !"); }
}
Gnuplot::~Gnuplot() {
fprintf(gnuplotpipe,"exit\n");
_pclose(gnuplotpipe);
}
void Gnuplot::operator()(const string & command) {
fprintf(gnuplotpipe,"%s\n",command.c_str());
fflush(gnuplotpipe);
// flush is necessary, nothing gets plotted else
};
#endif

3 use the head file and plot

 now you have a class of gnuplot, so you can initialize it with object and send the command directly to gnuplot. If you don't know what I mean, check the example I use to test under Windows(example.cpp)

#include <iostream>
#include "gnuplot.h"
using namespace std;
int main(){
Gnuplot plot;
plot("plot sin(x)") ;
system("pause");
plot("plot cos(x)") ;
system("pause");
return 0;
}

Others:

The good side is that you can customize what you want to plot and make it automatically done for you.
The bad side is that it is the same usage as gnuplot itself. I mean, if you have to plot the simulation results, you have to output them then read in and plot the graph out. If you concerns only on the graph instead of the output data files, you will find that the most time-consuming thing for C++ is output files. If you have better solution for this( directly plot with a data structure), please let me know. I know there's some pipe written for this but they just don't work for me. Maybe you have better suggestion. Thanks.