Newer
Older
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
//**************************************************************************//
//* FRIDA: fast reliable interactive data analysis *//
//* dualplot.cpp: different mechanisms for screen and paper output *//
//* (C) Joachim Wuttke 1990-, v2(C++) 2001- *//
//* http://frida.sourceforge.net *//
//**************************************************************************//
#include <stdlib.h>
#include <iostream>
#include <math.h>
#include "mystd.h"
#include "range.h"
#include "grid.h"
#include "plotaux.h"
#include "coord.h"
#include "readln.h"
#include "asi.h"
#include "dualplot.h"
// local set-up:
#define GNUP // Gnuplot
// #define PLUT // GNU plotutils (too low level; buffering problem)
// #define PLPL // PlPlot (only Tek works, in X11 clipping problem)
#define WUPS // my own postscript driver
// local implementation:
#ifdef GNUP
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#endif
#ifdef PLUT
#include <plotter.h>
#endif
#ifdef PLPL
#include <plplot/plConfig.h>
#include <plplot/plplotP.h>
#endif
#ifdef WUPS
#define WUPS_GBUF "/tmp/rda.ps"
#endif
#define PLOTDTYP double
#define PSMAX 10
namespace NPlot {
#endif
#ifdef GNUP
int gp_fifo;
void gp_write(string);
int gp_fno;
string gp_fnames;
#endif
#ifdef WUPS
uint ps_fnum; // file
uint ps_snum; // scan
uint ps_pnum; // scan with pstyle
uint ps_cnum; // scan with cstyle
void ps_ticktack(uint ntack, double *tack, int ntpt, double *ticklim,
CAxis *A);
vector<string> ps_Doc;
vector<string> ps_accu; // future output is accumulated here
char outlin[ LINSIZ ];
#endif
};
void CAxis::Ask(const string& quest)
{
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
string def, in, in1, in2;
CRange newR;
while(1) {
def = (log ? "log " : "") + R.str();
// out = quest + " [" + def + "] ?"; so gehts leider(?) nicht
in = sask(quest.c_str(), def);
if (in==def)
return;
mystd::string_extract_word(in, &in1, &in2);
if (in1=="l") {
SetLog(!log);
in = in2;
} else if (in1=="i") {
SetLog(0);
in = in2;
} else if (in1=="g") {
SetLog(1);
in = in2;
}
if (in!="") {
newR = CRange(in);
if (!newR.valid)
continue;
if (log && newR.inf<=0) {
printf("! log scale requires range above 0\n");
continue;
}
R = newR;
return;
}
}
}
void CAxis::SetLog(const uint val)
{
if (log!=val) {
log = val;
CRange RX = AlternateR;
AlternateR = R;
R = RX;
}
}
#ifdef WUPS
double CAxis::pc(double v) // value -> plot-coordinate
{
}
#endif
void NPlot::Open(void)
{
#ifdef GNUP
// Start gnuplot. Use input redirection so that gnuplot receives
// commands from a gp_fifo which is created here.
string fn_fifo = string("/tmp/gnuplot-") + getenv( "LOGNAME" );
system( ("rm -f "+fn_fifo).c_str() );
if (mkfifo( fn_fifo.c_str(), 0666 )) {
printf("SEVERE SYSTEM ERROR cannot make fifo %s"
" - will not be able to print\n", fn_fifo.c_str() );
return;
}
system( ("gnuplot -noraise < " + fn_fifo + " &").c_str() );
// we use open instead of fopen or ofstream,
// because we need non-blocking mode.
if (!(gp_fifo = open(fn_fifo.c_str(), O_WRONLY))) {
printf("SEVERE SYSTEM ERROR cannot open gp_fifo"
" - will not be able to print\n");
return;
}
fcntl(gp_fifo,F_SETFL,O_NONBLOCK);
// gp_write(string("plot 1 2 3")); // test
gp_write(string("set terminal x11"));
#endif
#ifdef PLUT
// die folgenden Initialisierungen scheinen keinen Effekt zu haben:
Plotter::parampl("VANISH_ON_DELETE", (void*)"no");
Plotter::parampl("DISPLAY", (void*)":0.0");
Plotter::parampl("USE_DOUBLE_BUFFERING", (void*)"no");
plut = new XPlotter(cin, cout, cerr);
if (plut->openpl() < 0) {
printf("SEVERE SYSTEM ERROR "
"cannot open plotutils::Plotter::plut"
" - will not be able to print\n");
return;
}
plut->fspace(-.08, -.08, 1.04, 1.04);
#endif
#ifdef PLPL
// plsdev("xterm");
// plsdev("tk");
plscol0(0,255,255,255);
plscol0(1,0,0,0);
plSetOpt("np", ""); // no pause between plots
// plSetOpt("geometry", "600x400+340+5");
// plSetOpt("debug", "");
cout << "DEBUG P1\n";
plinit();
cout << "DEBUG P2\n";
// plfont(2);
// pltext(); // back to Tektronix text window
cout << "DEBUG P3\n";
#endif
#ifdef WUPS
#endif
}
void NPlot::Close(void)
{
#ifdef PLPL
cout << "DEBUG PEND\n";
plend();
#endif
}
void NPlot::Clear(void)
{
// cout << "DEBUG dp Clear beg\n";
gp_fno = 0;
gp_fnames = string("");
#endif
#ifdef PLUT
#endif
#ifdef PLPL
// new pl window:
// plgra(); // go to Tektronix graph window
pladv(0);
plvpor(0.15, 0.85, 0.1, 0.9);
#endif
#ifdef WUPS
// new wups file:
string cmd;
ps_accu.clear();
ps_accu.push_back( "\n%% output created by frida2\n");
ps_snum = 0;
ps_pnum = 0;
ps_cnum = 0;
ps_Doc.clear();
#endif
}
void NPlot::Multiask(void)
{
maxpoints = iask("Max # points in plot", maxpoints);
X.force = bask("Force x points into frame", X.force);
Y.force = bask("Force y points into frame", Y.force);
}
void NPlot::Box()
{
#ifdef GNUP
if (X.log) whichlog += "x";
if (Y.log) whichlog += "y";
#endif
#ifdef PLUT
plut->flinewidth(0.001);
plut->pencolorname("black");
plut->fbox(0., 0., 1., 1.);
plut->fbox(0., 0., 1., 1.);
plut->flushpl();
#endif
#ifdef PLPL
plwind(X.R.inf, X.R.sup, Y.R.inf, Y.R.sup);
plcol0(1);
plbox("bcnst", 0.0, 0, "bcnstv", 0.0, 0);
// plbox("bcfghlnst", 0.0, 0, "bcghnstv", 0.0, 0);
plcol0(1);
// plmtex("b", 3.2, 0.5, 0.5, "Frequency");
// plmtex("t", 2.0, 0.5, 0.5, "Single Pole Low-Pass Filter");
plcol0(2);
// plmtex("l", 5.0, 0.5, 0.5, "Amplitude (dB)");
*/
#endif
#ifdef WUPS
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
// wups:
snprintf(outlin, LINSIZ, "\n%d %f %f xSetCoord\n",
X.log, X.R.inf, X.R.sup);
ps_accu.push_back( outlin );
snprintf(outlin, LINSIZ, "%d %f %f ySetCoord\n",
Y.log, Y.R.inf, Y.R.sup);
ps_accu.push_back( outlin );
snprintf(outlin, LINSIZ, "%% %d %f %f %d zSetCoord\n\n", 0, 0., 0., 0);
ps_accu.push_back( outlin );
int ntack, ntpt;
double *tack, ticklim[2];
ps_accu.push_back( "\n/xPlotFrame {" );
if(plotaux::calc_ticks(X.log, X.R.inf, X.R.sup,
&ntack, &tack, &ntpt, ticklim)) {
printf("PROGRAM ERROR/ Ticks\n");
return;
}
ps_ticktack(ntack, tack, ntpt, ticklim, &X);
free(tack);
snprintf(outlin, LINSIZ, " {(%s)}\n", X.C.ps_str().c_str());
ps_accu.push_back( outlin );
ps_accu.push_back( " 0 10 0 0 0 90 "
"OneAxx Axx Tic xTacL xNumL %% low x axis\n" );
ps_accu.push_back( " 0 10 0 10 0 270 "
"OneAxx Axx Tic xTacH %% top x axis\n" );
ps_accu.push_back( " xCL\n" );
ps_accu.push_back( "} def\n" );
ps_accu.push_back( "\n/yPlotFrame {" );
if(plotaux::calc_ticks(Y.log, Y.R.inf, Y.R.sup,
&ntack, &tack, &ntpt, ticklim)) {
printf("PROGRAM ERROR/ Ticks\n");
return;
}
ps_ticktack(ntack, tack, ntpt, ticklim, &Y);
free(tack);
snprintf(outlin, LINSIZ, " {(%s)}\n", Y.C.ps_str().c_str());
ps_accu.push_back( outlin );
ps_accu.push_back( " 0 10 0 0 90 0 "
"OneAxx Axx Tic yTacL yNumL %% left y axis\n" );
ps_accu.push_back( " 0 10 10 0 90 180 "
"OneAxx Axx Tic yTacH % yNumH %% right yaxis\n" );
ps_accu.push_back( " yCL\n" );
ps_accu.push_back( "} def\n" );
ps_accu.push_back( "\n%% modeDD\nplotbefore\n" );
#endif
}
void NPlot::Line(const int lstyle,
const CGrid x, const vector<double> y,
const vector<double>* z,
const string xco, const string yco)
{
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
PLOTDTYP *xp, *yp;
uint np=0, nxl=0, nxh=0, nyl=0, nyh=0;
uint n=x.size();
if (n!=y.size()) {
printf("PROG ERR NPLot::Line x.size<>y.size\n");
return;
}
xp = (PLOTDTYP *) malloc(sizeof(PLOTDTYP)*n);
yp = (PLOTDTYP *) malloc(sizeof(PLOTDTYP)*n);
for (uint i=0; i<n; i++) {
if(!X.force && !X.R.contained(x[i])) {
if (x[i]<=X.R.inf) nxl++;
if (x[i]>=X.R.sup) nxh++;
continue;
}
if(!Y.force && !Y.R.contained(y[i])) {
if (y[i]<=Y.R.inf) nyl++;
if (y[i]>=Y.R.sup) nyh++;
continue;
}
if(np==maxpoints && np<n) {
Tekx();
printf("reached maxpoints at %g\n", x[i]);
}
xp[np] = x[i];
yp[np] = y[i];
np++;
if(np>maxpoints) i += maxpoints;
}
if (np==0) {
Tekx();
printf("no points in data range:\n"
"of %d points are\n %d left and %d right of the x range,"
"\n %d below and %d above of the y range\n",
n, nxl, nxh, nyl, nyh);
return;
}
// save to file:
char gp_fnam[40];
sprintf( gp_fnam, "/tmp/%s-%03d.gnu", getenv("LOGNAME"), gp_fno++);
if (gp_fnames!="") gp_fnames += ", ";
gp_fnames += string("\"") + gp_fnam + "\"" +
// string(" title \"") + xco + string (" -> ")
// + yco + string ("\"");
" notitle";
if (lstyle<0)
gp_fnames += " with lines";
FILE *gp_fd;
if (!(gp_fd = fopen(gp_fnam, "w"))) {
printf( "cannot save gnuplot data to %s", gp_fnam );
return;
}
for (uint i=0; i<np; i++)
fprintf(gp_fd, "%20.12g %20.12g\n", xp[i], yp[i]);
fclose(gp_fd);
// plot command:
char aux[80];
sprintf(aux, "[%20.12g:%20.12g] [%20.12g:%20.12g] ",
X.R.inf, X.R.sup, Y.R.inf, Y.R.sup);
gp_write(string("plot ") + aux + gp_fnames);
#endif
#ifdef PLUT
#endif
#ifdef PLPL
plcol0(9);
plpoin(np, xp, yp, 1);
#endif
#ifdef WUPS
snprintf( outlin, LINSIZ, "\n%3u [", ++ps_snum);
ps_accu.push_back( outlin );
for (uint i=0; i<z->size(); i++){
snprintf( outlin, LINSIZ, " %12g", (*z)[i]);
ps_accu.push_back( outlin );
}
snprintf( outlin, LINSIZ, " ] zValues\n");
ps_accu.push_back( outlin );
if (lstyle>=0)
snprintf( outlin, LINSIZ, "%2d pstyle", ++ps_pnum);
else
snprintf( outlin, LINSIZ, "%2d cstyle", 1);
ps_accu.push_back( outlin );
snprintf( outlin, LINSIZ, " %% (%s -> %s)\n", xco.c_str(), yco.c_str());
ps_accu.push_back( outlin );
for (uint i=0; i<np; i++) {
snprintf( outlin, LINSIZ,
"%7.3f%7.3f%7.3f t%c %% %14.7g wx %14.7g wy\n",
X.pc(xp[i]), Y.pc(yp[i]), 0.0,
i==0 ? 'i' : i==np-1 ? 'f' : ' ',
xp[i], yp[i]);
ps_accu.push_back( outlin );
}
}
void NPlot::Doc (vector<string> lDoc)
{
#ifdef WUPS
for (uint i=0; i<lDoc.size(); i++)
ps_Doc.push_back(lDoc[i]);
void NPlot::Save( bool full_outfile )
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
string ps_outdir, ps_head, ps_dict;
// read configuration parameters:
if ( NRead::wofmac("\\psdir", &ps_outdir) ) {
printf("! please define \\psdir\n");
return;
}
if ( NRead::wofmac("\\pshead", &ps_head) ) {
printf("! please define \\pshead\n");
return;
}
if ( full_outfile && NRead::wofmac("\\psdict", &ps_dict)) {
printf("! please define \\psdict\n");
return;
}
// construct output file name:
FILE *pssav;
char outf[20];
string flong, cmd;
while(1) {
if (ps_fnum>=999) {
printf ("graph file number overflow\n");
return;
}
sprintf(outf, "%sl%d.%s", ps_outdir.c_str(), ++ps_fnum,
full_outfile ? "ps" : "psa" );
if (!(pssav = mystd::glob_fopen(outf, "", "", "r")))
break; // legal exit
fclose(pssav);
}
printf("save plot in %s\n", outf);
// copy headers to output file:
cmd = string("cat ") + ( full_outfile ? ps_dict : "" ) + " " +
ps_head + " > " + outf + "\n";
if (system(cmd.c_str())) {
printf ("cannot copy to %s\n", outf);
return;
}
// a redundant check of existence of the outfile:
if (!(pssav = mystd::glob_fopen(outf, "", "", "r", &flong))) {
printf("have not created file %s\n", outf);
return;
}
fclose(pssav);
// append specific output to output file:
if (!(pssav = fopen(flong.c_str(), "a+"))) {
printf ("cannot write (append) to file %s\n", flong.c_str());
return;
}
for( uint i=0; i<ps_accu.size(); ++i ){
fprintf( pssav, ps_accu[i].c_str() );
}
// additional output (do not append this to ps_accu to allow
// further incrementation of ps_accu):
fprintf(pssav, "\nblack 0 -4 13 newlist\n");
for (uint i=0; i<ps_Doc.size(); i++)
fprintf(pssav, "{(%s)} infline\n", ps_Doc[i].c_str());
fprintf(pssav,
"\n{(%s)} /filename exch def 10 -2.8 18 showfilename\n\n"
"EndFrame\n", outf);
// output completed:
fclose(pssav);
cout << "graphic save desactivated\n";
#endif
#ifdef PLPL
// plend(); // TEST
#endif
}
void NPlot::Tekx(void)
{
#ifdef PLPL
// pltext(); // back to Tektronix text window
#endif
}
void NPlot::Dialog(void)
{
#ifdef GNUP
string cmd;
cout << "entering mygnuplot - to leave, type q\n";
while(1) {
cmd = sask("mygnuplot> ");
if (cmd.substr(0,1)=="q") return;
gp_write(cmd);
}
cout << "Graphic dialog is implemented only for Gnuplot\n";
#endif
}
#ifdef GNUP
void NPlot::gp_write(string in)
{
// cout << "DEBUG gp_write " << in << "\n";
string out = in + "\n";
write(gp_fifo, out.c_str(), out.size());
}
#endif
#ifdef WUPS
void NPlot::ps_ticktack(uint ntack, double *tack, int ntpt, double *ticklim,
CAxis *A)
{
uint i;
ps_accu.push_back( "[\n" );
if (A->log && ( tack[0]<1e-3 || tack[ntack-1]>1e3 )) {
for (i=0; i<ntack; i++) {
snprintf( outlin, LINSIZ, " %9.6f {(10)(%d)sp()} %%{(%g)}\n",
A->pc(tack[i]), mystd::nint(log10(tack[i])),
(float) tack[i]);
ps_accu.push_back( outlin );
}
} else {
for (i=0; i<ntack; i++) {
snprintf( outlin, LINSIZ, " %9.6f {(%g)}\n",
A->pc(tack[i]), (float) tack[i]);
ps_accu.push_back( outlin );
}
}
ps_accu.push_back( " ] SetTacVec\n" );
snprintf( outlin, LINSIZ, " %g %g %d %d SetTicVec%s\n",
A->pc(ticklim[0]), A->pc(ticklim[1]), ntack+2, ntpt,
(A->log? "Log" : "Lin"));
ps_accu.push_back( outlin );