File: u_gnuplot.cpp

package info (click to toggle)
fityk 0.4.4-1
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 2,472 kB
  • ctags: 2,617
  • sloc: cpp: 19,705; sh: 5,965; xml: 2,325; yacc: 356; makefile: 183; lex: 178
file content (150 lines) | stat: -rw-r--r-- 4,363 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// This file is part of fityk program. Copyright (C) Marcin Wojdyr

// CLI-only file

#include "common.h"
RCSID ("$Id: u_gnuplot.cpp,v 1.6 2004/06/17 19:01:12 wojdyr Exp $")

#include "u_gnuplot.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fstream>
#include <string>
#include <sys/types.h>
#include <signal.h>
#include <errno.h>
#include "data.h"
#include "sum.h"
#include "pcore.h"
#include "other.h"
#include "ui.h"

using namespace std;

char GnuPlot::path_to_gnuplot[]="gnuplot";

GnuPlot::GnuPlot ()
{
    fork_and_make_pipe ();
}

GnuPlot::~GnuPlot() 
{
    fclose(gnuplot_pipe);  //it closes gnuplot
}

void GnuPlot::fork_and_make_pipe ()
{
    int     fd[2];
    pid_t   childpid;
    pipe(fd);
    if ((childpid = fork()) == -1) {
        perror("fork");
        exit(1);
    }

    if (childpid == 0) {
        // Child process closes up output side of pipe 
        close (fd[1]);
        // and input side is stdin
        dup2 (fd[0], 0);
        if (fd[0] > 2)
            close (fd[0]);
        //putenv("PAGER="); //putenv() - POSIX, not ANSI
        execlp (path_to_gnuplot, path_to_gnuplot, /*"-",*/NULL);
        // if we are here, sth went wrong
        warn("Problem encountered when trying to run `" 
                + S(path_to_gnuplot) + "'.");
        exit(0);
    }
    else {
        // Parent process closes up input side of pipe 
        close (fd[0]);
        gnuplot_pipe  = fdopen (fd[1], "w"); //fdopen() - POSIX, not ANSI
    }
}

bool GnuPlot::gnuplot_pipe_ok()
{
    static bool give_up = false;
    if (give_up) 
        return false;
    //sighandler_t and sig_t are not portable
    typedef void (*my_sighandler_type) (int);
    my_sighandler_type shp = signal (SIGPIPE, SIG_IGN);
    errno = 0;
    fprintf (gnuplot_pipe, " "); //pipe test
    fflush(gnuplot_pipe);
    if (errno == EPIPE) {
        errno = 0;
        fork_and_make_pipe();
        signal (SIGPIPE, SIG_IGN);
        fprintf (gnuplot_pipe, " "); //test again
        fflush(gnuplot_pipe);
        if (errno == EPIPE) {
            give_up = true;
            signal (SIGPIPE, shp);
            return false;
        }
    }                    
    signal (SIGPIPE, shp);
    return true;
}

int GnuPlot::plot (const vector<fp>& workingA) 
{
    if (!gnuplot_pipe_ok())
        return -1;
    my_sum->use_param_a_for_value(workingA);
    bool plus_bg = my_core->plus_background;
    string yfun = my_sum->sum_full_formula (workingA);
    very_verbose("Plotting function: " + yfun); 
    // Send commands through the pipe to gnuplot
    int i_f = my_data->get_lower_bound_ac (my_core->view.left);
    int i_l = my_data->get_upper_bound_ac (my_core->view.right);
    if (i_l - i_f > 0) { //plot data & sum
        bool function_as_points = (i_l - i_f > smooth_limit);
        string plot_string = "plot "+ my_core->view.str() 
            + " \'-\' title \"data\", ";
        if (function_as_points) {
            plot_string += " '-' title \"sum\" with line\n ";
            fprintf (gnuplot_pipe, plot_string.c_str());
        }
        else {
            plot_string += yfun + " title \"sum\"\n ";
            fprintf (gnuplot_pipe, plot_string.c_str());
        }
        if (fflush (gnuplot_pipe) != 0)
            warn ("Flushing pipe program-to-gnuplot failed.");
        for (int i = i_f; i < i_l; i++)
            fprintf (gnuplot_pipe, "%f  %f\n", my_data->get_x(i), 
                    plus_bg ? my_data->get_original_y(i) : my_data->get_y(i));
        fprintf (gnuplot_pipe, "e\n");//gnuplot needs 'e' at the end of data
        if (function_as_points) {
            my_sum->use_param_a_for_value (workingA);
            for (int i = i_f; i < i_l; i++) {
                fp x = my_data->get_x(i);
                fprintf(gnuplot_pipe, "%f  %f\n", x, 
                       plus_bg ? my_sum->value(x) + my_data->get_background_y(i)
                               : my_sum->value (x));
            }
            fprintf(gnuplot_pipe, "e\n");
        }
    }
    else { // plot only sum
        string plot_string =  "plot " + my_core->view.str() + " " + yfun 
            + " title \"function\"\n";
        fprintf (gnuplot_pipe, plot_string.c_str());
    }
    fflush(gnuplot_pipe);
    return 0;
}

void GnuPlot::raw_command(char *command) 
{
    fprintf (gnuplot_pipe, "%s\n", command);
    fflush(gnuplot_pipe);
}