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

Last change on this file since 3739 was 3661, checked in by cmv, 16 years ago
  • ajout des TArray/TMatrix/TVector <uint_1> et <int_1>
  • cet ajout n'a pas ete porte dans Image<T>
  • correction petit bug:

inline int_4 Convert(int_2& x) const {...}
-> inline int_2 Convert(int_2& x) const {...}

cmv 23/10/2009

File size: 33.7 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;}
985 }
986return -1;
987}
988
989//! Pour interface NTuple
990string GeneralFitData::ColumnName(sa_size_t k) const
991{
992if(k==2*NVar()) return string("y");
993else if(k==2*NVar()+1) return string("ey");
994else if(k==2*NVar()+2) return string("ok");
995else if(k<0 || k>=2*NVar()+3) return string("");
996
997char str[64] = "";
998if(k<NVar()) sprintf(str,"x%d",k);
999else if(k<2*NVar()) sprintf(str,"ex%d",k-NVar());
1000return string(str);
1001}
1002
1003/*!
1004 Retourne une chaine de caracteres avec la declaration des noms de
1005 variables. si "nomx!=NULL" , des instructions d'affectation
1006 a partir d'un tableau "nomx[i]" sont ajoutees (pour interface NTuple).
1007*/
1008string GeneralFitData::VarList_C(const char* nomx) const
1009{
1010char buff[256];
1011string rets;
1012int_4 i;
1013rets = "\ndouble";
1014for(i=0; i<mNVar; i++) {
1015 sprintf(buff," x%d, ex%d",i,i);
1016 rets += buff;
1017 if(i!=mNVar-1) rets += ","; else rets += ";\n";
1018}
1019sprintf(buff,"\ndouble y, ey, ok;\n");
1020rets += buff;
1021if (nomx) {
1022 for(i=0; i<mNVar; i++) {
1023 sprintf(buff,"x%d=%s[%d];\n", i, nomx, i);
1024 rets += buff;
1025 }
1026 for(i=0; i<mNVar; i++) {
1027 sprintf(buff,"ex%d=%s[%d];\n", i, nomx, mNVar+i);
1028 rets += buff;
1029 }
1030 sprintf(buff,"y=%s[%d];\ney=%s[%d];\nok=%s[%d];\n"
1031 ,nomx,2*mNVar,nomx,2*mNVar+1,nomx,2*mNVar+2);
1032 rets += buff;
1033}
1034
1035return(rets);
1036}
1037
1038
1039//! Compute errors according to specifications
1040/*!
1041 \param val : value of the function
1042 \param err : value of the default error
1043 \param errtype : type of error according to enum FitErrType (def=DefaultError)
1044 \param errscale : scaling (or value) of the error (def=1.)
1045 \param errmin : minimum value of the error (def=0.)
1046 \param nozero : if true, do not return negative errors but
1047 set them to zero (def=false)
1048 \return : return the error computed according to specifications
1049 \verbatim
1050 - val is the value to be fitted ex: val = f(x,y,...)
1051 - err is the error by default we want to set.
1052 - errtype = DefaultError : errtmp = errscale*err
1053 errtype = ConstantError : errtmp = errscale
1054 errtype = SqrtError : errtmp = errscale*sqrt(|val|)
1055 errtype = ProporError : errtmp = errscale*|val|
1056 - errscale <=0 then errscale=1
1057 - errmin >=0 if errtmp>0 return max(errtmp,errmin)
1058 if errtmp<=0 return errtmp
1059 errmin <0 if errtmp>0 return max(errtmp,|errmin|)
1060 if errtmp<=0 return |errmin|
1061 \endverbatim
1062 */
1063double GeneralFitData::ComputeError(double val,double err,FitErrType errtype
1064 ,double errscale,double errmin,bool nozero)
1065{
1066 bool errminneg=false;
1067 if(errmin<0.) {errminneg=true; errmin*=-1.;}
1068 if(errscale<0.) errscale=1.;
1069
1070 // Choix du type d'erreur
1071 if(errtype==ConstantError) err = errscale;
1072 else if(errtype==SqrtError) err = errscale*sqrt(fabs(val));
1073 else if(errtype==ProporError) err = errscale*fabs(val);
1074
1075 // Gestion du minimum a partir de la valeur calculee precedemment "err"
1076 // Ex1: errmin=1., err=10. ==> 10.
1077 // err=0.5 ==> 1.
1078 // err=0. ==> 0.
1079 // err=-2. ==> -2.
1080 // Ex2: errmin=-1., err=10. ==> 10.
1081 // err=0.5 ==> 1.
1082 // err=0. ==> 1.
1083 // err=-2. ==> 11.
1084 if(err>0.) err = (err>errmin) ? err: errmin;
1085 else if(errminneg) err = errmin;
1086
1087 // ne pas retourner d'erreurs negatives si demande
1088 if(nozero && err<0.) err=0.;
1089
1090 return err;
1091}
1092
1093///////////////////////////////////////////////////////////
1094// --------------------------------------------------------
1095// Les objets delegues pour la gestion de persistance
1096// --------------------------------------------------------
1097///////////////////////////////////////////////////////////
1098
1099
1100DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
1101void ObjFileIO<GeneralFitData>::ReadSelf(PInPersist& is)
1102{
1103char strg[256];
1104
1105if(dobj==NULL) dobj=new GeneralFitData;
1106 else dobj->Delete();
1107
1108// Lecture entete
1109is.GetLine(strg, 255);
1110
1111// Ecriture des valeurs de definitions
1112int_4 nvar,ndatalloc,ndata,ndatagood;
1113is.Get(nvar);
1114is.Get(ndatalloc);
1115is.Get(ndata);
1116is.Get(ndatagood);
1117is.Get(dobj->mOk_EXP);
1118if(nvar<=0 || ndatalloc<=0 || ndata<=0 || ndatagood<0 || ndatalloc<ndata) return;
1119
1120// Allocation de la place (attention Alloc efface mNData,mNDataGood);
1121dobj->Alloc(nvar,ndatalloc,dobj->mOk_EXP);
1122dobj->mNData = ndata;
1123dobj->mNDataGood = ndatagood;
1124
1125// Lecture des datas
1126is.GetLine(strg, 255);
1127int_4 blen = dobj->mNVar + 3;
1128if(dobj->mOk_EXP) blen += dobj->mNVar;
1129double *buff = new double[blen];
1130for(int_4 i=0;i<dobj->mNData;i++) {
1131 is.Get(buff, blen);
1132 int_4 ip = i*dobj->mNVar;
1133 {for(int_4 j=0;j<dobj->mNVar;j++) dobj->mXP[ip+j] = buff[j];}
1134 dobj->mF[i] = buff[dobj->mNVar];
1135 dobj->mErr[i] = buff[dobj->mNVar+1];
1136 dobj->mOK[i] = (uint_2)(buff[dobj->mNVar+2]+0.01);
1137 if(dobj->mOk_EXP) {for(int_4 j=0;j<dobj->mNVar;j++)
1138 dobj->mErrXP[ip+j] = buff[dobj->mNVar+3+j];}
1139}
1140delete [] buff;
1141
1142return;
1143}
1144
1145DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
1146void ObjFileIO<GeneralFitData>::WriteSelf(POutPersist& os) const
1147{
1148if (dobj == NULL) return;
1149char strg[256];
1150
1151// Ecriture entete pour identifier facilement
1152sprintf(strg,"GeneralFitData: NVar=%d NDataAlloc=%d NData=%d NDataGood=%d Ok_EXP=%d"
1153 ,dobj->mNVar,dobj->mNDataAlloc,dobj->mNData,dobj->mNDataGood,dobj->mOk_EXP);
1154os.PutLine(strg);
1155
1156// Ecriture des valeurs de definitions
1157os.Put(dobj->mNVar);
1158os.Put(dobj->mNDataAlloc);
1159os.Put(dobj->mNData);
1160os.Put(dobj->mNDataGood);
1161os.Put(dobj->mOk_EXP);
1162if(dobj->mNVar<=0 || dobj->mNDataAlloc<=0 || dobj->mNData<=0 || dobj->mNDataGood<0) return;
1163
1164// Ecriture des datas (on n'ecrit que mNData / mNDataAlloc)
1165sprintf(strg
1166 ,"GeneralFitData: Abscisses, Ordonnee, Erreur Ordonnee, Flag, Erreur Abscisses");
1167os.PutLine(strg);
1168
1169int_4 blen = dobj->mNVar + 3;
1170if(dobj->mOk_EXP) blen += dobj->mNVar;
1171double *buff = new double[blen];
1172for(int_4 i=0;i<dobj->mNData;i++) {
1173 {for(int_4 j=0;j<dobj->mNVar;j++) buff[j] = dobj->Absc(j,i);}
1174 buff[dobj->mNVar] = dobj->Val(i);
1175 buff[dobj->mNVar+1] = dobj->EVal(i);
1176 buff[dobj->mNVar+2] = (double) dobj->IsValid(i);
1177 if(dobj->mOk_EXP) {for(int_4 j=0;j<dobj->mNVar;j++) buff[dobj->mNVar+3+j] = dobj->EAbsc(j,i);}
1178 os.Put(buff, blen);
1179}
1180delete [] buff;
1181
1182return;
1183}
1184
1185
1186#ifdef __CXX_PRAGMA_TEMPLATES__
1187#pragma define_template ObjFileIO<GeneralFitData>
1188#endif
1189
1190#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
1191template class ObjFileIO<GeneralFitData>;
1192#endif
1193
1194} // FIN namespace SOPHYA
Note: See TracBrowser for help on using the repository browser.