File: apop_plot_query.c

package info (click to toggle)
apophenia 1.0%2Bds-7
  • links: PTS, VCS
  • area: main
  • in suites: buster, stretch
  • size: 2,904 kB
  • sloc: ansic: 19,479; makefile: 374; awk: 124; sh: 105; sed: 32
file content (144 lines) | stat: -rw-r--r-- 4,930 bytes parent folder | download | duplicates (3)
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
/** \file 
 Command line utility to take in a query and produce a plot of its output via Gnuplot.

Copyright (c) 2006--2007 by Ben Klemens.  Licensed under the GPLv2; see COPYING.  */

#include "apop_internal.h"
#include <unistd.h>


/** This convenience function will take in a \c gsl_vector of data and put out a histogram, ready to pipe to Gnuplot.

\param data A \c gsl_vector holding the data. Do not pre-sort or bin; this function does that for you via apop_data_to_bins.
\param bin_count   The number of bins in the output histogram (if you send zero, I set this to \f$\sqrt(N)\f$, where \f$N\f$ is the length of the vector.)
\param with The method for Gnuplot's plotting routine. Default is \c "boxes", so the gnuplot call will read <tt>plot '-' with boxes</tt>. The \c "lines" option is also popular, and you can add extra terms if desired, like <tt> "boxes linetype 3"</tt>.
*/
void plot_histogram(gsl_vector *data, FILE *f, size_t bin_count, char *with){
    Apop_stopif(!data, return, 0, "Input vector is NULL.");
    if (!with) with="impulses";
    apop_data vector_as_data = (apop_data){.vector=data};
    apop_data *histodata = apop_data_to_bins(&vector_as_data, .bin_count=bin_count, .close_top_bin='y');
    apop_data_sort(histodata);
    apop_data_free(histodata->more); //the binspec.

    fprintf(f, "set key off	;\n"
               "plot '-' with %s\n", with);
    apop_data_print(histodata, .output_pipe=f);
    fprintf(f, "e\n");

    fflush(f);
    apop_data_free(histodata);
}


char *plot_type = NULL;
int histobins = 0;
int histoplotting = 0;

FILE *open_output(char *outfile, int sf){
    FILE  *f;
    if (sf && !strcmp (outfile, "-"))
        return stdout;
    if (sf && outfile){
        f = fopen(outfile, "w");
        Apop_stopif(!f, exit(0), 0, "Trouble opening %s.", outfile);
        return f;
    }
    f = popen("`which gnuplot` -persist", "w");
    Apop_stopif(!f, exit(0), 0, "Trouble opening %s.", "gnuplot");
    return f;
}

char *read_query(char *infile){
    char in[1000];
    char *q = malloc(10);
    q[0] = '\0';
    FILE *inf = fopen(infile, "r");
    Apop_stopif(!inf, exit(0), 0, "Trouble opening %s. Look into that.\n", infile);
    while(fgets(in, 1000, inf)){
        q = realloc(q, strlen(q) + strlen(in) + 4);
        sprintf(q, "%s%s", q, in);
    }
    sprintf(q, "%s;\n", q);
    fclose(inf);
    return q;
}

gsl_matrix *query(char *d, char *q, int no_plot){
	apop_db_open(d);
    apop_data *result = apop_query_to_data("%s", q);
	apop_db_close(0);
    Apop_stopif(!result && !no_plot, exit(2), 0, "Your query returned a blank table. Quitting.");
    Apop_stopif(result->error, exit(2), 0, "Error running your query. Quitting.");
    if (no_plot){
        apop_data_show(result);
        exit(0);
    }
    return result->matrix;
}

void print_out(FILE *f, char *outfile, gsl_matrix *m){
    if (!histoplotting){
        fprintf(f,"plot '-' with %s\n", plot_type);
	    apop_matrix_print(m, NULL, .output_type='p', .output_pipe=f);
    } else {
        Apop_col_v(&(apop_data){.matrix=m}, 0, v);
        plot_histogram(v, f, histobins, NULL);
    }
    if (outfile) fclose(f);
}

int main(int argc, char **argv){
    int c;
    char *q = NULL,
         *d = NULL,
         *outfile = NULL;
    int sf = 0,
        no_plot = 0;

    const char* msg= "Usage: %s [opts] dbname query\n"
"\n"
"Runs a query, and pipes the output directly to gnuplot. Use -f to dump to stdout or a file.\n"
" -d\tdatabase to use (mandatory)\n"
" -q\tquery to run (mandatory or use -Q)\n"
" -Q\tfile from which to read the query\t\t\n"
" -n\tno plot: just run the query and display results to stdout\t\t\n"
" -t\tplot type (points, bars, ...) (default: \"lines\")\n"
" -H\tplot histogram with this many bins (e.g., -H100) (to let the system auto-select bin sizes, use -H0)\n"
" -f\tfile to dump to. If -f- then use stdout (default: pipe to Gnuplot)\n"
" -h\tdisplay this help and exit\n"
"\n";

	Apop_stopif(argc<2, return 1, 0, msg, argv[0]);
	while ((c = getopt (argc, argv, "ad:f:hH:nQ:q:st:-")) != -1)
	    if (c=='f'){
              outfile = strdup(optarg);
              sf++;
        } else if (c=='H'){
              histoplotting = 1;
              histobins = atoi(optarg);
        }
        else if (c=='h'||c=='-') {
            printf(msg, argv[0]);
			return 0;
		}
        else if (c=='d') d = strdup(optarg);
        else if (c=='n') no_plot ++;
        else if (c=='Q') q = read_query(optarg);
        else if (c=='q') q = strdup(optarg);
        else if (c=='t') plot_type = strdup(optarg);

    if (optind == argc -2){
        d = argv[optind];
        q = argv[optind+1];
    } else if (optind == argc-1)
        q = argv[optind];

    Apop_stopif(!q, return 1, 0, "I need a query specified with -q.\n");

    if (!plot_type) plot_type = strdup("lines");

    FILE *f = open_output(outfile, sf);
    gsl_matrix *m = query(d, q, no_plot);
    print_out(f, outfile, m);
}