Making C code plot a graph automatically - c

I have written a program which writes a list of data to a '.dat' file with the intention of then plotting it separately using gnuplot. Is there a way of making my code plot it automatically? My output is of the form:
x-coord analytic approximation
x-coord analytic approximation
x-coord analytic approximation
x-coord analytic approximation
x-coord analytic approximation
....
Ideally, when I run the code the graph would also be printed with an x-label, y-label and title (which could be changed from my C code). Many thanks.

I came across this while searching for something else regarding gnuplot. Even though it's an old question, I thought I'd contribute some sample code. I use this for a program of mine, and I think it does a pretty tidy job. AFAIK, this PIPEing only works on Unix systems (see the edit below for Windows users). My gnuplot installation is the default install from the Ubuntu repository.
#include <stdlib.h>
#include <stdio.h>
#define NUM_POINTS 5
#define NUM_COMMANDS 2
int main()
{
char * commandsForGnuplot[] = {"set title \"TITLEEEEE\"", "plot 'data.temp'"};
double xvals[NUM_POINTS] = {1.0, 2.0, 3.0, 4.0, 5.0};
double yvals[NUM_POINTS] = {5.0 ,3.0, 1.0, 3.0, 5.0};
FILE * temp = fopen("data.temp", "w");
/*Opens an interface that one can use to send commands as if they were typing into the
* gnuplot command line. "The -persistent" keeps the plot open even after your
* C program terminates.
*/
FILE * gnuplotPipe = popen ("gnuplot -persistent", "w");
int i;
for (i=0; i < NUM_POINTS; i++)
{
fprintf(temp, "%lf %lf \n", xvals[i], yvals[i]); //Write the data to a temporary file
}
for (i=0; i < NUM_COMMANDS; i++)
{
fprintf(gnuplotPipe, "%s \n", commandsForGnuplot[i]); //Send commands to gnuplot one by one.
}
return 0;
}
EDIT
In my application, I also ran into the problem that the plot doesn't appear until the calling program is closed. To get around this, add a fflush(gnuplotPipe) after you've used fprintf to send it your final command.
I've also seen that Windows users may use _popen in place of popen -- however I can't confirm this as I don't have Windows installed.
EDIT 2
One can avoid having to write to a file by sending gnuplot the plot '-' command followed by data points followed by the letter "e".
e.g.
fprintf(gnuplotPipe, "plot '-' \n");
int i;
for (int i = 0; i < NUM_POINTS; i++)
{
fprintf(gnuplotPipe, "%lf %lf\n", xvals[i], yvals[i]);
}
fprintf(gnuplotPipe, "e");

You can either create a gnuplot script and spawn a process running gnuplot to plot this script from the commandline, or you may use one of the provided interfaces. For C, there is a POSIX pipe-based interface from Nicolas Devillard available here:
http://ndevilla.free.fr/gnuplot/
...and an iostream-based C++ version is available via git (see: http://www.stahlke.org/dan/gnuplot-iostream/ )
The most portable and probably the easiest way would still be calling gnuplot to plot a script, though. As sje397 mentioned, check your documentation for the system() call in stdlib.h.
On a sidenote, there is also GNU plotutils, which offers libplot, a library for plotting datasets, which you could use in your application. See: http://www.gnu.org/software/plotutils/

Although I've seen a lot of ways of doing this, the most simplest way of doing this would be by using the system() (from stdlib.h) function in C.
First make a gnuplot script and save it as "name.gp" (neither the name nor the extension matter).
A simple script would be,
plot 'Output.dat' with lines
After saving this script file, just add
system("gnuplot -p name.gp");
at the end of your code.
It's as simple as that.
Make sure to add gnuplot path to the Windows System Path variables.

I've adapted the accepted answer to plot a float array while avoiding the use of a temporary file. In it, float* data_ is the array and size_t size_ its size. Hopefully it is helpful for someone!
Cheers,
Andres
void plot(const char* name="FloatSignal"){
// open persistent gnuplot window
FILE* gnuplot_pipe = popen ("gnuplot -persistent", "w");
// basic settings
fprintf(gnuplot_pipe, "set title '%s'\n", name);
// fill it with data
fprintf(gnuplot_pipe, "plot '-'\n");
for(size_t i=0; i<size_; ++i){
fprintf(gnuplot_pipe, "%zu %f\n", i, data_[i]);
}
fprintf(gnuplot_pipe, "e\n");
// refresh can probably be omitted
fprintf(gnuplot_pipe, "refresh\n");
}

I know it's too late, but answering if it may help someone.
fputs really does the job, you want. first you need to print the data you want to plot in a temporary file data.temp.
FILE *pipe_gp = popen("gnuplot -p", "w");
fputs("set terminal png \n",pipe_gp);
fputs("set output 'abc.png' \n",pipe_gp);
fputs("set xlabel 'f' \n",pipe_gp);
fputs("set xrange [0:100] \n",pipe_gp);
fputs("set yrange [0:100] \n",pipe_gp);
fputs("plot 'data.temp' u 1:2 w circles lc rgb 'pink' notitle \n",pipe_gp);
pclose(pipe_gp);

Related

C language / How to read input from one file and write an output to another file

I am having a problem with reading input from one file and write an output to another file.
here is my code
#include <stdio.h>
#include <math.h>
//Variables declarations
FILE *reportfile;
FILE *inputfile;
char ratioName[20];
char nameorganization[25];
int asset1,asset2,asset3;
int lia1,lia2,lia3;
float asset;
float liabilites;
float ratio;
int ave_asset;
int ave_liabilites;
float ave_ratio;
char year[5]
//char currentasset[15];
//char currentLia[30];
//char tekstRatio[45];
//void
void ReadingData(void);
void DoCalcs(void);
void Report(void);
int main(void) {
ReadingData();
DoCalcs();
Report();
return 0;
}
void ReadingData(void){
inputfile = fopen("c:\\class\\current.txt" , "r");
fgets(nameorganization,25, inputfile);
fscanf(inputfile,"%d%d\n", &asset1, &lia1);
fscanf(inputfile,"%d%d\n", &asset2, &lia2);
fscanf(inputfile,"%d%d", &asset3, &lia3);
fclose(inputfile);
}
void DoCalcs(void){
ratio = asset / liabilites;
ave_asset = (asset1 + asset2 + asset3) / 3;
ave_liabilites = (lia1 + lia2 + lia3) / 3;
ave_ratio = ratio / 3;
}
void Report(void){
reportfile = fopen("c:\\class\\alimbetm_cr.txt","w");
fprintf(reportfile,"\n");
fprintf(reportfile,"Current Ratio Report",ratioName);
fprintf(reportfile,"Year");
//fprintf(reportfile,"Current Asset",currentasset);
}
//void GettingInfo(void){
//printf("Please type ratio: ");
//scanf();
//}
when I run it , it saves file to new disk but removes old data, that is NOT what I want.
What I want is read input/data from one file and write bot input/output to another file without removing input.
This is input file data (current.txt)
Hi-Tech Leisure Products
47900 31007
34500 9100
57984 14822
This how it should be on a new file
Hi-Tech Leisure Products
Current Ratio Report
Current Current Current
Year Assets Liabilities Ratio
----------------------------------------------------------
2010 47900 31007 1.54
2011 34500 9100 3.79
2012 57984 14822 3.91
----------------------------------------------------------
Average 46795 18310 3.08
This report produced by Raul Jimenez.
please help
In this case, you need to use "a" instead of "w" because write function is used to clear the old data and write the new one
The posted code does not compile! The first problem is this statement:
char year[5]
which is missing the trailing semicolon ;.
regarding:
#include <math.h>
None of the 'features' of math.h are being used in the posted code. It is a very poor programming practice to include header files those contents are not being used. Suggest removing that statement.
regarding:
reportfile = fopen("c:\\class\\alimbetm_cr.txt","w");
The mode w causes the output file to be truncated to 0 length.
Since you want to keep the old contents of the output file and simply add more data. Strongly suggest using;
reportfile = fopen("c:\\class\\alimbetm_cr.txt","a");
where the mode a will open the output file in append mode so the new data is added to the end of the existing file.
Of course, always check reportfile to assure it is not NULL (I.E. the call to fopen() was successful.
Note this statement does not compile:
fprintf(reportfile,"Current Ratio Report",ratioName);
because it has a parameter but no matching 'output format conversion' specifier. Suggest (in this case) dropping the parameter: ratioName
the calls to fopen() and fclose() are scattered all over the code. As it is currently written, only one record will be read from the input file and only one record will be written to the output file. This will be a major problem when the input file contains multiple records.
the 'desired output' indicates that the first thing should be: "Hi-Tech Leisure Products" then: "Current Ratio Report" however, there is no statement (in Report()) to actually output that second statement AND the char array ratioName[] is never set to any specific value.
the 'desired output' indicates 2 lines of column headers, etc but there is no code to actually output those column headers ( other than year ). Similar considerations exist for the data lines, the Average: line, the author line. Each datum of each line needs to be specifically output by the code, they will not 'magically' appear in the output file.
regarding;
ratio = asset / liabilites;
Neither asset nor liabilites is ever set to any specific value so they will be (due to where they are declared) containing the value(s) 0.0f. So this division will result in a DIVIDE BY ZERO crash of the code.
There are plenty more problems, but the above should get you started in the right direction.

Opening files in C in Xcode

#include <stdio.h>
#include <math.h>
int main(void) {
int i=0;
int number =0;
float vector[100];
float sum=0., mean = 9., stdev=0.;
FILE *fp_in = NULL;
fp_in = fopen("stat_data.txt","r");
if(fp_in != NULL)
{
fscanf(fp_in,"%d",&number);
for (i=0; i < number; i++)
{
fscanf(fp_in, "%f", &vector[i]);
sum += vector[i];
}
mean = sum/number;
printf("Mean = %f\n",mean);
sum=0.0;
for(i=0; i<number;i++)
{
sum+= pow(vector[i]-mean,2);
}
stdev = sqrt(sum/(number - 1));
printf("standard deviation is %f\n", stdev);
}
else
{
printf("Opening of file stat_data.txt failed\n");
}
return 0;
}
I'm trying to open the text file "stat_data" in Xcode and it works on a linux computer, but it doesn't seem to work on Xcode. I think there's something wrong with the settings but I don't know what it could be.
Screenshot of the IDE showing where the stat_data.txt is placed -
This happened because the place where the Xcode created de binary file is different where your txt file is locate.
So I put my txt file in the same directory of my binary (readFile).
In the picture I list where my source and binary file are locate.
If you don't know where your binary file is. You can show it f you don't know where your binary file is. You can show it using the "show in finder".
So my result is it:
File opened.
Because you do not specify a path to the file name when you open it, the program expects the file to be in the current working directory which is set by Xcode when you run the program in Xcode and set by the shell when you run the program from the command line (as the directoy you are in when you run it).
There are two ways to get around this:
specify an absolute path when you open the file e.g.
/Users/thiagmarques/path/to/stat_data.txt
Edit the scheme to run from the directory containing the file. If you click on "Edit Scheme" and then select the Run section. The Options tab has a check box to "Use custom working directory". Check this and enter the directory containing your text file.

Running a terminal command from a C program in OS X

I'm trying to use plotutils to generate a plot from binary data. First, I wrote a C program to export some sample binary data. Then, when I execute the following command in terminal, the plot gets generated as expected.
graph -T png -I d <'/Users/username/Documents/Restofpath/PlotutilsDataGen/testData'> '/Users/username/Documents/Restofpath/PlotutilsDataGen/testPlot.png'
But I want to combine this command with the C code that generates the binary data file so that once the code is executed, the plot is automatically exported. I tried two approaches: (i) using popen() which I suspect I'm doing incorrectly, and (ii) using system() which I thought should work, but doesn't. My entire code is as follows (I've listed both approaches together in the code by I naturally tried them individually):
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int numSamples = 1024;
double outputVec[2*numSamples];
char outputPath[200] = "/Users/username/Documents/Restofpath/PlotutilsDataGen/testData";
char plotcommand[400] = "graph -T png -I d <'/Users/username/Documents/Restofpath/PlotutilsDataGen/testData'> '/Users/username/Documents/Restofpath/PlotutilsDataGen/testPlot.png'";
FILE *fp, *p;
// Compute sample functions to export
for(int ii = 0; ii < (2*numSamples); ii = ii + 2)
{
outputVec[ii] = (double)ii/2;
outputVec[ii+1] = (double)(ii*2);
}
// Export as binary data file for plotutils to use for plotting
fp = fopen(outputPath, "wb");
fwrite(outputVec, sizeof(double), 2*numSamples, fp);
fclose(fp);
// Option 1
p = popen(plotcommand, "w");
pclose(p);
// Option 2
system(plotcommand);
return 0;
}
Any ideas as to what I'm doing wrong or how I might get this to work? Thanks.

Incorrect graph generated by graphviz library

I am currently struggling with GraphViz.
Here is my code :
GVC_t* gvc = gvContext();
FILE* f = fopen("out.dot", "r");
Agraph_t* G = agread (f);
fclose(f);
gvLayout (gvc, G, "dot");
gvRenderFilename (gvc, G, "svg", "mygraph.svg");
gvFreeLayout(gvc, G);
agclose (G);
gvFreeContext(gvc);
However, the output given by this code and the output given by the call to dot -Tsvg out.dot > output.svg are completely different :
The command line call to dot produces a good-looking graph
This code produces a graph where all nodes are at the same place, making it unreadable.
Strangely, when I change the algorithm in gvLayout (gvc, G, "dot"); from dot to neato or other layout algorithms, it works well (except for twopi), but the dot layout engine is the only one that produces acceptable results for my graphs.
Does anybody know what is wrong with my code?

Obtaining List of all Xorg Displays

I would like to know how I can obtain a list of all Xorg displays on my system, along with a list of screens associated with each display. I spent some time looking through the Xlib documentation, but was not able to find a function that does what I want. Please assume that I have no other dependencies other than a POSIX-complaint OS and X (e.g., no GTK). If what I ask is not possible assuming these minimal dependencies, then a solution using other libraries is fine.
Thank you very much for your help!
The only way I know of to get a list of displays is to check the /tmp/.X11-unix directory.
Once you do that, you can use Xlib to query each display for more information.
Per example:
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <X11/Xlib.h>
int main(void) {
DIR* d = opendir("/tmp/.X11-unix");
if (d != NULL) {
struct dirent *dr;
while ((dr = readdir(d)) != NULL) {
if (dr->d_name[0] != 'X')
continue;
char display_name[64] = ":";
strcat(display_name, dr->d_name + 1);
Display *disp = XOpenDisplay(display_name);
if (disp != NULL) {
int count = XScreenCount(disp);
printf("Display %s has %d screens\n",
display_name, count);
int i;
for (i=0; i<count; i++)
printf(" %d: %dx%d\n",
i, XDisplayWidth(disp, i), XDisplayHeight(disp, i));
XCloseDisplay(disp);
}
}
closedir(d);
}
return 0;
}
Running the above gives me this output with my current displays/screens:
Display :0 has 1 screens
0: 3046x1050
Display :1 has 2 screens
0: 1366x768
1: 1680x1050
Never found a better way of listing X displays other than that. I'd very much like to know if any better alternative exists.
Like netcoder wrote, the problem has two distinct parts:
Connection to the X server
The process establishes a connection to an X server using XOpenDisplay(). The connection is torn down using XCloseDisplay(). netcoders code in this thread is a good example of how to do it correctly.
As netcoder mentioned, the problem is that there is no reliable way find out which X servers a process can connect to. His code checks the typical location where the X sockets are, /tmp/.X11-unix/. That approach does not work at all if the user is remotely connected, for example via SSH (with X forwarding enabled). In that case there is really only the DISPLAY environment variable (and perhaps some trickery wrt. ~/.Xauthority files).
Unfortunately, I do not know of any better method either. I personally prefer to use a per-user configuration file -- say ~/.application/displays --, where the user can list the server names the application should try to connect in the same format as the DISPLAY environment variable, in addition to the default one. It is not automatic (netcoder's code is), but this approach suits me better.
Finding out about the screens provided by an X server
XScreenCount() will return the number of screens provided by the X server the process is currently connected to. If you only need the screen dimensions, follow netcoders example. For more detailed information, use XScreenOfDisplay(Display,index) to obtain the Screen pointers; 0 <= index < XScreenCount(Display).
In C code, the macros ScreenCount() and ScreenOfDisplay() are usually a bit more efficient than the actual function calls.

Resources