source: Sophya/trunk/SophyaPI/PIext/pintuple.cc@ 3559

Last change on this file since 3559 was 3559, checked in by ansari, 17 years ago

Amelioration gestion taille de fonte ds PIHisto, PINTuple ... en utilisant le flag AutoFontSize mis ds la classe PIDrawer (attributs autofontsize=, fixedfontsize), Reza 24/12/2008

File size: 15.6 KB
RevLine 
[537]1// Peida Interactive - PI R. Ansari 97-99
2// Traceur (Drawer) pour NTupleInterface
3// LAL (Orsay) / IN2P3-CNRS DAPNIA/SPP (Saclay) / CEA
4
[165]5#include <stdio.h>
[2517]6#include <stdlib.h>
7#include <iostream>
8#include <math.h>
[2615]9#include "sopnamsp.h"
[165]10#include "pintuple.h"
11
[537]12//++
13// Class PINTuple
14// Lib PIext
15// include pintuple.h
16//
17// Classe de traceur 2D (dans un plan) à partir des données
18// d'un objet implémentant l'interface *NTupleInterface*.
19// Les objets "PINTuple" peuvent tracer des signes (markers)
20// éventuellement avec des barres d'erreur et une étiquette
[2373]21// pour chaque point. Si un nom de colonne poids est spécifié,
22// la taille et/ou la couleur des signes (markers) sera fonction
23// de la valeur de poids.
[537]24//--
25//++
26// Links Parents
27// PIDrawer
28//--
29//++
30// Links Voir aussi
31// NTupleInterface
32// PINTuple3D
33//--
34
35//++
36// Titre Constructeur
37//--
38//++
39// PINTuple(NTupleInterface* nt, bool ad)
[544]40// Constructeur. Si "ad == true", l'objet "nt" est détruit par
[537]41// le destructeur de l'objet "PINTuple"
[2373]42// Note : "nt" doit être créé par new dans ce cas.
[537]43//--
[165]44
45/* --Methode-- */
[326]46PINTuple::PINTuple(NTupleInterface* nt, bool ad)
[165]47: PIDrawer()
48{
49 mNT = nt;
50 mAdDO = ad;
[544]51 SetStats(true);
[2383]52 SetStatPosOffset();
[2350]53 ConnectPoints(false);
[2373]54 UseSizeScale(true, 5);
55 UseColorScale(true);
[165]56 SelectXY(NULL, NULL);
[2373]57 SelectWt(NULL);
[165]58 SelectErrBar();
[486]59 SelectLabel(NULL);
[3269]60 SelectColorByName(NULL);
61 SelectColorByIndex(NULL);
[1856]62 SetName("NTupleDrw");
[2517]63 NptDraw = 0;
64
[165]65}
66
67PINTuple::~PINTuple()
68{
69 if (mAdDO && mNT) delete mNT;
70}
71
[537]72//++
73// Titre Méthodes
74//--
75//++
76// void SelectXY(const char* px, const char* py)
77// Choix des noms de colonnes X,Y définissant les coordonnées des points.
78// Ces deux colonnes doivent être spécifiées pour obtenir un tracé.
79// void SelectErrBar(const char* erbx=NULL, const char* erby=NULL)
80// Choix des noms de colonnes pour le tracé des barres d'erreur.
81// void SelectWt(const char* pw=NULL, int nbins=10)
82// Choix du nom de colonne poids. Dans ce cas, la taille du signe
83// (marker) sera proportionnel à la valeur de cette colonne pour
84// chaque point.
85// void SelectLabel(const char* plabel=NULL)
86// Choix du nom de colonne correspondant à l'étiquette.
87//--
88
[165]89/* --Methode-- */
90void PINTuple::SelectXY(const char* px, const char* py)
91{
[326]92string name;
[165]93if (mNT == NULL) xK = yK = -1;
94if (px == NULL) xK = -1;
[326]95else { name = px; xK = mNT->ColumnIndex(name); }
[165]96if (py == NULL) yK = -1;
[326]97else { name = py; yK = mNT->ColumnIndex(name); }
[165]98}
99
100/* --Methode-- */
[2373]101void PINTuple::SelectWt(const char* pw)
[333]102{
103if (pw == NULL) wK = -1;
104else { string name = pw; wK = mNT->ColumnIndex(name); }
105
106if (wK >= 0) mNT->GetMinMax(wK, wMin, wMax);
107else { wMin = 0.; wMax = 1.; }
108}
109
110/* --Methode-- */
[486]111void PINTuple::SelectLabel(const char* plabel)
112{
113if (plabel == NULL) lK = -1;
114else { string name = plabel; lK = mNT->ColumnIndex(name); }
115}
116
117/* --Methode-- */
[3272]118void PINTuple::SelectColorByName(const char* pcolnm)
[3269]119{
120if (pcolnm == NULL) cnK = -1;
121else { string name = pcolnm; cnK = mNT->ColumnIndex(name); }
122if (cnK >= 0) ciK = -1;
123}
124
125/* --Methode-- */
[3272]126void PINTuple::SelectColorByIndex(const char* pcolidx)
[3269]127{
128if (pcolidx == NULL) ciK = -1;
129else { string name = pcolidx; ciK = mNT->ColumnIndex(name); }
130if (ciK >= 0) cnK = -1;
131}
132
133
134/* --Methode-- */
[165]135void PINTuple::SelectErrBar(const char* erbx, const char* erby)
136{
[326]137string name;
[165]138if (mNT == NULL) xebK = yebK = -1;
139if (erbx == NULL) xebK = -1;
[326]140else { name = erbx; xebK = mNT->ColumnIndex(name); }
[165]141if (erby == NULL) yebK = -1;
[326]142else { name = erby; yebK = mNT->ColumnIndex(name); }
[165]143}
144
145
146/* --Methode-- */
147void PINTuple::UpdateLimits()
148{
149 if (!mNT) return;
[326]150 if (mNT->NbLines() <= 0) return;
[165]151 if ( (xK < 0) || (yK < 0) ) return;
152
153 // Commencer par trouver nos limites
[326]154 double xmin, xmax, ymin, ymax;
[165]155 xmin = ymin = 9.e19;
156 xmax = ymax = -9.e19;
157 mNT->GetMinMax(xK, xmin, xmax);
158 mNT->GetMinMax(yK, ymin, ymax);
[2115]159 PIAxes::ReSizeMinMax(isLogScaleX(),xmin,xmax);
160 PIAxes::ReSizeMinMax(isLogScaleY(),ymin,ymax);
161 SetLimits(xmin,xmax,ymin,ymax);
[548]162// SetAxesFlags(kBoxAxes | kExtTicks | kLabels); Ne pas faire - Reza 11/99
[165]163}
164
165
166/* --Methode-- */
[2469]167#define NMXMULTP_LOCAL 30 // Pour multipoint sans new
[205]168void PINTuple::Draw(PIGraphicUC* g, double xmin, double ymin, double xmax, double ymax)
[165]169{
[333]170double xp,yp,xer,yer,wp;
[326]171double xl,yl;
[2689]172long nok;
173int npolyg;
[165]174
175if (!mNT) return;
[548]176if (axesFlags != kAxesNone) DrawAxes(g);
[165]177if ( (xK < 0) || (yK < 0) ) return;
[1905]178if (GetGraphicAtt().GetLineAtt() == PI_NotDefLineAtt) g->SelLine(PI_ThinLine);
[326]179
[333]180// Pour tracer des markers avec taille fonction de Wt (poids)
181double dw = (wMax-wMin)/nWbins;
[2373]182if (dw < 1.e-19) dw = 1.e-19;
183
[3269]184// La couleur par defaut (pour le trace avec couleur specifie par nom de colonne (06/2007)
185PIColors defcol = GetGraphicAtt().GetColor();
186if (defcol == PI_NotDefColor) defcol = PI_Black;
187
[2373]188// Pour tracer des markers avec couleur en fonction de Wt (poids)
189PIColorMap * cmap = NULL;
190double dwc = 1.;
[2469]191int nwc = 1;
[2373]192bool revcmap;
193CMapId mcmapid = GetGraphicAtt().GetColMapId(revcmap);
194if( colorScale && (wK >= 0) && (mcmapid != CMAP_OTHER) ) {
195 cmap = new PIColorMap(mcmapid);
196 cmap->ReverseColorIndex(revcmap);
197 nwc = cmap->NCol();
[2469]198 dwc = (wMax-wMin)/(double)nwc;
[2373]199}
200
[333]201int msz,sz;
202
[1905]203PIMarker mmrk = GetGraphicAtt().GetMarker();
[333]204PIMarker mrk;
[1905]205if (wK >= 0) mrk = (mmrk != PI_NotDefMarker) ? mmrk : PI_CircleMarker;
206else mrk = (mmrk != PI_NotDefMarker) ? mmrk : PI_DotMarker;
[2373]207msz = GetGraphicAtt().GetMarkerSz();
[333]208if (msz < 1) msz = 1;
[344]209g->SelMarker(msz, mrk);
[333]210
[685]211PIGrCoord uxmin, uxmax, uymin, uymax;
212g->GetGrSpace(uxmin, uxmax, uymin, uymax);
213double xmin2 = uxmin;
214double ymin2 = uymin;
215double xmax2 = uxmax;
216double ymax2 = uymax;
217
[165]218nok = 0;
[326]219xp = yp = xl = yl = 0;
[2469]220PIGrCoord xpolyg[NMXMULTP_LOCAL], ypolyg[NMXMULTP_LOCAL];
[2517]221npolyg = 0;
222NptDraw = 0;
[2755]223
224// Mai 2005: Correction bug trace des lignes avec le pts en dehors de la zone (Reza)
225// flags pour la gestion des points/lignes a tracer
226bool fgokcurpt = true; // Point courant dans la zone a tracer
227bool fgoklastpt = true; // Le dernier point etait dans la zone a tracer
[2115]228for (long i=0; i<(long)mNT->NbLines(); i++) {
[2755]229 xl = xp; yl = yp; fgoklastpt = fgokcurpt;
230
[326]231 xp = mNT->GetCell(i, xK);
232 yp = mNT->GetCell(i, yK);
[2373]233
[2755]234 // Comptage du nombre de pts dans la zone graphique du widget
235 if ( !((xp < xmin2) || (xp > xmax2) || (yp < ymin2) || (yp > ymax2)) ) nok++;
236 // Gestion des limites a tracer
237 fgokcurpt = true;
238 if ( (xp < xmin) || (xp > xmax) || (yp < ymin) || (yp > ymax) ) fgokcurpt = false;
239 else NptDraw++;
240
[2373]241// Taille - couleur de marker en fonction du poids
[2755]242 if ( fgokcurpt &&(wK >= 0) ) wp = mNT->GetCell(i, wK);
243 if ( fgokcurpt && mrkSzScale && (wK >= 0) ) { // Changement de taille
[2373]244 sz = (int)((wp-wMin)/dw);
245 if (sz < 0) sz = 0;
246 if (sz > nWbins) sz = nWbins;
247 sz += msz;
248 if (sz < 2) g->SelMarker(sz, PI_DotMarker);
249 else g->SelMarker(sz, mrk);
250 }
251// Couleur du marker en fonction du poids
[2755]252 if( fgokcurpt && colorScale && (wK >= 0) && cmap ) {
[2373]253 int cid = (int)((wp-wMin)/dwc);
254 if (cid < 0) cid = 0;
255 if (cid >= nwc) cid = nwc-1;
256 g->SelForeground(*cmap, cid);
257 }
258
[3269]259// Si on a specifie un nom de colonne pour la couleur (06/2007)
260 if ( (cnK >= 0) || (ciK >= 0) ) {
261 PIColors scol = defcol;
262 if (cnK > 0)
263 scol = PIGraphicAtt::ColNameToColor(mNT->GetCelltoString(i, cnK));
264 else
265 scol = PIGraphicAtt::ColIndexToColor(mNT->GetCell(i, ciK));
266 if (scol == PI_NotDefColor) scol = defcol;
267 g->SelForeground(scol);
268 }
269
[2469]270 // Trace d'une ligne reliant les points
271 if( connectPts ) {
[2755]272 // On initialise le polygone avec le dernier point, si ce dernier ok
273 if((npolyg==0) && (i>0) && fgokcurpt) {xpolyg[0]=xl; ypolyg[0]=yl; npolyg=1;}
274 // On ajoute le point courant au polygone - sauf si celui-ci est vide
275 if((npolyg<NMXMULTP_LOCAL) && (npolyg>0))
[2469]276 {xpolyg[npolyg]=xp; ypolyg[npolyg]=yp; npolyg++;}
[2755]277 // On trace le polygone s'il est plein - ou le point courant en dehors
278 // (point courant en dehors -> discontinuite de la ligne
279 if( !fgokcurpt || (npolyg==NMXMULTP_LOCAL) )
[2469]280 {g->DrawPolygon(xpolyg,ypolyg,npolyg,false); npolyg=0;}
281 }
282
[2755]283 // Plus rien a faire si point en dehors -- on s'en va
284 if (!fgokcurpt) continue;
285
[2469]286 // Trace des erreurs selon X et Y
[2755]287 if (xebK >= 0) {
[326]288 xer = mNT->GetCell(i, xebK);
[165]289 if(xer>0.) g->DrawLine(xp-xer, yp, xp+xer, yp);
290 }
[2755]291 if (yebK >= 0) {
[326]292 yer = mNT->GetCell(i, yebK);
[165]293 if(yer>0.) g->DrawLine(xp, yp-yer, xp, yp+yer);
294 }
[2469]295
[486]296 // Trace du marker
[1905]297 if ((wK >= 0)||(lK < 0)||(mmrk != PI_NotDefMarker)) g->DrawMarker(xp, yp);
[2469]298
[486]299 // Trace eventuel du label
300 if (lK >= 0) g->DrawString(xp, yp, mNT->GetCelltoString(i, lK).c_str());
301
[165]302}
303
[2469]304// Fin du trace d'une ligne reliant les points si necessaire
305if( connectPts && npolyg>1 )
306 {g->DrawPolygon(xpolyg,ypolyg,npolyg,false); npolyg=0;}
307
[544]308if (stats) { // Trace de stats
[3269]309 g->SelForeground(defcol);
[3559]310// Reza(12/2008): utilisation de flag et fraction pour selection automatique taille de fonte
311 if (mAFSz) {
312 double fsz = (YMax() - YMin())*mFontSzF;
313 g->SelFontSz(fsz); // au lieu de 1/30*(ymax-ymin)
314 }
[1645]315 // La hauteur de la cellule
[544]316 PIGrCoord a,d;
317 double cH = (double)g->GetFontHeight(a,d);
[1645]318 double cellHeight = 1.2 * cH;
319 // Les labels et leurs longueurs -> largeur de la cellule
320 char label[64];
[2689]321 sprintf(label, "N=%ld (/%ld)", (long)nok, (long)mNT->NbLines());
[1644]322 double cellWidth = 1.1 * (double)g->CalcStringWidth(label);
[1645]323 double xu, yu, cw;
[2383]324 double ofpx = spoX*(XMax()-XMin());
325 double ofpy = spoY*(YMax()-YMin());
[1645]326 // Les limites du cadre
[548]327 xu = g->DeltaUCX(XMax(), - cellWidth);
328 yu = g->DeltaUCY(YMax(), - cellHeight);
[2383]329 double recw = XMax()-xu;
330 double rech = YMax()-yu;
331 xu += ofpx; yu += ofpy;
332 g->DrawBox(xu, yu, recw, rech);
[1645]333 // L'ecriture des labels (attention aux inversions possibles des axes!)
334 cw = (g->isAxeXDirRtoL()) ? -0.05*cellWidth : -0.95*cellWidth;
335 xu = g->DeltaUCX(XMax(),cw);
336 cw = (g->isAxeYDirUpDown()) ? -0.1*cH : -1.1*cH;
337 yu = g->DeltaUCY(YMax(),cw);
[2383]338 xu += ofpx; yu += ofpy;
[1645]339 g->DrawString(xu,yu,label);
[544]340}
341
[2373]342if (cmap) delete cmap;
[165]343return;
344}
[2469]345#undef NMXMULTP_LOCAL
[165]346
[344]347/* --Methode-- */
348void PINTuple::AppendTextInfo(string& info, double xmin, double ymin, double xmax, double ymax)
349{
350if (!mNT) return;
351if ( (xK < 0) || (yK < 0) ) return;
352
[2690]353long ncnt = 0;
[344]354double xp,yp;
355char buff[128];
[2689]356sprintf(buff,"PINTuple: NLines= %ld NCol= %ld \n", (long)mNT->NbLines(),
357 (long)mNT->NbColumns());
[344]358info += buff;
359info += mNT->LineHeaderToString();
[2115]360for(long i=0; i<(long)mNT->NbLines(); i++) {
[344]361 xp = mNT->GetCell(i, xK);
362 yp = mNT->GetCell(i, yK);
363 if ( (xp < xmin) || (xp > xmax) || (yp < ymin) || (yp > ymax) ) continue;
364 ncnt++;
365 if (ncnt > 101) continue;
366 info += mNT->LineToString(i);
367 }
368if (ncnt >= 101) info += " .... \n";
[2690]369sprintf(buff," %ld points inside selected region \n", (long)ncnt);
[344]370info += buff;
371// printf("PINTuple::AppendTextInfo()-DBG %g %g %g %g - %d\n", xmin, ymin, xmax, ymax, ncnt);
372return;
373}
[1971]374
375/* La methode DecodeOptionString permet de decoder un ensemble d'options
376 et de parametre d'affichage specifie sous forme d'un vecteur de string.
377 Si rmdecopt == true, les options decodees sont supprimees du vecteur
378 de string fourni en entree - ce qui permet l'enchainement eventuel
379 de plusieurs decodages de string.
380 Les options peuvent etre sous forme de flag : "stat" "nostat"
381 ou plus complexes, par exemple "dynamic=-3,3"
382 Rc: La methode renvoie le nombre d'options decodees
383*/
384
385/* --Methode-- */
386int PINTuple::DecodeOptionString(vector<string> & opt, bool rmdecopt)
387{
[2229]388 int optsz1 = opt.size();
389 if(optsz1<1) return(0);
[1971]390 // On appelle d'abord le decodage de la classe PIDrawer de laquelle
391 // on herite. (Pas obligatoire) on decode donc ici les attributs de
392 // couleur, fontes ...
393 int ndec1 = PIDrawer::DecodeOptionString(opt, rmdecopt);
[2229]394 if(optsz1-ndec1<1) return(ndec1); // si tout a ete decode
[1971]395
396 vector<string> udopt; // On gardera ici les options non decodees
397 unsigned int k = 0;
398 int ndec = opt.size();
399 for( k=0; k<opt.size(); k++ ) {
400 string opts = opt[k];
[2229]401 if(opts=="sta" || opts=="stat" || opts=="stats") SetStats(true);
402 else if( opts=="nsta" || opts=="nstat"
403 || opts=="nostat" || opts=="nostats") SetStats(false);
[2383]404 else if(opts.substr(0,11) == "statposoff=") {
[3149]405 double xo=0., yo=0.;
406 sscanf(opts.substr(11).c_str(),"%lf,%lf",&xo, &yo);
[2383]407 SetStatPosOffset(xo, yo);
408 }
[2350]409 else if (opts == "connectpoints") ConnectPoints(true);
[3505]410 else if (opts == "cpts") ConnectPoints(true);
[2350]411 else if (opts == "noconnectpoints") ConnectPoints(false);
[2373]412 else if (opts == "colorscale") UseColorScale(true);
413 else if (opts == "nocolorscale") UseColorScale(false);
414 else if (opts == "sizescale") UseSizeScale(true);
415 else if (opts == "nosizescale") UseSizeScale(false);
416 else if (opts.substr(0,10) == "sizescale=") {
417 int nbn = atoi(opts.substr(10).c_str());
418 UseSizeScale(true, nbn);
419 }
[2383]420
[1971]421 else {
422 // Si option non decode
423 ndec--;
424 // S'il faut supprimer les options decodees
425 if (rmdecopt) udopt.push_back(opts);
426 }
427 }
428 // S'il faut supprimer les options decodees, on remplace l'argument opt
429 // par le vecteur des options non decodees.
430 if (rmdecopt) opt = udopt;
431 return(ndec+ndec1);
432}
[1975]433
[2524]434int PINTuple::OptionToString(vector<string> & opt) const
435{
436 PIDrawer::OptionToString(opt);
437
438 char str[256];
439
440 if(stats) opt.push_back("stat"); else opt.push_back("nstat");
441
[3149]442 sprintf(str,"statposoff=%lf,%lf",spoX,spoY); opt.push_back(str);
[2524]443
444 if(connectPts) opt.push_back("connectpoints");
445 else opt.push_back("noconnectpoints");
446
447 if(colorScale) opt.push_back("colorscale");
448 else opt.push_back("nocolorscale");
449
450 if(mrkSzScale) {
451 if(nWbins>0) {sprintf(str,"sizescale=%d",nWbins); opt.push_back(str);}
452 else opt.push_back("sizescale");
453 } else opt.push_back("nosizescale");
454
455 return 1;
456}
457
[1975]458/* La methode GetOptionsHelpInfo(string& info) renvoie une chaine
459 avec la description des options comprises par ce drawer
460 Note: Il est preferable de ne pas initialiser la chaine
461 string info au depart, afin de permettre de mettre bout a
462 bout les aides de differents Drawer */
463
464/* --Methode-- */
465void PINTuple::GetOptionsHelpInfo(string& info)
466{
[2229]467info += " ---- PINTuple options help info : \n" ;
[2350]468info += " sta,stat,stats: activate statistic display\n";
[2229]469info += " nsta,nstat,nostat,nostats: deactivate statistic display\n";
[2383]470info += " statposoff=OffsetX,OffsetY : Position offset for Stats drawing \n";
471info += " as a fraction of total size \n";
[2350]472info += " connectpoints: The points are connected by a line \n";
473info += " noconnectpoints (this is the default) \n";
[2373]474info += " colorscale/nocolorscale (Use color scale for weight) \n";
475info += " sizescale/sizescale=nbins/nosizescale (Use marker size for weight) \n";
[2383]476info += " (and usual color/line/marker/... attribute decoding) \n";
[2388]477// On recupere ensuite la chaine info de la classe de base
478PIDrawer::GetOptionsHelpInfo(info);
[2229]479return;
[1975]480}
[2373]481
482
[2517]483/* --Methode-- */
484double PINTuple::GetDistanceToPoint(double x, double y)
485{
486 if(!mNT) return 1.e+9;
487 if( xK<0 || yK<0 ) return 1.e+9;
[2373]488
[2517]489 const int nessai = 100;
490 long inc = (NptDraw>nessai) ? (long)(NptDraw/nessai)+1 : 1;
491
492 double dist = -1.e+18;
493 long n = 0;
494 for(long i=0; i<(long)mNT->NbLines(); i++) {
495 double xp=mNT->GetCell(i,xK);
496 if(xp<XMin() || xp>XMax()) continue;
497 double yp=mNT->GetCell(i,yK);
498 if(yp<YMin() || yp>YMax()) continue;
499 if(n%inc==0) {
500 xp = (xp-x)/(XMax()-XMin())/0.5;
501 yp = (yp-y)/(YMax()-YMin())/0.5;
502 xp = xp*xp+yp*yp;
503 if(dist<0. || xp<dist) dist = xp;
504 }
505 n++;
506 }
507 dist=sqrt(fabs(dist));
508 //cout<<"PINTuple: xlim="<<XMin()<<","<<XMax()<<" ylim="<<YMin()<<","<<YMax()
509 // <<" NbLines="<<mNT->NbLines()<<" inc="<<inc<<endl;
510 //cout<<"....d="<<dist<<" x="<<x<<" y="<<y<<" NptDraw="<<NptDraw<<endl;
511
512 return dist;
513}
Note: See TracBrowser for help on using the repository browser.