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

Last change on this file since 2340 was 2340, checked in by ansari, 23 years ago

Nettoyage apres Compli avec SGI-CC / gcc 3.1 - Reza 10/03/2003

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