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
Line 
1// Classe traceur d histogramme 96-99
2// C. Magneville , R. Ansari 2000-2007
3// (C) CEA-DAPNIA LAL-IN2P3/CNRS
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <iostream>
8#include <math.h>
9#include <typeinfo>
10
11#include "pihisto.h"
12
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
59//++
60// Class PIHisto
61// Lib PIext
62// include pihisto.h
63//
64// Classe traceur d'objet histogramme (classe *P1DHistoWrapper*)
65//--
66//++
67// Links Parents
68// PIDrawer
69//--
70//++
71// Titre Constructeur, méthodes
72//--
73//++
74// PIHisto(P1DHistoWrapper* histo, bool ad=false)
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
84PIHisto::PIHisto(P1DHistoWrapper* histo, bool ad)
85: PIDrawer(), mHisto(histo)
86{
87 mAdDO = ad; // Flag pour suppression automatique de mHisto
88 SetStats();
89 SetError();
90 SetFilled();
91 SetStatPosOffset();
92 SetName("HistoDrw");
93}
94
95PIHisto::~PIHisto()
96{
97 if(mAdDO) delete mHisto;
98}
99
100void
101PIHisto::UpdateLimits()
102{
103 if (!mHisto) return;
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;
112 }
113 // REZA$CHECK : Modifier pour tenir compte si axe (Y) en log
114 v1 = 0.1*(hmax-hmin);
115 hmin -= v1; hmax += v1;
116
117 if(hmax<=hmin) hmax = hmin+1.;
118 SetLimits(mHisto->XMin(), mHisto->XMax(), hmin, hmax);
119}
120
121void
122PIHisto::Draw(PIGraphicUC* g, double /*xmin*/, double /*ymin*/, double /*xmax*/, double /*ymax*/)
123{
124 if (axesFlags != kAxesNone) DrawAxes(g);
125
126 if (!mHisto) return;
127 if (mHisto->NBins()<=0) return;
128
129 mHisto->Update();
130
131 bool oktrace=false;
132 // Tracer d'une polyline si demandee
133 bool drawpline=false;
134 if(GetGraphicAtt().GetLineAtt() != PI_NotDefLineAtt) drawpline=true;
135 // Tracer des marqueurs si demande ou si HProf
136 bool drawmarker=false;
137 if (GetGraphicAtt().GetMarker() != PI_NotDefMarker) drawmarker = true;
138//RZDEL || (typeid(*mHisto) == typeid(HProf)) ) drawmarker = true;
139 // Tracer des erreurs ?
140 bool drawerr=false;
141 if(error==0) { // Gestion automatique des erreurs
142 //RZDEL Tracer les erreurs si HProf
143//RZDEL if( typeid(*mHisto)==typeid(HProf) ) drawerr=true;
144 // Trace les erreurs si marqueurs demandes
145 if(drawmarker) drawerr=true;
146 }
147 else if(error>0) drawerr=true;
148 else if(error<0) drawerr=false;
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;
154
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
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;
181 double bw = mHisto->BinWidth();
182 for(int i=0; i<mHisto->NBins(); i++) {
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 }
196
197 // Trace de la ligne continue si demandee
198 if(drawpline) {
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++;
206 for(int i=0; i<mHisto->NBins(); i++) {
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++;
213 }
214 x1[npt] = x1[npt-1];
215 y1[npt] = 0;
216 npt++;
217 g->DrawPolygon(x1,y1,npt,false);
218 delete [] x1; delete [] y1;
219 oktrace = true;
220 }
221
222 // Trace/Ecriture des statistiques
223 // A faire a la fin - DrawStats change l'attribut de ligne
224 if(stats) DrawStats(g);
225}
226
227int
228PIHisto::DecodeOptionString(vector<string> & opt, bool rmdecopt)
229{
230 int optsz1 = opt.size();
231 if(optsz1<1) return(0);
232 int ndec1 = PIDrawer::DecodeOptionString(opt, rmdecopt);
233 if(optsz1-ndec1<1) return(ndec1); // si tout a ete decode
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];
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);
244 else if(opts=="noerr" || opts=="nerr") SetError(-1);
245 else if(opts=="autoerr") SetError(0);
246 else if(opts=="fill") SetFilled(true);
247 else if(opts=="nofill" || opts=="nfill") SetFilled(false);
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 }
253 else {
254 ndec--;
255 // S'il faut supprimer les options decodees
256 if (rmdecopt) udopt.push_back(opts);
257 }
258 }
259
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;
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);
270}
271
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
289void
290PIHisto::GetOptionsHelpInfo(string& info)
291{
292info += " ---- PIHisto options help info : \n" ;
293info += " sta,stat,stats: activate statistic display\n";
294info += " nsta,nstat,nostat,nostats: deactivate statistic display\n";
295info += " err / noerr,nerr : draw, do not draw error bars\n";
296info += " autoerr : draw error bars if Marker drawing requested OR Profile histo\n";
297info += " fill / nofill,nfill : fill, do not fill bars with selected color\n";
298info += " statposoff=OffsetX,OffsetY : Position offset for Stats drawing \n";
299info += " as a fraction of total size \n";
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" ;
304// On recupere ensuite la chaine info de la classe de base
305PIDrawer::GetOptionsHelpInfo(info);
306return;
307}
308
309void
310PIHisto::DrawStats(PIGraphicUC* g)
311{
312 if (!mHisto) return;
313 // if (mLAtt == PI_NotDefLineAtt) g->SelLine(PI_ThinLine);
314 g->SelLine(PI_ThinLine);
315 g->SelFontSz((YMax() - YMin())/30);
316
317 // La hauteur de la cellule
318 PIGrCoord a, d;
319 double cH = (double)g->GetFontHeight(a,d);
320 vector<string> lines;
321 int nlig = mHisto->GetStatInfoAsText(lines);
322 if (nlig < 1) return;
323
324 double cellHeight = (nlig+0.6) * cH;
325
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
335 double ofpx = spoX*(XMax()-XMin());
336 double ofpy = spoY*(YMax()-YMin());
337
338 double xu, yu, cw;
339 // Les limites du cadre
340 xu = g->DeltaUCX(XMax(), -cellWidth);
341 yu = g->DeltaUCY(YMax(), -cellHeight);
342 double recw = XMax()-xu;
343 double rech = YMax()-yu;
344 xu += ofpx; yu += ofpy;
345 g->DrawBox(xu, yu, recw, rech);
346
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);
353 xu += ofpx; yu += ofpy;
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 }
360
361}
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.