diff --git a/pub/src/dualplot.cpp b/pub/src/dualplot.cpp index b0cfcd994703d4706d5e83b5402e915ff896fabb..f4ddc52891b21d5c421576c1a5d26a667e2a9c84 100644 --- a/pub/src/dualplot.cpp +++ b/pub/src/dualplot.cpp @@ -25,12 +25,16 @@ //* CRange *// //**************************************************************************// +//! Initialize with infinite limits, to be automatically reset by 1st plot call. + CRange::CRange() { inf = -INFINITY; sup = +INFINITY; } - + +//! Initialize; check given limits. + CRange::CRange( double infin, double supin ) { if( infin > supin ) @@ -41,6 +45,8 @@ CRange::CRange( double infin, double supin ) sup = supin; } +//! Parse string to set bounds. + void CRange::set_from_string( const string& in ) { if ( in=="*" ) { @@ -69,6 +75,8 @@ void CRange::set_from_string( const string& in ) } } +//! Replace limits by rounded values. + void CRange::Round( int logflag, double relmargin, double digits ) { if( !finite() ) @@ -112,11 +120,15 @@ void CRange::Round( int logflag, double relmargin, double digits ) } } +//! Have finite limits been set ? + bool CRange::finite() const { return inf!=-INFINITY && sup!=+INFINITY; } +//! Is value val contained in this range? + bool CRange::contained(double val) const { return inf <= val && val <= sup; @@ -150,6 +162,8 @@ double CRange::plotcoord2value(int logflag, double c) const } } +//! String representation. + string CRange::str() const { string ret = ""; @@ -170,28 +184,18 @@ string CRange::str() const //* CAxis *// //**************************************************************************// +//! Query and check range. + void CAxis::Ask( const string& quest ) { string def, in, in1, in2; - def = (log ? "log " : "") + R.str(); + def = R.str(); in = sask( quest, 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!="") R.set_from_string( in ); @@ -208,16 +212,18 @@ void CAxis::Ask( const string& quest ) } } -void CAxis::SetLog( const bool _log ) +//! Set lin or log, reset ranges to auto. + +void CAxis::setLog( const bool _log ) { - if ( _log!=log ) { - log = _log; - CRange RX = AlternateR; - AlternateR = R; - R = RX; - } + log = _log; + //if( log && R.inf<0 ){ + R.inf = -INFINITY; + R.sup = +INFINITY; } +//! Describe range, for use in table of plot frames. + string CAxis::info() { string ret; @@ -227,7 +233,9 @@ string CAxis::info() return ret; } -double CAxis::pc(double v) const // value -> plot-coordinate +//! Convert value -> plot_coordinate. + +double CAxis::pc(double v) const { return CPLOT_PSMAX * R.value2plotcoord(log, v); } @@ -237,7 +245,10 @@ double CAxis::pc(double v) const // value -> plot-coordinate //* CPlot *// //**************************************************************************// -void CPlot::Open() +//! Constructor for plot window: setup for gnuplot and postscript. + +CPlot::CPlot( uint _iPlot, bool _logx, bool _logy ) : + iPlot( _iPlot ), maxpoints(12000), X( _logx ), Y( _logy ) { // Start gnuplot. Use input redirection so that gnuplot receives // commands from a gp_fifo which is created here. @@ -266,18 +277,16 @@ void CPlot::Open() ps_fnum=0; } - -void CPlot::Close() -{ -} -void CPlot::Clear() +//! Clear plot frame and buffer. + +void CPlot::clearFrame() { - // cout << "DEBUG dp Clear beg\n"; + // clear gnuplot tmp files gp_fno = 0; - gp_fnames = string(""); + gp_fnames = ""; - // new wups file: + // reset buffers for postscript output string cmd; ps_accu.clear(); ps_accu.push_back( "\n%% output created by frida2\n"); @@ -287,14 +296,42 @@ void CPlot::Clear() ps_Doc.clear(); } -void CPlot::Multiask() +//! Change one setup parameter per command. + +void CPlot::setAux( string cmd ) { - 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); + if ( cmd=="gnp" ) + maxpoints = iask("Max # points in plot", maxpoints); + else if ( cmd=="gxl" ) { + X.setLog( !X.log ); printf( "set x %s\n", X.log ? "log" : "lin" ); } + else if ( cmd=="gxl+" ) + X.setLog( true ); + else if ( cmd=="gxl+" ) + X.setLog( false ); + else if ( cmd=="gyl" ) { + Y.setLog( !Y.log ); printf( "set y %s\n", Y.log ? "log" : "lin" ); } + else if ( cmd=="gyl+" ) + Y.setLog( true ); + else if ( cmd=="gyl+" ) + Y.setLog( false ); + else if ( cmd=="gxf" ) { + X.force = !X.force; printf( "force x %s\n", X.force ? "on" : "off" ); } + else if ( cmd=="gxf+" ) + X.force = true; + else if ( cmd=="gxf+" ) + X.force = false; + else if ( cmd=="gyf" ) { + Y.force = !Y.force; + Y.force = !Y.force; printf( "force y %s\n", Y.force ? "on" : "off" ); } + else if ( cmd=="gyf+" ) + Y.force = true; + else if ( cmd=="gyf+" ) + Y.force = false; } -void CPlot::Box() +//! Plot coordinate frame (axes, ticks, labels). + +void CPlot::plotFrame() { gp_write( "set nologscale" ); string whichlog=""; @@ -310,7 +347,8 @@ void CPlot::Box() snprintf( outlin, CPLOT_LINSIZ, "%d %g %g ySetCoord\n", Y.log, Y.R.inf, Y.R.sup ); ps_accu.push_back( outlin ); - snprintf( outlin, CPLOT_LINSIZ, "%% %d %g %g %d zSetCoord\n\n", 0, 0., 0., 0 ); + snprintf( outlin, CPLOT_LINSIZ, "%% %d %g %g %d zSetCoord\n\n", + 0, 0., 0., 0 ); ps_accu.push_back( outlin ); int ntack, ntpt; @@ -352,11 +390,13 @@ void CPlot::Box() ps_accu.push_back( "\n%% modeDD\nplotbefore\n" ); } -void CPlot::Line( const bool as_line, const int style_no, - const vector<double> xp, const vector<double> yp, - const vector<double>* z, - const string xco, const string yco, - const string info ) +//! Plot one scan. + +void CPlot::plotScan( const bool as_line, const int style_no, + const vector<double> xp, const vector<double> yp, + const vector<double>* z, + const string xco, const string yco, + const string info ) { // Checks: uint np=xp.size(); @@ -423,13 +463,17 @@ void CPlot::Line( const bool as_line, const int style_no, } } -void CPlot::Doc (vector<string> lDoc) +//! Add documentation lines to postscript output. + +void CPlot::plotDoclines( vector<string> lDoc ) { for (uint i=0; i<lDoc.size(); i++) ps_Doc.push_back(lDoc[i]); } -void CPlot::Save( bool full_outfile ) +//! Write buffered plot to postscript file. + +void CPlot::writePostscript( bool full_outfile ) { string ps_outdir, ps_head, ps_dict; @@ -490,7 +534,9 @@ void CPlot::Save( bool full_outfile ) fclose(pssav); } -void CPlot::Dialog() +//! Endless loop: query for gnuplot commands. + +void CPlot::feedGnuplot() { string cmd; cout << "entering mygnuplot - to leave, type q\n"; @@ -501,6 +547,8 @@ void CPlot::Dialog() } } +//! Info line to characterize this plot window. + string CPlot::info() { string ret; @@ -509,6 +557,8 @@ string CPlot::info() return ret; } +//! Send one line to gnuplot fifo. + void CPlot::gp_write( string in ) { string out = in + "\n"; @@ -517,6 +567,8 @@ void CPlot::gp_write( string in ) throw string( "could not write to gp_fifo" ); } +//! Format ticks and tacks for postscript file. + void CPlot::ps_ticktack(uint ntack, double *tack, int ntpt, double *ticklim, CAxis *A) { @@ -524,7 +576,8 @@ void CPlot::ps_ticktack(uint ntack, double *tack, int ntpt, double *ticklim, ps_accu.push_back( "[\n" ); if (A->log && ( tack[0]<1e-3 || tack[ntack-1]>1e3 )) { for (i=0; i<ntack; i++) { - snprintf( outlin, CPLOT_LINSIZ, " %9.6f {(10)(%d)sp()} %%{(%g)}\n", + snprintf( outlin, CPLOT_LINSIZ, + " %9.6f {(10)(%d)sp()} %%{(%g)}\n", A->pc(tack[i]), (int)(log10(tack[i])), (float) tack[i]); ps_accu.push_back( outlin ); diff --git a/pub/src/dualplot.h b/pub/src/dualplot.h index 79058e317d8c056cfbcc77683d9934d136889b86..b5d26c133c68e9385c09422810cae37febcdd7ea 100644 --- a/pub/src/dualplot.h +++ b/pub/src/dualplot.h @@ -22,7 +22,6 @@ class CRange { class CAxis { public: CRange R; - CRange AlternateR; // obsoleted by multi-CPlot CCoord C; bool log; bool force; @@ -30,7 +29,7 @@ class CAxis { CAxis( bool _log ) : log(_log), force(false) {}; void Ask( const string& quest ); - void SetLog( const bool _log ); + void setLog( const bool _log ); string info(); double pc(double v) const; @@ -40,35 +39,30 @@ class CAxis { #define CPLOT_PSMAX 10 #define CPLOT_LINSIZ 80 -class CPlot { // additional declarations in dualplot.cpp +class CPlot { public: uint iPlot; CAxis X, Y; uint maxpoints; - CPlot( uint _iPlot, bool _logx, bool _logy ) : - iPlot( _iPlot ), maxpoints(12000), X( _logx ), Y( _logy ) - { Open(); }; - - void Multiask(); - - void Open(); - void Close(); - void Clear(); - void Box(); - void Line( const bool as_line, const int style_no, - const vector<double> x, const vector<double> y, - const vector<double>* z, - const string xco, const string yco, - const string info ); - void Doc (vector<string> lDoc); - void Save( bool full_outfile ); - void Dialog(); + CPlot( uint _iPlot, bool _logx, bool _logy ); + + void clearFrame(); + void plotFrame(); + void plotScan( const bool as_line, const int style_no, + const vector<double> x, const vector<double> y, + const vector<double>* z, + const string xco, const string yco, + const string info ); + void plotDoclines( vector<string> lDoc ); + void writePostscript( bool full_outfile ); + void setAux( string cmd ); + void feedGnuplot(); string info(); - private: +private: // can we move this to the .cpp file ? int gp_fifo; - void gp_write(string); + void gp_write( string ); int gp_fno; string gp_fnames; @@ -76,8 +70,8 @@ class CPlot { // additional declarations in dualplot.cpp 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); + 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[ CPLOT_LINSIZ ]; diff --git a/pub/src/edif.cpp b/pub/src/edif.cpp index 2945c7ceb80b4ab39b2d890dbd3c702354dcddf5..8dc7f6e4b92a748135e530343c6357893f93115b 100644 --- a/pub/src/edif.cpp +++ b/pub/src/edif.cpp @@ -1090,8 +1090,8 @@ void NEdif::Plot( CPlot *plot, bool add ) plot->Y.C = NOlm::MOM[*(NOlm::FSel.V.begin())].P()->yco; // draw new frame: - plot->Clear(); - plot->Box(); + plot->clearFrame(); + plot->plotFrame(); } // plot data: @@ -1162,10 +1162,10 @@ void NEdif::Plot( CPlot *plot, bool add ) if( nyh ) printf( " %zu points > ymax\n", nyh ); } else { - plot->Line( false, pstyle++, - xp, yp, e->Z(j), - e->P()->xco.str(), e->P()->yco.str(), - "data file "+strg(k)+" scan "+strg(j) ); + plot->plotScan( false, pstyle++, + xp, yp, e->Z(j), + e->P()->xco.str(), e->P()->yco.str(), + "data file "+strg(k)+" scan "+strg(j) ); } } else if ( fc && false ) { // keep old vectorial version; @@ -1176,9 +1176,9 @@ void NEdif::Plot( CPlot *plot, bool add ) xp[i] = plot->X.R.plotcoord2value( plot->X.log, i/(npts-1.0) ); fc->T->tree_curve_val_vec( &yp, xp, k, j ); - plot->Line( true, cstyle++, xp, yp, e->Z(j), - e->P()->xco.str(), e->P()->yco.str(), - "curve file "+strg(k)+" scan "+strg(j) ); + plot->plotScan( true, cstyle++, xp, yp, e->Z(j), + e->P()->xco.str(), e->P()->yco.str(), + "curve file "+strg(k)+" scan "+strg(j) ); } else if ( fc && fc->kconv!=-1 ) { // plot only at x points of convolutand uint kconv = fc->kconv; @@ -1193,9 +1193,9 @@ void NEdif::Plot( CPlot *plot, bool add ) xp.push_back( x ); } fc->T->tree_curve_val_vec( &yp, xp, k, j ); - plot->Line( true, cstyle++, xp, yp, e->Z(j), - e->P()->xco.str(), e->P()->yco.str(), - "curve file "+strg(k)+" scan "+strg(j) ); + plot->plotScan( true, cstyle++, xp, yp, e->Z(j), + e->P()->xco.str(), e->P()->yco.str(), + "curve file "+strg(k)+" scan "+strg(j) ); } else if ( fc ) { // improved line plotting: // - stop/start line when leaving/reentering the frame @@ -1235,17 +1235,17 @@ void NEdif::Plot( CPlot *plot, bool add ) pos = 1; } for( int iS=0; iS<SS.size(); ++iS ){ - plot->Line( true, cstyle, SS[iS].x, SS[iS].y, e->Z(j), - e->P()->xco.str(), e->P()->yco.str(), - "curve file "+strg(k)+" scan "+strg(j)+ - " segment "+strg(iS) ); + plot->plotScan( true, cstyle, SS[iS].x, SS[iS].y, e->Z(j), + e->P()->xco.str(), e->P()->yco.str(), + "curve file "+strg(k)+" scan "+strg(j)+ + " segment "+strg(iS) ); } cstyle++; } else throw string( "PROGRAM ERROR plot invalid *e" ); } - plot->Doc( e->P()->lDoc ); + plot->plotDoclines( e->P()->lDoc ); if( fc ) - plot->Doc( fc->pInfo() ); + plot->plotDoclines( fc->pInfo() ); } } diff --git a/pub/src/frida2.cpp b/pub/src/frida2.cpp index cf9ecce734a4cad5593bb28865fd47a64117da7e..bbd540dd0e9a6883a3ee6824f9694ac8ea887f1d 100644 --- a/pub/src/frida2.cpp +++ b/pub/src/frida2.cpp @@ -258,11 +258,17 @@ int main() cout << "Graphic commands:\n" " gx set x range\n" " gy set x range\n" - " ga, gxa, gya auto-ranges\n" - " gs set auxiliary parameters\n" + " ga auto-ranges\n" + " gxa x auto-range\n" + " gya y auto-range\n" + " gxl log x (toggle; or use gxf+ gxf-)\n" + " gyl log y\n" + " gxf force x into frame (toggle; or use gxl+ gxl-)\n" + " gyf force x into frame\n" + " gnp set maximum number of points\n" " gp plot to complete .ps file\n" " gf plot to short .psX file\n" - " gl list of plot windows\n" + " gw list of plot windows\n" " g<n> switch to plot window <n>\n" " gd dialog (within gnuplot)\n" " p plot\n" @@ -279,15 +285,17 @@ int main() Plots[iPlot]->X.R = CRange(); } else if (cmd == "gya") { Plots[iPlot]->Y.R = CRange(); - } else if (cmd == "gs") { - Plots[iPlot]->Multiask(); + } else if (cmd.substr(0,2) == "gx" || + cmd.substr(0,2) == "gy" || + cmd == "gnp" ) { + Plots[iPlot]->setAux( cmd ); } else if (cmd == "gp") { - Plots[iPlot]->Save( true ); + Plots[iPlot]->writePostscript( true ); } else if (cmd == "gf") { - Plots[iPlot]->Save( false ); + Plots[iPlot]->writePostscript( false ); } else if (cmd == "gd") { // graph dialog - Plots[iPlot]->Dialog(); - } else if (cmd == "gl") { + Plots[iPlot]->feedGnuplot(); + } else if (cmd == "gw") { for( uint i=0; i<nPlot; ++i ){ printf( " %c %1i %s\n", i==iPlot ? '*' : ' ', i, Plots[i]->info().c_str() ); @@ -547,7 +555,6 @@ int main() NSpecial::FourierCosine(); } else if ( cmd == "qui" || cmd=="quit" ) { - Plots[iPlot]->Close(); exit(0);