Pavel K Pavel K - 9 days ago 7
C++ Question

How to continue to execute the C++ code after gnuplot was called?

I am using gcc as a compiler and gnuplot-iostream.h as a stream to combine C++ code and the gnuplot features.

What I am doing:

I try to make a fit of the data via gnuplot and extract the final fit parameters from the generated fit.log file for further processing.

What's the problem:

When executing the code like this

std::cout << "Starting to fit" << std::endl;
if (bStartFit == true)
{
// gp << doing stuf here;
std::cout << "Test end" << std::endl;
}
std::cout << "Fit is done" << std::endl;


the output will be:

Starting to fit
Fit is done
Test end
//gnuplot stuff


My question is: how to force the code execute gnuplot stuff exactly when needed, and after proceed with the C++ code. For example:


  • write intro message;

  • plot the sin(x) function (as fast example);

  • wait until the gnuplot is closed;

  • write exiting message or do what ever AFTER the gnuplot is done.



thank you,
P

EDIT:

std::string filename = "fit.log";
if (bStartFit == true)
{
// Using Gnuplot for the data fit (command are parsed as the strings):
// 1. define the fit function.
gp << "f(x) = imfpZP * x**(-b) + c * x**(d) + g * x**(h) \n";
// 2. fit parameters first assumption.
gp << "b = 1.1; c = 0.5; d = 1.0; g = 2.0; h = 0.1 \n";
// 3. fit range.
gp << "fit [50:10000] f(x) 'agn.iimfp' via b,c,d,g,h \n";
// 4. set the logarithmic scale.
gp << "set logscale \n";
// 5. plot the fitted data.
gp << "plot 'agn.iimfp' w l lw 2 tit 'orig', f(x) w l lw 2 tit 'fit' \n";

std::cout << "Fit was successful" << std::endl;
}

// Opening the generated fit.log file to store the fit parameters:
std::ifstream inFIT(filename.c_str());
if (inFIT.is_open())
{
std::cout << "FIT log is opened" << std::endl;

std::string line;
int lineCounter = 0;
while (std::getline(inFIT, line))
{
lineCounter++;
}
std::cout << "Total lines: " << lineCounter << std::endl;

// Getting the five lines with fit parameters from the fit.log:
std::fstream& GoToLine(std::fstream& file, unsigned int lineNumber);
std::fstream file(filename.c_str());


GoToLine(file, lineCounter - 15);
std::string b_Line;
std::getline(file, b_Line);
std::cout << b_Line << std::endl;
std::istringstream sb(b_Line);
std::string tempStr;
char tempChar;
sb >> tempStr >> tempChar >> b
// similar code to get another 4 lines


;

Answer

It is operating system specific. I am guessing you are on Linux (or at least on some POSIX OS). Then you really should read Advanced Linux Programming. And using strace(1) could be helpful to understand what is happening.

You could use popen(3), but you probably should explicitly use system calls (they are listed in syscalls(2)) like pipe(2), fork(2), dup2(2), execve(2), waitpid(2), etc. And very probably have some event loop (e.g. around poll(2)).

BTW, you should be aware that input output is buffered, and you probably want to be sure that your gnuplot stream is regularly flushed (so use std::endl or std::flush appropriately on it). Writing a \n is not enough! You probably should code at least

gp << "plot 'agn.iimfp' w l lw 2 tit 'orig', f(x) w l lw 2 tit 'fit' " 
   << std::endl;

(I have replaced some \n inside a string with an explicit use of std::endl)

I don't know much about gnuplot stream (I'm guessing it is a bit like some specialized popen but using C++ streams), but I guess that you should the gnuplot print or printerr command to communicate to your calling program the fact that a given curve has been plotted. (But then you need a genuine event loop, and you are defining a bidirectional protocol between gnuplot and your program.).

Perhaps Qt or POCO might be relevant, because they provide some notion of event loop and processes. Perhaps you might have several threads (one managing gnuplot and the other for the rest), but then you have synchronization issues.

(I don't understand enough what your program is supposed to do, and how you have coded it, so it is a blind guess; I feel your question is very unclear)

Read more about Inter-Process Communications.