0

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

;

Pavel K
  • 13
  • 4

1 Answers1

0

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.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • Hey, I work on Linux machine, that's true, but I would like not to use system specific calls if possible. I am new to this gnuplot-iostream and faced such problem which I can solve by writing two separate programs, but first I would like to figure out maybe there is a way to solve it within the one code. – Pavel K Nov 27 '16 at 16:10
  • But your question does not show enough code and is still unclear. I believe you are misunderstanding something essential. Perhaps the issues are not where you believe they are. – Basile Starynkevitch Nov 27 '16 at 16:15
  • By using Qt I will need to write a fitting function by myself. In my work I need to use the gnuplot in order to get the fitting parameters and use them later on within the C++ code and the gnuplot as well. So, it is not a good alternative for me – Pavel K Nov 27 '16 at 16:18
  • I will add more code right now in the main question – Pavel K Nov 27 '16 at 16:19
  • But then it looks like you need some event loop, and some protocol from gnuplot to your application. My feeling is that you need to have some event loop and understand multiplexing syscalls à la `poll`. Or you have an [XY problem](http://xyproblem.info) – Basile Starynkevitch Nov 27 '16 at 16:19
  • I have a file with data, I fit that data with gnuplot, I read the fit.log file to get the final fit parameters and proceed with them within C++ code. The problem is that C++ code right now executes BEFORE the gnuplot is called even if it states in the code before. I don't know to loop it properly, I've tried already – Pavel K Nov 27 '16 at 16:32
  • You really need to learn more about Linux programming. And we cannot explain that in an answer. I have given useful references. – Basile Starynkevitch Nov 27 '16 at 16:35
  • Why did you accept my answer (what was right in it)? I just made a set of guesses about your code, that you did not describe enough. – Basile Starynkevitch Nov 27 '16 at 16:37
  • I have checked the `std::endl` statement and now it works properly... I am curious why in this case an examples of gnuplot-iostream are not showing such things (or they are not needed for the simple programs?) Ah, Exaple 2 shows it... gosh.. – Pavel K Nov 27 '16 at 16:38
  • Because buffering is not specific to *gnuplot-iostream*. They don't need to document that. But you need to read a lot more about Linux programming. – Basile Starynkevitch Nov 27 '16 at 16:40
  • Yes, I will, thank you for your help – Pavel K Nov 27 '16 at 16:41
  • That is the sad fact about programming. Even if you are doing it only for e.g. a PhD in physics, you need to learn a lot more about programming. See http://norvig.com/21-days.html – Basile Starynkevitch Nov 27 '16 at 16:42
  • In fact I am doing it for my PhD, I will follow you advice, thank you – Pavel K Nov 27 '16 at 16:46