source: Sophya/trunk/SophyaPI/PIext/pihisto.cc@ 3132

Last change on this file since 3132 was 3132, checked in by ansari, 19 years ago

introduction methode P1DHistoWrapper::DecodeOptionString et son implementation par defaut, Reza 12/01/2007

File size: 10.5 KB
RevLine 
[544]1// Classe traceur d histogramme 96-99
[3125]2// C. Magneville , R. Ansari 2000-2007
3// (C) CEA-DAPNIA LAL-IN2P3/CNRS
[544]4
[165]5#include <stdio.h>
[2517]6#include <stdlib.h>
7#include <iostream>
8#include <math.h>
[295]9#include <typeinfo>
10
[165]11#include "pihisto.h"
12
[3132]13//------ Implementation classe P1DHistoWrapper
14P1DHistoWrapper::P1DHistoWrapper()
15: mScale(1.) , mOff(0.)
16{
17}
18
19P1DHistoWrapper::~P1DHistoWrapper()
20{
21}
22
23int P1DHistoWrapper::GetStatInfoAsText(vector<string> & /* text */ )
24{
25 return 0;
26}
27
28int P1DHistoWrapper::DecodeOptionString(vector<string> & opt, bool rmdecopt)
29{
30 if(opt.size() < 1) return(0);
31
32 vector<string> udopt; // On gardera ici les options non decodees
33 unsigned int k = 0;
34 int ndec = opt.size();
35 for( k=0; k<opt.size(); k++ ) {
36 string & opts = opt[k];
37 if(opts.substr(0,7) == "hs1") {
38 mScale = 1.; mOff = 0.;
39 }
40 else if(opts.substr(0,7) == "hscale=") {
41 mScale = atof(opts.substr(7).c_str());
42 }
43 else if(opt[k].substr(0,8) == "hoffset=") {
44 mOff = atof(opts.substr(8).c_str());
45 }
46 else {
47 ndec--;
48 // S'il faut supprimer les options decodees
49 if (rmdecopt) udopt.push_back(opts);
50 }
51 }
52 // S'il faut supprimer les options decodees, on remplace l'argument opt
53 // par le vecteur des options non decodees.
54 if (rmdecopt) opt = udopt;
55 return(ndec);
56}
57
58
[544]59//++
60// Class PIHisto
61// Lib PIext
62// include pihisto.h
63//
[3125]64// Classe traceur d'objet histogramme (classe *P1DHistoWrapper*)
[544]65//--
66//++
67// Links Parents
68// PIDrawer
69//--
70//++
71// Titre Constructeur, méthodes
72//--
73//++
[3125]74// PIHisto(P1DHistoWrapper* histo, bool ad=false)
[544]75// Constructeur. Si "ad == true", l'objet "histo" est détruit par
76// le destructeur de l'objet "PIHisto"
77// Note : "histo" doit être créé par new
78//
79// void SetStats(bool fg=true)
80// Active/ désactive l'indication des statistiques d'histogramme
81//--
82
83
[3125]84PIHisto::PIHisto(P1DHistoWrapper* histo, bool ad)
[165]85: PIDrawer(), mHisto(histo)
86{
87 mAdDO = ad; // Flag pour suppression automatique de mHisto
[2232]88 SetStats();
89 SetError();
[2517]90 SetFilled();
[2383]91 SetStatPosOffset();
[1856]92 SetName("HistoDrw");
[165]93}
94
95PIHisto::~PIHisto()
96{
[2229]97 if(mAdDO) delete mHisto;
[165]98}
99
100void
101PIHisto::UpdateLimits()
102{
103 if (!mHisto) return;
[3125]104 double v1,v2,hmin,hmax;
105 hmin = 9.e39;
106 hmax = -9.e39;
107 for (int i=1; i<mHisto->NBins(); i++) {
108 v1 = (*mHisto)(i); //DEL - mHisto->Error(i);
109 v2 = (*mHisto)(i); //DEL + mHisto->Error(i);
110 if(v1<hmin) hmin = v1;
111 if(v2>hmax) hmax = v2;
[165]112 }
[3125]113 // REZA$CHECK : Modifier pour tenir compte si axe (Y) en log
114 v1 = 0.1*(hmax-hmin);
115 hmin -= v1; hmax += v1;
116
[2229]117 if(hmax<=hmin) hmax = hmin+1.;
[165]118 SetLimits(mHisto->XMin(), mHisto->XMax(), hmin, hmax);
119}
120
121void
[205]122PIHisto::Draw(PIGraphicUC* g, double /*xmin*/, double /*ymin*/, double /*xmax*/, double /*ymax*/)
[165]123{
[548]124 if (axesFlags != kAxesNone) DrawAxes(g);
125
[2229]126 if (!mHisto) return;
[3055]127 if (mHisto->NBins()<=0) return;
[2229]128
[3125]129 mHisto->Update();
[203]130
[2469]131 bool oktrace=false;
[2517]132 // Tracer d'une polyline si demandee
133 bool drawpline=false;
134 if(GetGraphicAtt().GetLineAtt() != PI_NotDefLineAtt) drawpline=true;
[2469]135 // Tracer des marqueurs si demande ou si HProf
136 bool drawmarker=false;
[3125]137 if (GetGraphicAtt().GetMarker() != PI_NotDefMarker) drawmarker = true;
138//RZDEL || (typeid(*mHisto) == typeid(HProf)) ) drawmarker = true;
[2469]139 // Tracer des erreurs ?
140 bool drawerr=false;
[2229]141 if(error==0) { // Gestion automatique des erreurs
[3125]142 //RZDEL Tracer les erreurs si HProf
143//RZDEL if( typeid(*mHisto)==typeid(HProf) ) drawerr=true;
[2229]144 // Trace les erreurs si marqueurs demandes
145 if(drawmarker) drawerr=true;
[2469]146 }
147 else if(error>0) drawerr=true;
148 else if(error<0) drawerr=false;
[2517]149 // Fill de l'histo ?
150 bool drawfill=false;
151 if(filled) drawfill=true; else drawfill=false;
152 // Et aussi si on ne demande ni ligne ni marqueur ?
153 if( !drawmarker && !drawpline && !drawerr ) drawfill=true;
[2229]154
[2517]155 // Remplissage des bins avec la couleur courante (trace en premier)
156 if(drawfill) {
157 oktrace = true;
158 for(int i=0; i<mHisto->NBins(); i++) {
159 double left = mHisto->BinLowEdge(i);
160 double width = mHisto->BinWidth();
161 double bottom = 0;
162 double height = (*mHisto)(i);
163 g->DrawFBox(left,bottom,width,height);
164 }
165 }
166
[2229]167 // Trace des marqeurs
168 if(drawmarker) {
169 double x1,y1; oktrace = true;
170 for(int i=0; i<mHisto->NBins(); i++) {
171 x1 = mHisto->BinCenter(i);
172 y1 = (*mHisto)(i);
173 g->DrawMarker(x1,y1);
174 }
175 }
176
177 // Trace des erreurs
178 if(drawerr) {
179 if(GetGraphicAtt().GetLineAtt()==PI_NotDefLineAtt) g->SelLine(PI_ThinLine);
180 double x1,x2,y1,y2; oktrace = true;
[205]181 double bw = mHisto->BinWidth();
[1057]182 for(int i=0; i<mHisto->NBins(); i++) {
[165]183 if(mHisto->Error(i)>0.) {
184 // barres d'erreur verticales
185 x1 = x2 = mHisto->BinCenter(i);
186 y1 = (*mHisto)(i) - mHisto->Error(i);
187 y2 = (*mHisto)(i) + mHisto->Error(i);
188 g->DrawLine(x1,y1, x1, y2);
189 // limites de barres d'erreurs (horizontales)
190 x1 -= bw/3.; x2 += bw/3.;
191 g->DrawLine(x1,y1, x2, y1);
192 g->DrawLine(x1,y2, x2, y2);
193 }
194 }
195 }
[2229]196
[2517]197 // Trace de la ligne continue si demandee
198 if(drawpline) {
[2469]199 PIGrCoord* x1 = new PIGrCoord[2*mHisto->NBins()+2];
200 PIGrCoord* y1 = new PIGrCoord[2*mHisto->NBins()+2];
201 double dx = mHisto->BinWidth();
202 int npt=0;
203 x1[npt] = mHisto->BinLowEdge(0);
204 y1[npt] = 0;
205 npt++;
[1057]206 for(int i=0; i<mHisto->NBins(); i++) {
[2469]207 x1[npt] = mHisto->BinLowEdge(i);
208 y1[npt] = (*mHisto)(i);
209 npt++;
210 x1[npt] = (double)x1[npt-1] + dx;
211 y1[npt] = y1[npt-1];
212 npt++;
[165]213 }
[2469]214 x1[npt] = x1[npt-1];
215 y1[npt] = 0;
216 npt++;
[2517]217 g->DrawPolygon(x1,y1,npt,false);
218 delete [] x1; delete [] y1;
219 oktrace = true;
[165]220 }
[2229]221
222 // Trace/Ecriture des statistiques
[203]223 // A faire a la fin - DrawStats change l'attribut de ligne
[1057]224 if(stats) DrawStats(g);
[165]225}
226
[1971]227int
228PIHisto::DecodeOptionString(vector<string> & opt, bool rmdecopt)
229{
[2229]230 int optsz1 = opt.size();
231 if(optsz1<1) return(0);
[1971]232 int ndec1 = PIDrawer::DecodeOptionString(opt, rmdecopt);
[2229]233 if(optsz1-ndec1<1) return(ndec1); // si tout a ete decode
[1971]234
235 vector<string> udopt; // On gardera ici les options non decodees
236 unsigned int k = 0;
237 int ndec = opt.size();
238 for( k=0; k<opt.size(); k++ ) {
239 string opts = opt[k];
[2229]240 if(opts=="sta" || opts=="stat" || opts=="stats") SetStats(true);
241 else if( opts=="nsta" || opts=="nstat"
242 || opts=="nostat" || opts=="nostats") SetStats(false);
243 else if(opts=="err") SetError(1);
[2523]244 else if(opts=="noerr" || opts=="nerr") SetError(-1);
[2229]245 else if(opts=="autoerr") SetError(0);
[2517]246 else if(opts=="fill") SetFilled(true);
[2523]247 else if(opts=="nofill" || opts=="nfill") SetFilled(false);
[2383]248 else if(opts.substr(0,11) == "statposoff=") {
249 float xo=0., yo=0.;
250 sscanf(opts.substr(11).c_str(),"%g,%g",&xo, &yo);
251 SetStatPosOffset(xo, yo);
252 }
[1971]253 else {
254 ndec--;
255 // S'il faut supprimer les options decodees
256 if (rmdecopt) udopt.push_back(opts);
257 }
[2229]258 }
[3132]259
[1971]260 // S'il faut supprimer les options decodees, on remplace l'argument opt
261 // par le vecteur des options non decodees.
262 if (rmdecopt) opt = udopt;
[3132]263
264 // Decodage des options par le histo-wrapper
265 int ndec2 = 0;
266 if ( ( optsz1-ndec1-ndec > 0) && (mHisto) ) {
267 ndec2 = mHisto->DecodeOptionString(opt, rmdecopt);
268 }
269 return(ndec+ndec1+ndec2);
[1971]270}
271
[2523]272int
273PIHisto::OptionToString(vector<string> & opt) const
274{
275 PIDrawer::OptionToString(opt);
276
277 if(stats) opt.push_back("stat"); else opt.push_back("nstat");
278 if(error==-1) opt.push_back("noerr");
279 else if(error==0) opt.push_back("autoerr");
280 else if(error==1) opt.push_back("err");
281 if(filled) opt.push_back("fill"); else opt.push_back("nofill");
282
283 char str[256]; sprintf(str,"statposoff=%g,%g",spoX,spoY);
284 opt.push_back(str);
285
286 return 1;
287}
288
[165]289void
[2229]290PIHisto::GetOptionsHelpInfo(string& info)
291{
292info += " ---- PIHisto options help info : \n" ;
[2383]293info += " sta,stat,stats: activate statistic display\n";
[2229]294info += " nsta,nstat,nostat,nostats: deactivate statistic display\n";
[2523]295info += " err / noerr,nerr : draw, do not draw error bars\n";
[2229]296info += " autoerr : draw error bars if Marker drawing requested OR Profile histo\n";
[2523]297info += " fill / nofill,nfill : fill, do not fill bars with selected color\n";
[2383]298info += " statposoff=OffsetX,OffsetY : Position offset for Stats drawing \n";
299info += " as a fraction of total size \n";
[3132]300info += " ---- HistoWrapper options : \n" ;
301info += " hscale=value : multiplicative factor (in Y) \n" ;
302info += " hoffset=value : additive coefficient (in Y) \n" ;
303info += " hs1 : set hscale=1 hoffset=0 (default) \n" ;
[2388]304// On recupere ensuite la chaine info de la classe de base
305PIDrawer::GetOptionsHelpInfo(info);
[2229]306return;
307}
308
309void
[165]310PIHisto::DrawStats(PIGraphicUC* g)
311{
312 if (!mHisto) return;
[203]313 // if (mLAtt == PI_NotDefLineAtt) g->SelLine(PI_ThinLine);
314 g->SelLine(PI_ThinLine);
[1905]315 g->SelFontSz((YMax() - YMin())/30);
[1644]316
317 // La hauteur de la cellule
[544]318 PIGrCoord a, d;
319 double cH = (double)g->GetFontHeight(a,d);
[3125]320 vector<string> lines;
321 int nlig = mHisto->GetStatInfoAsText(lines);
322 if (nlig < 1) return;
[1644]323
[3125]324 double cellHeight = (nlig+0.6) * cH;
[1644]325
[3125]326 int idxll = 0;
327
328 int kl;
329 // on recherche la ligne la plus longue
330 for(kl=1; kl<nlig; kl++)
331 if ( lines[kl].length() > lines[idxll].length() ) idxll = kl;
332
333 double cellWidth = 1.1 * (double)g->CalcStringWidth(lines[idxll].c_str());
334
[2383]335 double ofpx = spoX*(XMax()-XMin());
336 double ofpy = spoY*(YMax()-YMin());
337
[1645]338 double xu, yu, cw;
[1644]339 // Les limites du cadre
[1645]340 xu = g->DeltaUCX(XMax(), -cellWidth);
341 yu = g->DeltaUCY(YMax(), -cellHeight);
[2383]342 double recw = XMax()-xu;
343 double rech = YMax()-yu;
344 xu += ofpx; yu += ofpy;
345 g->DrawBox(xu, yu, recw, rech);
[1644]346
[1645]347 // L'ecriture des labels (attention aux inversions possibles des axes!)
348 cw = (g->isAxeXDirRtoL()) ? -0.05*cellWidth : -0.95*cellWidth;
349 xu = g->DeltaUCX(XMax(),cw);
350
351 cw = (g->isAxeYDirUpDown()) ? -0.15*cH : -1.15*cH;
352 yu = g->DeltaUCY(YMax(),cw);
[2383]353 xu += ofpx; yu += ofpy;
[3125]354
355 for(kl=0; kl<nlig; kl++) {
356 g->DrawString(xu, yu, lines[kl].c_str() );
357 cw += -1.15*cH;
358 yu = g->DeltaUCY(YMax(),cw); yu += ofpy;
359 }
[165]360
361}
[2517]362
363
364
365/* --Methode-- */
366double PIHisto::GetDistanceToPoint(double x, double y)
367{
368 if (!mHisto) return 1.e+9;
369
370 double dist = -1.e+18;
371 for(int i=0; i<mHisto->NBins(); i++) {
372 double xp=mHisto->BinCenter(i);
373 double yp=(*mHisto)(i);
374 xp = (xp-x)/(XMax()-XMin())/0.5;
375 yp = (yp-y)/(YMax()-YMin())/0.5;
376 xp = xp*xp+yp*yp;
377 if(dist<0. || xp<dist) dist = xp;
378 }
379 dist=sqrt(fabs(dist));
380 //cout<<dist<<"PIHisto: xlim="<<XMin()<<","<<XMax()<<" ylim="<<YMin()<<","<<YMax()
381 // <<" NBins="<<mHisto->NBins()<<endl;
382 //cout<<"....d="<<dist<<" x="<<x<<" y="<<y<<endl;
383
384 return dist;
385}
Note: See TracBrowser for help on using the repository browser.