Newer
Older
//***************************************************************************//
//* FRIDA: fast reliable interactive data analysis *//
//* (C) Joachim Wuttke 1990-, v2(C++) 2001- *//
//* http://apps.jcns.fz-juelich.de/frida *//
//***************************************************************************//
//! \file plot.cpp
//! \brief NPlot: plot data and curves
#include <vector>
#include <memory>
#include <math.h>
#include "defs.hpp"
#include "list.hpp"
#include "olf.hpp"
#include "mem.hpp"
#include "jsel.hpp"
#include "zentry.hpp"
#include "dualplot.hpp"
#include "plot.hpp"
#include "curve.hpp"
//**************************************************************************//
//**************************************************************************//
//! Loop over selected data files to determine x range.
void determine_Xrange( CPlot* plot, CList* JSel )
{
double inf, sup;
NOlm::IterateD fiter;
const vector<double> *vx;
bool first = true;
POld fd;
while((fd=fiter())) {
JSel->evaluate( 0, fd->nJ()-1 );
for ( int iv=0; iv<JSel->size(); ++iv ) {
if ( plot->X.logflag && (*vx)[i]<=0 )
continue;
if ( first ){
inf = (*vx)[i];
sup = (*vx)[i];
first = false;
} else {
if ( (*vx)[i]<inf ) inf = (*vx)[i];
if ( (*vx)[i]>sup ) sup = (*vx)[i];
}
}
}
}
if ( first )
throw "x range is empty";
plot->X.setRoundedLimits( "x", inf, sup );
}
//! Loop over selected files to determine y range for current x range.
void determine_Yrange( CPlot* plot, CList* JSel )
{
NOlm::IterateO iter;
POlo f;
while( (f=iter()) ){
POlc fc = P2C( f );
if ( fc && fc->kconv!=-1 )
continue;
POld fd = P2D( f );
JSel->evaluate( 0, f->nJ()-1 );
for ( int iv=0; iv<JSel->size(); ++iv ){
PSpec s;
if ( fd ){
s = fd->VS(j);
} else {
s = PSpec( new CSpec );
plot->X.set_xgrid( s->x, 97 );
fc->curve_val_vec( &(s->y), s->x, k, j );
}
if ( !plot->X.contains( s->x[i] ) )
continue;
if ( plot->Y.logflag && s->y[i]<=0 )
continue;
if (s->y[i]<inf) inf=s->y[i];
if (s->y[i]>sup) sup=s->y[i];
throw "y range is empty";
plot->Y.setRoundedLimits( "y", inf, sup );
}
//**************************************************************************//
//* Subroutines: plot one scan *//
//**************************************************************************//
//! Plot scan j of data file fd; return number of points plotted.
int plot_data( CPlot* plot, POld fd, int k, int j, int pstyle )
if ( n!=s->y.size() )
throw "BUG: plot: x.size<>y.size";
// Filter: x,y -> xp,yp if inside frame
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
double x = s->x[i];
if ( !plot->X.contains(x) ) {
if ( x<=plot->X.inf ){
x = plot->X.inf;
nxl++;
}
if ( x>=plot->X.sup ){
x = plot->X.sup;
nxh++;
}
if ( !plot->X.force )
continue;
}
double y = s->y[i];
if ( !plot->Y.contains(y) ) {
if ( y<=plot->Y.inf ){
y = plot->Y.inf;
nyl++;
}
if ( y>=plot->Y.sup ){
y = plot->Y.sup;
nyh++;
}
if ( !plot->Y.force )
continue;
}
if ( np==plot->maxpoints && np<n ) {
cout << "reached maxpoints at " << s->x[i] << "\n";
}
xp.push_back( x );
yp.push_back( y );
if ( s->dy.size() )
dyp.push_back( s->dy[i] );
np = xp.size();
if ( np > plot->maxpoints ) // continue in large steps
i += plot->maxpoints;
}
if ( np==0 ) {
cout << "file " << k << " spec " << j << " all " << n <<
" points outside plot range:\n";
if ( nxl )
cout << " " << nxl << " points < xmin\n";
if ( nxh )
cout << " " << nxh << " points > xmax\n";
if ( nyl )
cout << " " << nyl << " points < ymin\n";
if ( nyh )
cout << " " << nyh << " points > ymax\n";
} else {
plot->addSpec(
false, true, pstyle, xp, yp, dyp, fd->V[j]->z,
fd->xco.str_std(), fd->yco.str_std(),
"data file " + S(k) + " spectrum "+S(j) );
}
return np;
}
//! Plot scan j of convolved curve file fc; return number of points plotted.
int plot_curve_convolved( CPlot* plot, POlc fc, int k, int j, int cstyle )
NCurveFile::getConv( &sconv, &kconv, &jconv, k, j );
for ( int i=0; i<sconv->size(); ++i ){
double x = sconv->x[i];
if ( plot->X.contains( x ) )
xp.push_back( x );
}
fc->curve_val_vec( &yp, xp, k, j );
vector<double> xo, yo;
if ( !( plot->X.contains( xp[i] ) &&
plot->Y.contains( yp[i] ) ) )
continue;
xo.push_back( xp[i] );
yo.push_back( yp[i] );
}
if ( xo.size()==0 ){
cout << "curve k="<<S(k)<<", j="<<S(j)<<
plot->addSpec( true, true, cstyle, xo, yo, novec, fc->V[j]->z,
fc->xco.str_std(), fc->yco.str_std(),
"curve file "+S(k)+" spectrum "+S(j) );
//! Plot scan j of curve file fc, using grid from file kd.
int plot_curve_to_grid( CPlot* plot, POlc fc, int k, int j, int cstyle )
{
if( fc->kd==-1 )
throw "data reference not set, incompatible with cg+";
POld fd = NOlm::mem_get_D(fc->kd);
if( !fd )
throw "data reference not found";
if( j>=fd->nJ() )
throw "number of spectra does not match";
vector<double> *xc = &(fd->VS(j)->x);
vector<double> novec, yc, xp, yp;
fc->curve_val_vec( &yc, *xc, k, j );
if ( plot->X.contains((*xc)[i]) && plot->Y.contains(yc[i]) ) {
xp.push_back( (*xc)[i] );
yp.push_back( yc[i] );
}
}
plot->addSpec( true, true, cstyle, xp, yp, novec, fc->V[j]->z,
fc->xco.str_std(), fc->yco.str_std(),
"curve file "+S(k)+" spectrum "+S(j) );
return xp.size();
}
//! Plot scan j of non-convolved curve file fc on equidistant grid;
//! return number of points plotted.
int plot_curve_equidist( CPlot* plot, POlc fc, int k, int j, int cstyle )
{
vector<double> novec;
// equidistant grid
vector<double> xc, yc, xp, yp;
plot->X.set_xgrid( xc, npts );
fc->curve_val_vec( &yc, xc, k, j );
if ( plot->X.contains(xc[i]) && plot->Y.contains(yc[i]) ) {
xp.push_back( xc[i] );
yp.push_back( yc[i] );
}
}
plot->addSpec( true, true, cstyle, xp, yp, novec, fc->V[j]->z,
fc->xco.str_std(), fc->yco.str_std(),
"curve file "+S(k)+" spectrum "+S(j) );
return xp.size();
}
//! Plot scan j of non-convolved curve file fc, refining the grid where
//! necessary; return number of points plotted.
int plot_curve_refine( CPlot* plot, POlc fc, int k, int j, int cstyle )
{
// refinement cares to:
// - stop/start line when leaving/reentering/crossing(TODO) the frame
// - TODO interpolate when crossing the horizontal border
// - interpolate at discontinuities
vector<double> xc, yc, xn, yn;
vector<double> novec;
// start with equidistant grid:
plot->X.set_xgrid( xc, npts );
// refinement loop:
for ( int iref=0; ; ++iref ) {
if ( !xc.size() ){
if ( !iref )
throw "BUG: plot_curve_refine called with xc.size()=0";
else
break; // regular exit
}
// cout << "DEB refinement #" <<iref<< ", xc.size=" <<xc.size()<< "\n";
// evaluate curve for grid xc:
fc->curve_val_vec( &yc, xc, k, j );
// printf ("DEB xc yc %12.6g %12.6g\n", xc[i], yc[i] );
// merge xc,yc and xn,yn:
if ( iref==0 ) {
xn = xc; yn = yc;
} else {
vector<double> xa, ya;
for ( ; ic<xc.size() && in<xn.size(); ) {
if ( plot->X.close_enough( xc[ic], xn[ic], 1e-7 ) ){
++in; // skip new point
} else if ( xc[ic]<xn[in] ) {
xa.push_back( xc[ic] );
ya.push_back( yc[ic] );
++ic;
} else {
xa.push_back( xn[in] );
ya.push_back( yn[in] );
++in;
}
}
for ( ; ic<xc.size(); ++ic ) {
xa.push_back( xc[ic] );
ya.push_back( yc[ic] );
}
for ( ; in<xn.size(); ++in ) {
xa.push_back( xn[in] );
ya.push_back( yn[in] );
}
xn = xa; yn = ya;
}
// printf ("DEB xn yn %12.6g %12.6g\n", xn[i], yn[i] );
// end of loop
if ( iref>=10 || xn.size()>=plot->maxpoints )
break; // alternate exit: too many refinements or too many points
// eliminate points outside y range (except border points):
vector<double> xa, ya;
xa.push_back( xn[0] );
ya.push_back( yn[0] );
new_segment:
xa.push_back( xn[i] );
ya.push_back( yn[i] );
if ( !plot->Y.contains(yn[i]) ) {
for ( int ii=i+1; ii<xn.size()-1; ++ii ) {
if ( plot->Y.contains(yn[ii]) ) {
if ( ii-1>i ) {
xa.push_back( xn[ii-1] );
ya.push_back( yn[ii-1] );
}
i = ii;
goto new_segment;
}
}
}
}
xa.push_back( xn.back() );
ya.push_back( yn.back() );
xn = xa; yn = ya;
// printf ("DEB xy %12.6g %12.6g\n", xn[i], yn[i] );
// set additional base points:
bool insert_next = false;
xc.clear();
for ( int i=1; i<xn.size()-1; ++i ) {
if ( i<xn.size()-2 ) {
double yi = ( (xn[i+1]-xn[i])*yn[i-1] +
(xn[i]-xn[i-1])*yn[i+1] ) /
(xn[i+1]-xn[i-1]);
if ( !plot->Y.close_enough( yn[i], yi, 0.005 ) ) {
xc.push_back( (xn[i-1] + xn[i])/2 );
insert_next = true;
continue;
}
}
if ( insert_next ) {
xc.push_back( (xn[i-1] + xn[i])/2 );

Wuttke, Joachim
committed
if ( ( plot->Y.contains(yn[i]) &&
!plot->Y.contains(yn[i-1]) ) ||
( !plot->Y.contains(yn[i]) &&
plot->Y.contains(yn[i-1]) ) ) {
xc.push_back( (xn[i-1] + xn[i])/2 );
continue;
}
}
// temporary check
if( xc.size() )
if ( xc[i+1]<=xc[i] )
throw "BUG: new base points not sorted at " +
}
// divide into segments and plot:
vector<double> xa, ya;
bool first_seg = true;
npts = 0;
if ( plot->Y.contains(yn[i]) ) {
xa.push_back( xn[i] );
ya.push_back( yn[i] );
}
if ( !plot->Y.contains(yn[i]) || i==xn.size()-1 ) {
npts += xa.size();
plot->addSpec(
true, first_seg, cstyle, xa, ya,
novec, fc->V[j]->z, fc->xco.str_std(), fc->yco.str_std(),
"curve file "+S(k)+ " spectrum "+S(j) );
xa.clear();
ya.clear();
first_seg = false;
}
}
}
return npts;
}
//**************************************************************************//
//* Plot routine is accessible from the main menu *//
//**************************************************************************//
//! Plot set of spectra, or add to open plot.
void NPlot::Plot( class CPlot *plot, bool add, const string& mode )
{
static CList JSel;
static int pstyle=1, cstyle=1;
static string jSel = "";
JSelAsk( "Plot which spectra", &jSel, &JSel );
JSel.increment( +1, 0, NOlm::nJ_max()-1 );
} else if ( mode == "prev" ) {
JSel.increment( -1, 0, NOlm::nJ_max()-1 );
if ( !add ) { // prepare frame (ranges, labels)
pstyle = 1;
cstyle = 1;
if (!plot->X.finite())
determine_Xrange( plot, &JSel );
if (!plot->Y.finite())
determine_Yrange( plot, &JSel );
// build label: (zur Zeit nur vom ersten File; definiere +=)
CCoord xCo = NOlm::sel_first()->xco;
CCoord yCo = NOlm::sel_first()->yco;
// draw new frame:
plot->clearFrame();
plot->plotFrame( xCo.str_ps(), yCo.str_ps() );
}
plot->docTxLine( f->name );
plot->docTxLine( " " + f->lDoc[i] );
if ( fc ) {
vector<string> vs = fc->infoFile();
plot->docTxLine( " " + vs[i] );
plot->docTxLine( " " + fc->infoScanHeader() );
}
JSel.evaluate( 0, f->nJ()-1 );
for ( int iv=0; iv<JSel.size(); ++iv){
if ( fd ) {
continue;
} else if ( fc ) {
if ( fc->kconv!=-1 ) {
if ( !plot_curve_convolved( plot, fc, k, j, cstyle ) )
continue;
} else if ( fc->plot_to_grid ) {
if ( !plot_curve_to_grid( plot, fc, k, j, cstyle ) )
continue;
} else if ( !plot->refine ) {
if ( !plot_curve_equidist( plot, fc, k, j, cstyle ) )
continue;
} else {
if ( !plot_curve_refine( plot, fc, k, j, cstyle ) )
continue;
} else {
throw "PROGRAM ERROR plot: unexpected file type";
}
if ( fd ) {
plot->docPtTxLine( " " + f->infoLine( j ), pstyle );
++pstyle;
} else if ( fc ) {
plot->docCvTxLine( " " + f->infoLine( j ), cstyle );
++cstyle;
}
}
}
plot->showSpecs();
}