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

Last change on this file since 2615 was 2615, checked in by cmv, 21 years ago

using namespace sophya enleve de machdefs.h, nouveau sopnamsp.h cmv 10/09/2004

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