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

Last change on this file since 3490 was 3235, checked in by ansari, 18 years ago

suppression include sopnamsp.h et mis la declaration namespace SOPHYA ds les fichiers .cc de NTools, quand DECL_TEMP_SPEC ds le fichier , cmv+reza 27/04/2007

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