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

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

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