source: Sophya/trunk/SophyaLib/NTools/generaldata.cc@ 2506

Last change on this file since 2506 was 2506, checked in by ansari, 22 years ago

Remplacement THROW par throw - Reza 15/03/2004

File size: 32.1 KB
Line 
1#include "machdefs.h"
2#include <stdio.h>
3#include <stdlib.h>
4#include <iostream>
5#ifndef NO_VALUES_H
6#include <values.h>
7#endif
8#include <math.h>
9#include <string.h>
10#include <string>
11
12#include "strutil.h"
13#include "nbtri.h"
14#include "generalfit.h"
15#include "generaldata.h"
16#include "pexceptions.h"
17#include "objfio.h"
18
19//================================================================
20// GeneralFitData
21//================================================================
22
23/*!
24 \class SOPHYA::GeneralFitData
25 \ingroup NTools
26 Classe de stoquage de donnees a plusieurs variables avec erreur
27 sur l'ordonnee et sur les abscisses (options) :
28
29 \f$ {x0(i),Ex0(i), x1(i),Ex1(i), x2(i),Ex2(i) ... ; Y(i),EY(i)} \f$
30 \verbatim
31 Pour memoire, structure du rangement (n=mNVar):
32 - Valeur des abscisses mXP (idem pour mErrXP):
33 x0,x1,x2,...,xn x0,x1,x2,...,xn .... x0,x1,x2,....,xn
34 | 1er point | | 2sd point | .... | point mNData |
35 Donc abscisse J=[0,mNVar[ du point numero I=[0,mNData[: mXP[I*mNVar+J]
36 - Valeur de l'ordonnee mF (idem pour mErr et mOK):
37 f f f
38 | 1er point | | 2sd point | .... | point mNData |
39 Donc point numero I [0,mNData[ : mF[i]
40 \endverbatim
41*/
42
43//////////////////////////////////////////////////////////////////////
44/*!
45 Constructeur. ``nVar'' represente la dimension de l'espace des abscisses,
46 ``ndatalloc'' le nombre maximum de points et ``errx'' si non nul
47 indique que l'on fournit des erreurs sur les ``nVar'' variables en abscisse.
48*/
49GeneralFitData::GeneralFitData(unsigned int nVar, unsigned int ndatalloc, uint_2 errx)
50 : mNVar(0), mNDataAlloc(0), mNData(0), mNDataGood(0), mOk_EXP(0)
51 , mXP(NULL), mErrXP(NULL), mF(NULL), mErr(NULL), mOK(NULL)
52 , BuffVar(NULL), BuffVarR4(NULL)
53{
54try {
55 Alloc(nVar,ndatalloc,errx);
56} catch(PException e) {
57 cout << "Exception : " << typeid(e).name() << " " << e.Msg() << endl;
58 throw;
59}
60}
61
62/*!
63 Constructeur par copie. Si ``clean'' est ``true''
64 seules les donnees valides de ``data'' sont copiees.
65 Si ``clean'' est ``false'' (defaut) toutes les donnees
66 sont copiees et la taille totale de ``data'' est allouee
67 meme si elle est plus grande que la taille des donnees stoquees.
68*/
69GeneralFitData::GeneralFitData(const GeneralFitData& data, bool clean)
70 : mNVar(0), mNDataAlloc(0), mNData(0), mNDataGood(0), mOk_EXP(0)
71 , mXP(NULL), mErrXP(NULL), mF(NULL), mErr(NULL), mOK(NULL)
72 , BuffVar(NULL), BuffVarR4(NULL)
73{
74try {
75 Alloc(data.mNVar,((clean)?data.mNDataGood:data.mNDataAlloc),((data.mErrXP)?1:0));
76} catch(PException e) {
77 cout << "Exception : " << typeid(e).name() << " " << e.Msg() << endl;
78 throw;
79}
80
81 // Remplissage
82 if(data.mNData>0) {
83 r_8* ret;
84 for(int i=0;i<data.mNData;i++) {
85 if( clean && data.mOK[i]==0 ) continue;
86 ret = data.GetVec(i,NULL);
87 memcpy(mXP+mNData*mNVar,ret,mNVar*sizeof(r_8));
88 if(mErrXP) memcpy(mErrXP+mNData*mNVar,ret+mNVar,mNVar*sizeof(r_8));
89 mF[mNData] = ret[2*mNVar];
90 mErr[mNData] = ret[2*mNVar+1];
91 mOK[mNData] = (uint_2) (ret[2*mNVar+2]+0.001);
92 if(mOK[mNData]!=0) mNDataGood++;
93 mNData++;
94 }
95 }
96
97}
98
99/*!
100 Constructeur par defaut.
101*/
102GeneralFitData::GeneralFitData()
103 : mNVar(0), mNDataAlloc(0), mNData(0), mNDataGood(0), mOk_EXP(0)
104 , mXP(NULL), mErrXP(NULL), mF(NULL), mErr(NULL), mOK(NULL)
105 , BuffVar(NULL), BuffVarR4(NULL)
106{
107}
108
109/*!
110 Destructeur
111*/
112GeneralFitData::~GeneralFitData()
113{
114 Delete();
115}
116
117//////////////////////////////////////////////////////////////////////
118/*!
119 Pour redefinir la structure de donnees (ou la creer si on a utilise
120 le createur par defaut). Voir les explications des arguments
121 dans les commentaires du constructeur. Si ``errx''\<0 alors
122 la valeur prise est celle definie auparavent.
123*/
124void GeneralFitData::Alloc(unsigned int nVar, unsigned int ndatalloc, int_2 errx)
125{
126ASSERT( nVar>0 && ndatalloc>0 );
127
128Delete();
129
130if(errx>=0) mOk_EXP = (uint_2) errx;
131mNVar = nVar;
132mNDataAlloc = ndatalloc;
133
134try {
135 mXP = new r_8[nVar*ndatalloc];
136 if(mOk_EXP) mErrXP = new r_8[nVar*ndatalloc];
137 mF = new r_8[ndatalloc];
138 mErr = new r_8[ndatalloc];
139 mOK = new uint_2[ndatalloc];
140 BuffVar = new r_8[2*nVar+3];
141 BuffVarR4 = (r_4 *) BuffVar;
142} catch(PException e) {
143 throw(AllocationError("GeneralFitData::Alloc allocation error\n"));
144}
145}
146
147//////////////////////////////////////////////////////////////////////
148/*!
149 Gestion des des-allocations
150*/
151void GeneralFitData::Delete()
152{
153mNVar = mNDataAlloc = mNData = mNDataGood = 0;
154if( mXP != NULL ) {delete [] mXP; mXP = NULL;}
155if( mErrXP != NULL ) {delete [] mErrXP; mErrXP = NULL;}
156if( mF != NULL ) {delete [] mF; mF = NULL;}
157if( mErr != NULL ) {delete [] mErr; mErr = NULL;}
158if( mOK != NULL ) {delete [] mOK; mOK = NULL;}
159if( BuffVar != NULL ) {delete [] BuffVar; BuffVar = NULL; BuffVarR4 = NULL;}
160}
161
162//////////////////////////////////////////////////////////////////////
163/*!
164 Remise a zero de la structure pour nouveau remplissage (pas d'arg)
165 ou remise a la position ``ptr'' (si arg). Les donnees apres ``ptr''
166 sont sur-ecrites.
167*/
168void GeneralFitData::SetDataPtr(int ptr)
169{
170 ASSERT(ptr >= 0 && ptr < mNDataAlloc);
171 mNData = ptr;
172 mNDataGood = 0;
173 if(ptr==0) return;
174 for(int i=0;i<mNData;i++) if(mOK[i]) mNDataGood++;
175}
176
177//////////////////////////////////////////////////////////////////////
178/*!
179 Pour tuer un point
180*/
181void GeneralFitData::KillData(int i)
182{
183 ASSERT(i >= 0 && i < mNData);
184
185 if( ! mOK[i] ) return;
186 mOK[i] = 0;
187 mNDataGood--;
188}
189
190/*!
191 Pour tuer une serie de points
192*/
193void GeneralFitData::KillData(int i1,int i2)
194{
195 ASSERT(i1 >= 0 && i1 < mNData);
196 ASSERT(i2 >= 0 && i2 < mNData);
197 ASSERT(i1 <= i2 );
198
199 for(int i=i1;i<=i2;i++) KillData(i);
200}
201
202//////////////////////////////////////////////////////////////////////
203/*!
204 Pour re-valider le point numero i ([0,NData]).
205*/
206void GeneralFitData::ValidData(int i)
207{
208 ASSERT(i >= 0 && i < mNData);
209
210 if( mOK[i] ) return;
211 if( mErr[i]<=0. ) return;
212 if(mOk_EXP) {
213 for(int j=0;j<mNVar;j++) if(mErrXP[i*mNVar+j]<=0.) return;
214 }
215 mOK[i] = 1;
216 mNDataGood++;
217}
218
219/*!
220 Pour re-valider les points numeros i1 a i2.
221*/
222void GeneralFitData::ValidData(int i1,int i2)
223{
224 ASSERT(i1 >= 0 && i1 < mNData);
225 ASSERT(i2 >= 0 && i2 < mNData);
226 ASSERT(i1 <= i2 );
227
228 for(int i=i1;i<=i2;i++) ValidData(i);
229}
230
231/*!
232 Pour re-valider tous les points.
233*/
234void GeneralFitData::ValidData()
235{
236 for(int i=0;i<mNData;i++) ValidData(i);
237}
238
239//////////////////////////////////////////////////////////////////////
240/*!
241 Pour redefinir un point a \f$ {x,[errx] ; f,err} \f$
242*/
243void GeneralFitData::RedefineData1(int i,double x,double f,double err,double errx)
244{
245 RedefineData(i,&x,f,err,&errx);
246}
247
248/*!
249 Pour redefinir un point a \f$ {x,[errx], y,[erry] ; f,err} \f$
250*/
251void GeneralFitData::RedefineData2(int i,double x,double y,double f
252 ,double err,double errx,double erry)
253{
254 double xp[2] = {x,y};
255 double errxp[2] = {errx,erry};
256 RedefineData(i,xp,f,err,errxp);
257}
258
259/*!
260 Pour redefinir un point a
261 \f$ {xp[0],[errxp[0]], xp[1],[errxp[1]], xp[2],[errxp[2]],... ; f,err} \f$
262*/
263void GeneralFitData::RedefineData(int i,double* xp,double f,double err,double* errxp)
264{
265 ASSERT(i>=0 && i<mNData);
266 bool ok = true;
267
268 int ip = mNVar*i;
269 for(int j=0;j<mNVar;j++) mXP[ip+j] = xp[j];
270 if(mOk_EXP) {
271 if(errxp) {
272 for(int j=0;j<mNVar;j++)
273 {mErrXP[ip+j] = errxp[j]; if(errxp[j]<=0.) ok=false;}
274 } else {
275 for(int j=0;j<mNVar;j++) mErrXP[ip+j] = Def_ErrX;
276 ok=false;
277 }
278 }
279 mF[i] = f;
280 mErr[i] = err; if(err<=0.) ok = false;
281 if(ok) {
282 if(! mOK[i]) {mOK[i]=1; mNDataGood++;}
283 } else {
284 if( mOK[i]) {mOK[i]=0; mNDataGood--;}
285 }
286}
287
288//////////////////////////////////////////////////////////////////////
289/*!
290 Pour ajouter un point \f$ {x,[errx] ; f,err} \f$
291*/
292void GeneralFitData::AddData1(double x, double f, double err, double errx)
293{
294 AddData(&x,f,err,&errx);
295}
296
297/*!
298 Pour ajouter un point \f$ {x,[errx], y,[erry] ; f,err} \f$
299*/
300void GeneralFitData::AddData2(double x, double y, double f
301 , double err, double errx, double erry)
302{
303 double xp[2] = {x,y};
304 double errxp[2] = {errx,erry};
305 AddData(xp,f,err,errxp);
306}
307
308/*!
309 Pour ajouter un point
310 \f$ {xp[0],[errxp[0]], xp[1],[errxp[1]], xp[2],[errxp[2]],... ; f,err} \f$
311*/
312void GeneralFitData::AddData(double* xp, double f, double err,double* errxp)
313{
314 ASSERT(mNData < mNDataAlloc);
315 bool ok = true;
316
317 int ip = mNVar*mNData;
318 for(int i=0;i<mNVar;i++) mXP[ip+i] = xp[i];
319 if(mOk_EXP) {
320 if(errxp) {
321 for(int j=0;j<mNVar;j++)
322 {mErrXP[ip+j] = errxp[j]; if(errxp[j]<=0.) ok=false;}
323 } else {
324 for(int j=0;j<mNVar;j++) mErrXP[ip+j] = Def_ErrX;
325 ok=false;
326 }
327 }
328 mF[mNData] = f;
329 mErr[mNData] = err;
330 if(err<=0.) ok = false;
331 if(ok) { mOK[mNData]=1; mNDataGood++; } else mOK[mNData]=0;
332 mNData++;
333}
334
335/*!
336 Pour ajouter un point
337 \f$ {xp[0],[errxp[0]], xp[1],[errxp[1]], xp[2],[errxp[2]],... ; f,err} \f$
338*/
339void GeneralFitData::AddData(float* xp, float f, float err, float* errxp)
340{
341 {for(int i=0;i<mNVar;i++) BuffVar[i] = (double) xp[i];}
342 if(errxp) for(int i=0;i<mNVar;i++) BuffVar[mNVar+i] = (double) errxp[i];
343 AddData(BuffVar,(double) f,(double) err,BuffVar+mNVar);
344}
345
346//////////////////////////////////////////////////////////////////////
347/*!
348 Pour remplir la structure de donnees d'un seul coup avec
349 \f$ {x(i),[errx(i)] ; f(i),err(i)} \f$
350*/
351void GeneralFitData::SetData1(int nData
352 , double* x, double* f, double *err, double *errx)
353{
354 ASSERT(nData>0 && mNData+nData<=mNDataAlloc);
355
356 for(int i=0;i<nData;i++) {
357 double ex = (errx) ? errx[i]: Def_ErrX;
358 double ef = (err ) ? err[i]: Def_ErrF;
359 AddData1(x[i],f[i],ef,ex);
360 }
361}
362
363/*!
364 Pour remplir la structure de donnees d'un seul coup avec
365 \f$ {x(i),[errx(i)] ; f(i),err(i)} \f$
366*/
367void GeneralFitData::SetData1(int nData
368 , float* x, float* f, float* err, float *errx)
369{
370 ASSERT(nData>0 && mNData+nData<=mNDataAlloc);
371
372 for(int i=0;i<nData;i++) {
373 double ex = (errx) ? (double) errx[i]: Def_ErrX;
374 double ef = (err ) ? (double) err[i]: Def_ErrF;
375 AddData1((double) x[i],(double) f[i],ef,ex);
376 }
377}
378
379/*!
380 Pour remplir la structure de donnees d'un seul coup avec
381 \f$ {x(i),[errx(i)], y(i),[erry(i)], ; f(i),err(i)} \f$
382*/
383void GeneralFitData::SetData2(int nData, double* x, double* y, double* f
384 ,double *err,double *errx,double *erry)
385{
386 ASSERT(nData>0 && mNData+nData<=mNDataAlloc);
387
388 for(int i=0;i<nData;i++) {
389 double ex = (errx) ? (double) errx[i]: Def_ErrX;
390 double ey = (erry) ? (double) erry[i]: Def_ErrX;
391 double ef = (err ) ? (double) err[i]: Def_ErrF;
392 AddData2(x[i],y[i],f[i],ef,ex,ey);
393 }
394}
395
396/*!
397 Pour remplir la structure de donnees d'un seul coup avec
398 \f$ {x(i),[errx(i)], y(i),[erry(i)], ; f(i),err(i)} \f$
399*/
400void GeneralFitData::SetData2(int nData, float* x, float* y, float* f
401 ,float *err,float *errx,float *erry)
402{
403 ASSERT(nData>0 && mNData+nData<=mNDataAlloc);
404
405 for(int i=0;i<nData;i++) {
406 double ex = (errx) ? (double) errx[i]: Def_ErrX;
407 double ey = (erry) ? (double) erry[i]: Def_ErrX;
408 double ef = (err ) ? (double) err[i]: Def_ErrF;
409 AddData2((double) x[i],(double) y[i],(double) f[i],ef,ex,ey);
410 }
411}
412
413/*!
414 Pour remplir la structure de donnees d'un seul coup avec
415 \f$ {X0(i),[EX0(i)], X1(i),[EX1(i)], X2(i),[EX2(i)], ... ; F(i),Err(i)} \f$
416
417 Attention: si la structure est n'est pas vide, les tableaux sont copies
418 apres les donnees pre-existantes (qui ne sont donc pas detruites). Pour
419 effacer les donnees pre-existantes utiliser SetDataPtr(0).
420 \verbatim
421 Ici **xp est un pointeur sur un tableau de pointeurs tq
422 xp[0] = &X0[0], xp[1] = &X1[0], xp[2] = &X2[0] ...
423 ou X0,X1,X2,... sont les tableaux X0[nData] X1[nData] X2[nData] ...
424 des variables (meme commentaire pour errxp).
425 \endverbatim
426*/
427void GeneralFitData::SetData(int nData,double** xp, double *f
428 , double *err, double** errxp)
429{
430 ASSERT(nData>0 && mNData+nData<=mNDataAlloc);
431 if(mOk_EXP && !errxp) {for(int j=0;j<mNVar;j++) BuffVar[mNVar+j] = Def_ErrX;}
432
433 for(int i=0;i<nData;i++) {
434 {for(int j=0;j<mNVar;j++) BuffVar[j] = *(xp[j]+i);}
435 if(mOk_EXP && errxp)
436 {for(int j=0;j<mNVar;j++) BuffVar[mNVar+j] = *(errxp[j]+i);}
437 double ef = (err) ? err[i]: Def_ErrF;
438 AddData(BuffVar,f[i],ef,BuffVar+mNVar);
439 }
440}
441
442/*!
443 Voir commentaire ci-dessus.
444*/
445void GeneralFitData::SetData(int nData,float** xp, float *f
446 , float *err, float** errxp)
447{
448 ASSERT(nData>0 && mNData+nData<=mNDataAlloc);
449
450 if(mOk_EXP && !errxp) {for(int j=0;j<mNVar;j++) BuffVar[mNVar+j] = Def_ErrX;}
451
452 for(int i=0;i<nData;i++) {
453 {for(int j=0;j<mNVar;j++) BuffVar[j] = (double) *(xp[j]+i);}
454 if(mOk_EXP && errxp)
455 {for(int j=0;j<mNVar;j++) BuffVar[mNVar+j] = (double) *(errxp[j]+i);}
456 double ef = (err) ? err[i]: Def_ErrF;
457 AddData(BuffVar,(double) f[i],ef,BuffVar+mNVar);
458 }
459}
460
461//////////////////////////////////////////////////////////////////////
462/*!
463 Impression de l'etat de la structure de donnees
464*/
465void GeneralFitData::PrintStatus() const
466{
467 cout<<"GeneralFitData:: "<<endl
468 <<"NVar="<<mNVar<<" NDataAlloc="<<mNDataAlloc<<" Ok_EXP="<<mOk_EXP
469 <<" ,NData="<<mNData<<" NDataGood="<<mNDataGood<<endl
470 <<" mXP="<<mXP<<" [mErrXP="<<mErrXP<<"] mF="<<mF<<" mErr="<<mErr
471 <<" mOK="<<mOK<<endl;
472}
473
474/*!
475 Impression du point i
476*/
477void GeneralFitData::PrintData(int i) const
478{
479 ASSERT(i>=0 && i<mNData);
480
481 cout<<" "<<i<<" F( ";
482 {for(int j=0;j<mNVar;j++) cout<<" "<<Absc(j,i);}
483 if(mOk_EXP) {
484 cout<<" ; ";
485 for(int j=0;j<mNVar;j++) cout<<" "<<EAbsc(j,i);
486 }
487 cout<<")= "<<Val(i)<<" "<<EVal(i)<<" ("<<IsValid(i)<<")\n";
488}
489
490/*!
491 Impression des points i1 a i2
492*/
493void GeneralFitData::PrintData(int i1,int i2) const
494{
495 if(i1<0) i1=0;
496 if(i1>=mNData) i1 = mNData-1;
497 if(i2>=mNData) i2 = mNData-1;
498 if(i1>i2) i2 = mNData-1;
499
500 cout<<"GeneralFitData::PrintData[NData="
501 <<mNData<<"/ NDataGood="<<mNDataGood<<"]"<<endl;
502 for(int i=i1;i<=i2;i++) PrintData(i);
503 cout<<flush;
504}
505
506/*!
507 Impression de tous les points
508*/
509void GeneralFitData::PrintData() const
510{
511 ASSERT(mNData>0);
512
513 PrintData(0,mNData-1);
514}
515
516/*!
517 Impression de l'etat de la structure de donnees avec bornes sur "s"
518*/
519void GeneralFitData::Show(ostream& os) const
520{
521double min,max;
522os<<"GeneralFitData:: NVar,ErrX="<<mNVar<<","<<mOk_EXP
523 <<" Data: "<<mNData<<" Good,Alloc="<<mNDataGood<<","<<mNDataAlloc<<endl;
524for(int k=0;k<2*NVar()+3;k++) {
525 GetMinMax(k,min,max);
526 os<<" - "<<k<<" "<<ColumnName(k)<<" , "<<min<<","<<max<<endl;
527}
528return;
529}
530
531//////////////////////////////////////////////////////////////////////
532/*!
533 Retourne les numeros des points de valeurs minimum et maximum
534 de la variable ``var'':
535 \verbatim
536 La variable "var" est de la forme : var = AB avec
537 B = 0 : variable d'ordonnee Y (valeur de A indifferente)
538 B = 1 : erreur variable d'ordonnee EY (valeur de A indifferente)
539 B = 2 : variable d'abscisse X numero A #[0,NVar[
540 B = 3 : erreur variable d'abscisse EX numero A #[0,NVar[
541 - Return NData checked si ok, -1 si probleme.
542 \endverbatim
543*/
544int GeneralFitData::GetMnMx(int var,int& imin,int& imax) const
545{
546imin = imax = -1;
547int ix = var/10;
548var = var%10;
549if(var<0 || var>3) return -1;
550if(var>=2 && (ix<0 || ix>=mNVar) ) return -1;
551double min=1., max=-1.;
552int ntest = 0;
553for(int i=0;i<mNData;i++) {
554 if( ! IsValid(i) ) continue;
555 double v;
556 if(var==1) v = EVal(i);
557 else if(var==2) v = Absc(ix,i);
558 else if(var==3) v = EAbsc(ix,i);
559 else v = Val(i);
560 if(ntest==0) {min = max = v; imin = imax = i;}
561 if(v<min) {min = v; imin = i;}
562 if(v>max) {max = v; imax = i;}
563 ntest++;
564}
565return ntest;
566}
567
568/*!
569 Retourne le minimum et le maximum de la variable ``var''
570 (cf commentaires GetMnMx).
571*/
572int GeneralFitData::GetMnMx(int var,double& min,double& max) const
573{
574min = 1.; max = -1.;
575int imin,imax;
576int ntest = GetMnMx(var,imin,imax);
577if(ntest<=0) return ntest;
578int ix = var/10;
579var = var%10;
580if(var==0) {
581 if(imin>=0) min = Val(imin);
582 if(imax>=0) max = Val(imax);
583} else if(var==1) {
584 if(imin>=0) min = EVal(imin);
585 if(imax>=0) max = EVal(imax);
586} else if(var==2) {
587 if(imin>=0) min = Absc(ix,imin);
588 if(imax>=0) max = Absc(ix,imax);
589} else if(var==3) {
590 if(imin>=0) min = EAbsc(ix,imin);
591 if(imax>=0) max = EAbsc(ix,imax);
592}
593return ntest;
594}
595
596//////////////////////////////////////////////////////////////////////
597/*!
598//
599 Retourne la moyenne et le sigma de la variable ``var''
600 (cf commentaires GetMnMx).
601 \verbatim
602 - Return : nombre de donnees utilisees, -1 si pb, -2 si sigma<0.
603 - Seuls les points valides de valeur entre min,max sont utilises.
604 Si min>=max pas de coupures sur les valeurs.
605 \endverbatim
606*/
607int GeneralFitData::GetMeanSigma(int var,double& mean,double& sigma,double min,double max) const
608{
609mean = sigma = 0.;
610int ix = var/10;
611var = var%10;
612if(var<0 || var>3) return -1;
613if(var>=2 && (ix<0 || ix>=mNVar) ) return -1;
614int ntest = 0;
615for(int i=0;i<mNData;i++) {
616 if( ! IsValid(i) ) continue;
617 double v;
618 if(var==1) v = EVal(i);
619 else if(var==2) v = Absc(ix,i);
620 else if(var==3) v = EAbsc(ix,i);
621 else v = Val(i);
622 if(min<max && (v<min || max<v)) continue;
623 mean += v;
624 sigma += v*v;
625 ntest++;
626}
627if(ntest==0) {
628 mean = sigma = 0.;
629} else {
630 mean /= (double)ntest;
631 sigma = sigma/(double)ntest - mean*mean;
632 if(sigma<0.) ntest = -2;
633 else if(sigma>0.) sigma = sqrt(sigma);
634}
635return ntest;
636}
637
638/*!
639 Retourne le mode de la variable ``var''
640 (cf commentaires GetMnMx).
641 \verbatim
642 - Return : nombre de donnees utilisees, -1 si pb.
643 - Seuls les points valides de valeur entre min,max sont utilises.
644 Si min>=max pas de coupures sur les valeurs.
645 - Le calcul du mode est approximee par la formule:
646 Mode = Median - coeff*(Mean-Median) (def: coeff=0.8)
647 - Kendall and Stuart donne coeff=2., mais coeff peut etre regle.
648 \endverbatim
649*/
650int GeneralFitData::GetMoMeMed(int var,double& mode,double& mean,double& median,
651 double min,double max,double coeff) const
652{
653mode = mean = median = 0.;
654if(mNData<=0) return -1;
655int ix = var/10;
656var = var%10;
657if(var<0 || var>3) return -1;
658if(var>=2 && (ix<0 || ix>=mNVar) ) return -1;
659double* buff = new double[mNData];
660int ntest = 0;
661for(int i=0;i<mNData;i++) {
662 if( ! IsValid(i) ) continue;
663 double v;
664 if(var==1) v = EVal(i);
665 else if(var==2) v = Absc(ix,i);
666 else if(var==3) v = EAbsc(ix,i);
667 else v = Val(i);
668 if(min<max && (v<min || max<v)) continue;
669 buff[ntest] = v;
670 mean += v;
671 ntest++;
672}
673if(ntest==0) {
674 mean = 0.;
675} else {
676 mean /= (double)ntest;
677 qsort(buff,(size_t) ntest,sizeof(double),qSort_Dble);
678 int im;
679 if(ntest%2==1) {
680 // nombre impair de points
681 im = ntest/2;
682 median = buff[im];
683 } else {
684 // nombre pair de points
685 im = (ntest-1)/2;
686 median = (buff[im]+buff[im+1])/2.;
687 }
688 mode = median - coeff*(mean-median);
689}
690delete [] buff;
691return ntest;
692}
693
694/*!
695 Cf description ci-dessus ``GetMoMeMed''.
696*/
697int GeneralFitData::GetMode(int var,double& mode,double min,double max,double coeff) const
698{
699double mean,median;
700return GetMoMeMed(var,mode,mean,median,min,max,coeff);
701}
702
703//////////////////////////////////////////////////////////////////////
704/*!
705 Pour fiter un polynome de degre ``degre''. On fite
706 Y=f(X-xc) ou Y=Val et X=Absc(varx). Si ``ey'' est ``true''
707 le fit prend en compte les erreurs stoquees dans EVal,
708 sinon fit sans erreurs. Le resultat du fit est retourne
709 dans le polynome ``pol''. On re-centre les abscisses X de ``xc''.
710 \verbatim
711 Return:
712 - Res = le residu du fit
713 - -1 si degre<0
714 - -2 si probleme sur numero de variable X
715 - -4 si NDataGood<0
716 - -5 si nombre de data trouves differents de NDataGood
717 \endverbatim
718*/
719double GeneralFitData::PolFit(int varx,Poly& pol,int degre,bool ey,double xc) const
720{
721if(degre<0) return -1.;
722if(varx<0 || varx>=mNVar) return -2.;
723if(mNDataGood<=0) return -4.;
724TVector<r_8> x(mNDataGood);
725TVector<r_8> y(mNDataGood);
726TVector<r_8> ey2(1);
727if(ey) ey2.Realloc(mNDataGood,true);
728int ntest = 0;
729for(int i=0;i<mNData;i++) {
730 if( ! IsValid(i) ) continue;
731 if(ntest>=mNDataGood) return -5.;
732 x(ntest) = Absc(varx,i) - xc;
733 y(ntest) = Val(i);
734 if(ey) ey2(ntest) = EVal(i)*EVal(i);
735 ntest++;
736}
737double res = 0.;
738if(ey) {
739 TVector<r_8> errcoef(1);
740 res = pol.Fit(x,y,ey2,degre,errcoef);
741} else {
742 res = pol.Fit(x,y,degre);
743}
744return res;
745}
746
747/*!
748 Pour fiter un polynome de degre ``degre1''. On fite
749 Z=f(X-xc,Y-yc) ou Z=Val et X=Absc(varx) et Y=Absc(vary).
750 Si ``ey'' est ``true'' le fit prend en compte les erreurs
751 stoquees dans EVal, sinon fit sans erreurs. Si ``degre2''
752 negatif, le fit determine un polynome en X,Y de degre
753 total ``degre`''. Si ``degre2'' positif ou nul, le fit
754 demande un fit de ``degre1'' pour la variable X et de degre
755 ``degre2'' sur la variable Y. Le resultat du fit est retourne
756 dans le polynome ``pol''. On re-centre les abscisses X de ``xc''
757 et Y de ``yc''.
758 \verbatim
759 Return:
760 - Res = le residu du fit
761 - -1 si degre<0
762 - -2 si probleme sur numero de variable X
763 - -3 si probleme sur numero de variable Y
764 - -4 si NDataGood<0
765 - -5 si nombre de data trouves different de NDataGood
766 \endverbatim
767*/
768double GeneralFitData::PolFit(int varx,int vary,Poly2& pol,int degre1,int degre2,bool ez
769 ,double xc,double yc) const
770{
771if(degre1<0) return -1.;
772if(varx<0 || varx>=mNVar) return -2.;
773if(vary<0 || vary>=mNVar || vary==varx) return -3.;
774if(mNDataGood<=0) return -4.;
775TVector<r_8> x(mNDataGood);
776TVector<r_8> y(mNDataGood);
777TVector<r_8> z(mNDataGood);
778TVector<r_8> ez2(1);
779if(ez) ez2.Realloc(mNDataGood,true);
780int ntest = 0;
781for(int i=0;i<mNData;i++) {
782 if( ! IsValid(i) ) continue;
783 if(ntest>=mNDataGood) return -5.;
784 x(ntest) = Absc(varx,i) - xc;
785 y(ntest) = Absc(vary,i) - yc;
786 z(ntest) = Val(i);
787 if(ez) ez2(ntest) = EVal(i)*EVal(i);
788 ntest++;
789}
790double res = 0.;
791if(ez) {
792 TVector<r_8> errcoef(1);
793 if(degre2>0) res = pol.Fit(x,y,z,ez2,degre1,degre2,errcoef);
794 else res = pol.Fit(x,y,z,ez2,degre1,errcoef);
795} else {
796 if(degre2>0) res = pol.Fit(x,y,z,degre1,degre2);
797 else res = pol.Fit(x,y,z,degre1);
798}
799return res;
800}
801
802//////////////////////////////////////////////////////////////////////
803/*!
804 Retourne une classe contenant les residus du fit ``gfit''.
805*/
806GeneralFitData GeneralFitData::FitResidus(GeneralFit& gfit) const
807{
808if(gfit.GetNVar()!=mNVar)
809 throw(SzMismatchError("GeneralFitData::FitResidus: size mismatch\n"));
810return gfit.DataResidus(true);
811}
812
813/*!
814 Retourne une classe contenant la function du fit ``gfit''.
815*/
816GeneralFitData GeneralFitData::FitFunction(GeneralFit& gfit) const
817{
818if(gfit.GetNVar()!=mNVar)
819 throw(SzMismatchError("GeneralFitData::FitFunction: size mismatch\n"));
820return gfit.DataFunction(true);
821}
822
823//////////////////////////////////////////////////////////////////////
824/*!
825//
826 Retourne la donnee `n' dans le vecteur de double `ret'.
827 \verbatim
828 Par defaut, ret=NULL et le buffer interne de la classe est retourne
829 - Les donnees sont rangees dans l'ordre:
830 x0,x1,x2,... ; ex0,ex1,ex2,... ; y ; ey ; ok(0/1)
831 |<- NVar ->| + |<- NVar ->| + 1 + 1 + 1
832 Le vecteur ret a la taille 2*NVar+2+1
833 \endverbatim
834*/
835r_8* GeneralFitData::GetVec(int n, r_8* ret) const
836{
837int i;
838if (ret == NULL) ret = BuffVar;
839for(i=0; i<2*mNVar+3; i++) ret[i] = 0.;
840if (n >= mNData) return(ret);
841
842memcpy(ret, mXP+n*mNVar, mNVar*sizeof(r_8));
843if(mErrXP) memcpy(ret+mNVar, mErrXP+n*mNVar, mNVar*sizeof(r_8));
844ret[2*mNVar] = mF[n];
845ret[2*mNVar+1] = mErr[n];
846ret[2*mNVar+2] = (double) mOK[n];
847return(ret);
848}
849
850/*!
851 Retourne la donnee `n' dans le vecteur de float `ret'
852 (meme commentaires que pour GetVec).
853*/
854r_4* GeneralFitData::GetVecR4(int n, r_4* ret) const
855{
856if (ret == NULL) ret = BuffVarR4;
857double *buff = new double[2*mNVar+3];
858GetVec(n,buff);
859for(int i=0;i<2*mNVar+3;i++) ret[i] = (float) buff[i];
860delete [] buff;
861return ret;
862}
863
864//////////////////////////////////////////////////////////////////////
865// ------- Implementation de l interface NTuple ---------
866
867/*!
868 Retourne le nombre de ligne = NData() (pour interface NTuple)
869*/
870uint_4 GeneralFitData::NbLines() const
871{
872return(NData());
873}
874
875/*!
876 Retourne le nombre de colonnes du ntuple equivalent:
877 \verbatim
878 Exemple: on a une fonction sur un espace a 4 dimensions:
879 "x0,x1,x2,x3 , ex0,ex1,ex2,ex3 , y, ey , ok"
880 0 1 2 3 4 5 6 7 8 9 10
881 | | | | | | |
882 0 nv-1 nv 2*nv-1 2*nv 2*nv+1 2*nv+2
883 soit 2*nvar+3 variables/colonnes.
884 \endverbatim
885 (pour interface NTuple)
886*/
887uint_4 GeneralFitData::NbColumns() const
888{
889return(2*NVar()+3);
890}
891
892//! Pour interface NTuple
893r_8 * GeneralFitData::GetLineD(int n) const
894{
895return(GetVec(n,NULL));
896}
897
898//! Pour interface NTuple
899r_8 GeneralFitData::GetCell(int n, int k) const
900{
901if(k<0 || k>=2*NVar()+3) return 0.;
902r_8 * val = GetVec(n,NULL);
903return val[k];
904}
905
906//! Pour interface NTuple
907r_8 GeneralFitData::GetCell(int n, string const & nom) const
908{
909int k = ColumnIndex(nom);
910return(GetCell(n,k));
911}
912
913/*!
914 Retourne le minimum et le maximum de la variable `k' (pour interface NTuple).
915*/
916void GeneralFitData::GetMinMax(int k, double& min, double& max) const
917{
918int var;
919if(k<0 || k>=2*NVar()+3) return;
920else if(k<NVar()) var = 10*k+2; // Variable Xi
921else if(k<2*NVar()) var = 10*(k-NVar())+3; // Variable EXi
922else if(k==2*NVar()) var = 0; // Variable Y
923else if(k==2*NVar()+1) var = 1; // Variable EY
924else {min=0.; max=1.; return;} // Variable Ok
925GetMnMx(var,min,max);
926return;
927}
928
929//! Pour interface NTuple
930void GeneralFitData::GetMinMax(string const & nom, double& min, double& max) const
931{
932int k = ColumnIndex(nom);
933GetMinMax(k,min,max);
934}
935
936//! Pour interface NTuple
937int GeneralFitData::ColumnIndex(string const & nom) const
938{
939char str[64]; int k = -1;
940strcpy(str,nom.c_str()); strip(str,'L',' ');
941if(str[0]=='y') return 2*NVar();
942if(str[0]=='o') return 2*NVar()+2;
943if(str[0]=='x') {sscanf(str,"x%d",&k); return k;}
944if(str[0]=='e')
945 if(str[1]=='y') return 2*NVar()+1;
946 else if(str[1]=='x') {sscanf(str,"ex%d",&k); return NVar()+k;}
947return -1;
948}
949
950//! Pour interface NTuple
951string GeneralFitData::ColumnName(int k) const
952{
953if(k==2*NVar()) return string("y");
954else if(k==2*NVar()+1) return string("ey");
955else if(k==2*NVar()+2) return string("ok");
956else if(k<0 || k>=2*NVar()+3) return string("");
957
958char str[64] = "";
959if(k<NVar()) sprintf(str,"x%d",k);
960else if(k<2*NVar()) sprintf(str,"ex%d",k-NVar());
961return string(str);
962}
963
964/*!
965 Retourne une chaine de caracteres avec la declaration des noms de
966 variables. si "nomx!=NULL" , des instructions d'affectation
967 a partir d'un tableau "nomx[i]" sont ajoutees (pour interface NTuple).
968*/
969string GeneralFitData::VarList_C(const char* nomx) const
970{
971char buff[256];
972string rets;
973int i;
974rets = "\ndouble";
975for(i=0; i<mNVar; i++) {
976 sprintf(buff," x%d, ex%d",i,i);
977 rets += buff;
978 if(i!=mNVar-1) rets += ","; else rets += ";\n";
979}
980sprintf(buff,"\ndouble y, ey, ok;\n");
981rets += buff;
982if (nomx) {
983 for(i=0; i<mNVar; i++) {
984 sprintf(buff,"x%d=%s[%d];\n", i, nomx, i);
985 rets += buff;
986 }
987 for(i=0; i<mNVar; i++) {
988 sprintf(buff,"ex%d=%s[%d];\n", i, nomx, mNVar+i);
989 rets += buff;
990 }
991 sprintf(buff,"y=%s[%d];\ney=%s[%d];\nok=%s[%d];\n"
992 ,nomx,2*mNVar,nomx,2*mNVar+1,nomx,2*mNVar+2);
993 rets += buff;
994}
995
996return(rets);
997}
998
999
1000//! Compute errors according to specifications
1001/*!
1002 \param val : value of the function
1003 \param err : value of the default error
1004 \param errtype : type of error according to enum FitErrType (def=DefaultError)
1005 \param errscale : scaling (or value) of the error (def=1.)
1006 \param errmin : minimum value of the error (def=0.)
1007 \param nozero : if true, do not return negative errors but
1008 set them to zero (def=false)
1009 \return : return the error computed according to specifications
1010 \verbatim
1011 - val is the value to be fitted ex: val = f(x,y,...)
1012 - err is the error by default we want to set.
1013 - errtype = DefaultError : errtmp = errscale*err
1014 errtype = ConstantError : errtmp = errscale
1015 errtype = SqrtError : errtmp = errscale*sqrt(|val|)
1016 errtype = ProporError : errtmp = errscale*|val|
1017 - errscale <=0 then errscale=1
1018 - errmin >=0 if errtmp>0 return max(errtmp,errmin)
1019 if errtmp<=0 return errtmp
1020 errmin <0 if errtmp>0 return max(errtmp,|errmin|)
1021 if errtmp<=0 return |errmin|
1022 \endverbatim
1023 */
1024double GeneralFitData::ComputeError(double val,double err,FitErrType errtype
1025 ,double errscale,double errmin,bool nozero)
1026{
1027 bool errminneg=false;
1028 if(errmin<0.) {errminneg=true; errmin*=-1.;}
1029 if(errscale<0.) errscale=1.;
1030
1031 // Choix du type d'erreur
1032 if(errtype==ConstantError) err = errscale;
1033 else if(errtype==SqrtError) err = errscale*sqrt(fabs(val));
1034 else if(errtype==ProporError) err = errscale*fabs(val);
1035
1036 // Gestion du minimum a partir de la valeur calculee precedemment "err"
1037 // Ex1: errmin=1., err=10. ==> 10.
1038 // err=0.5 ==> 1.
1039 // err=0. ==> 0.
1040 // err=-2. ==> -2.
1041 // Ex2: errmin=-1., err=10. ==> 10.
1042 // err=0.5 ==> 1.
1043 // err=0. ==> 1.
1044 // err=-2. ==> 11.
1045 if(err>0.) err = (err>errmin) ? err: errmin;
1046 else if(errminneg) err = errmin;
1047
1048 // ne pas retourner d'erreurs negatives si demande
1049 if(nozero && err<0.) err=0.;
1050
1051 return err;
1052}
1053
1054///////////////////////////////////////////////////////////
1055// --------------------------------------------------------
1056// Les objets delegues pour la gestion de persistance
1057// --------------------------------------------------------
1058///////////////////////////////////////////////////////////
1059
1060
1061DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
1062void ObjFileIO<GeneralFitData>::ReadSelf(PInPersist& is)
1063{
1064char strg[256];
1065
1066if(dobj==NULL) dobj=new GeneralFitData;
1067 else dobj->Delete();
1068
1069// Lecture entete
1070is.GetLine(strg, 255);
1071
1072// Ecriture des valeurs de definitions
1073int_4 nvar,ndatalloc,ndata,ndatagood;
1074is.Get(nvar);
1075is.Get(ndatalloc);
1076is.Get(ndata);
1077is.Get(ndatagood);
1078is.Get(dobj->mOk_EXP);
1079if(nvar<=0 || ndatalloc<=0 || ndata<=0 || ndatagood<0 || ndatalloc<ndata) return;
1080
1081// Allocation de la place (attention Alloc efface mNData,mNDataGood);
1082dobj->Alloc(nvar,ndatalloc,-1);
1083dobj->mNData = ndata;
1084dobj->mNDataGood = ndatagood;
1085
1086// Lecture des datas
1087is.GetLine(strg, 255);
1088int blen = dobj->mNVar + 3;
1089if(dobj->mOk_EXP) blen += dobj->mNVar;
1090double *buff = new double[blen];
1091for(int i=0;i<dobj->mNData;i++) {
1092 is.Get(buff, blen);
1093 int ip = i*dobj->mNVar;
1094 {for(int j=0;j<dobj->mNVar;j++) dobj->mXP[ip+j] = buff[j];}
1095 dobj->mF[i] = buff[dobj->mNVar];
1096 dobj->mErr[i] = buff[dobj->mNVar+1];
1097 dobj->mOK[i] = (uint_2)(buff[dobj->mNVar+2]+0.01);
1098 if(dobj->mOk_EXP) {for(int j=0;j<dobj->mNVar;j++)
1099 dobj->mErrXP[ip+j] = buff[dobj->mNVar+3+j];}
1100}
1101delete [] buff;
1102
1103return;
1104}
1105
1106DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
1107void ObjFileIO<GeneralFitData>::WriteSelf(POutPersist& os) const
1108{
1109if (dobj == NULL) return;
1110char strg[256];
1111
1112// Ecriture entete pour identifier facilement
1113sprintf(strg,"GeneralFitData: NVar=%d NDataAlloc=%d NData=%d NDataGood=%d Ok_EXP=%d"
1114 ,dobj->mNVar,dobj->mNDataAlloc,dobj->mNData,dobj->mNDataGood,dobj->mOk_EXP);
1115os.PutLine(strg);
1116
1117// Ecriture des valeurs de definitions
1118os.Put(dobj->mNVar);
1119os.Put(dobj->mNDataAlloc);
1120os.Put(dobj->mNData);
1121os.Put(dobj->mNDataGood);
1122os.Put(dobj->mOk_EXP);
1123if(dobj->mNVar<=0 || dobj->mNDataAlloc<=0 || dobj->mNData<=0 || dobj->mNDataGood<0) return;
1124
1125// Ecriture des datas (on n'ecrit que mNData / mNDataAlloc)
1126sprintf(strg
1127 ,"GeneralFitData: Abscisses, Ordonnee, Erreur Ordonnee, Flag, Erreur Abscisses");
1128os.PutLine(strg);
1129
1130int blen = dobj->mNVar + 3;
1131if(dobj->mOk_EXP) blen += dobj->mNVar;
1132double *buff = new double[blen];
1133for(int i=0;i<dobj->mNData;i++) {
1134 {for(int j=0;j<dobj->mNVar;j++) buff[j] = dobj->Absc(j,i);}
1135 buff[dobj->mNVar] = dobj->Val(i);
1136 buff[dobj->mNVar+1] = dobj->EVal(i);
1137 buff[dobj->mNVar+2] = (double) dobj->IsValid(i);
1138 if(dobj->mOk_EXP) {for(int j=0;j<dobj->mNVar;j++) buff[dobj->mNVar+3+j] = dobj->EAbsc(j,i);}
1139 os.Put(buff, blen);
1140}
1141delete [] buff;
1142
1143return;
1144}
1145
1146
1147#ifdef __CXX_PRAGMA_TEMPLATES__
1148#pragma define_template ObjFileIO<GeneralFitData>
1149#endif
1150
1151#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
1152template class ObjFileIO<GeneralFitData>;
1153#endif
Note: See TracBrowser for help on using the repository browser.