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

Last change on this file since 3062 was 3062, checked in by cmv, 19 years ago

dans GeneralFitData int -> int_4
GeneralFitData creation operator =
cmv 14/8/2006

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