1 | #include "sopnamsp.h"
|
---|
2 | #include "machdefs.h"
|
---|
3 | #include <iostream>
|
---|
4 | #include <stdlib.h>
|
---|
5 | #include <stdio.h>
|
---|
6 | #include <string.h>
|
---|
7 | #include <math.h>
|
---|
8 | #include <vector>
|
---|
9 |
|
---|
10 | #include "pexceptions.h"
|
---|
11 |
|
---|
12 | #include "histos.h"
|
---|
13 | #include "hisprof.h"
|
---|
14 | #include "srandgen.h"
|
---|
15 |
|
---|
16 | #include "geneutils.h"
|
---|
17 |
|
---|
18 | //-------------------------------------------------------------------
|
---|
19 | // Classe d'interpolation lineaire:
|
---|
20 | // Le vecteur y a n elements y_i tels que y_i = f(x_i)
|
---|
21 | // ou les x_i sont regulierement espaces
|
---|
22 | // et x_0=xmin et x_{n-1}=xmax (xmax inclus!)
|
---|
23 | InterpFunc::InterpFunc(double xmin,double xmax,vector<double>& y)
|
---|
24 | : _xmin(xmin), _xmax(xmax), _y(y)
|
---|
25 | {
|
---|
26 | if(_xmin>=_xmax || _y.size()<=2) { // au moins 3 points!
|
---|
27 | cout<<"InterpFunc::InterpFunc : bad arguments values"<<endl;
|
---|
28 | throw ParmError("InterpFunc::InterpFunc : bad arguments values");
|
---|
29 | }
|
---|
30 | _nm1 = _y.size()-1;
|
---|
31 | _dx = (_xmax-_xmin)/(double)_nm1;
|
---|
32 | }
|
---|
33 |
|
---|
34 | double InterpFunc::Linear(double x,unsigned short& ok)
|
---|
35 | {
|
---|
36 | ok=0; if(x<_xmin) ok=1; else if(x>_xmax) ok=2;
|
---|
37 | x -= _xmin;
|
---|
38 | long i = long(x/_dx); // On prend le "i" juste en dessous
|
---|
39 | if(i<0) i=0; else if(i>=_nm1) i=_nm1-1;
|
---|
40 | return _y[i] + (_y[i+1]-_y[i])/_dx*(x-i*_dx);
|
---|
41 | }
|
---|
42 |
|
---|
43 | double InterpFunc::Parab(double x,unsigned short& ok)
|
---|
44 | {
|
---|
45 | ok=0; if(x<_xmin) ok=1; else if(x>_xmax) ok=2;
|
---|
46 | x -= _xmin;
|
---|
47 | long i = long(x/_dx+0.5); // On prend le "i" le + proche
|
---|
48 | if(i<1) i=1; else if(i>=_nm1-1) i=_nm1-2;
|
---|
49 | double a = (_y[i+1]-2.*_y[i]+_y[i-1])/(2.*_dx*_dx);
|
---|
50 | double b = (_y[i+1]-_y[i-1])/(2.*_dx);
|
---|
51 | return _y[i] + (x-i*_dx)*(a*(x-i*_dx)+b);
|
---|
52 | }
|
---|
53 |
|
---|
54 | //-------------------------------------------------------------------
|
---|
55 | // Classe d'inversion d'une fonction STRICTEMENT MONOTONE CROISSANTE
|
---|
56 | // - Le vecteur y a "Nin" elements y_i tels que "y_i = f(x_i)"
|
---|
57 | // - On a x(i) < x(i+1) et y(i) < y(i+1)
|
---|
58 | // - La classe renvoie ymin=y(0) , ymax=y(Nin -1)
|
---|
59 | // et le vecteur x = f^-1(y) de "Nout" elements
|
---|
60 | // Les y_i sont regulierement espaces et ymin et ymax
|
---|
61 | // La re-interpolation inverse est faite par lineaire
|
---|
62 | InverseFunc::InverseFunc(vector<double>& x,vector<double>& y)
|
---|
63 | : _ymin(0.) , _ymax(0.) , _x(x) , _y(y)
|
---|
64 | {
|
---|
65 | int_4 ns = _x.size();
|
---|
66 | if(ns<3 || _y.size()<=0 || ns!=_y.size())
|
---|
67 | throw ParmError("InverseFunc::InverseFunc_Error: bad array size");
|
---|
68 |
|
---|
69 | // Check "x" strictement monotone croissant
|
---|
70 | for(int_4 i=0;i<ns-1;i++)
|
---|
71 | if(_x[i+1]<=_x[i]) {
|
---|
72 | cout<<"InverseFunc::InverseFunc_Error: _x array not stricly growing"<<endl;
|
---|
73 | throw ParmError("InverseFunc::InverseFunc_Error: _x array not stricly growing");
|
---|
74 | }
|
---|
75 |
|
---|
76 | // Check "y" monotone croissant
|
---|
77 | for(int_4 i=0;i<ns-1;i++)
|
---|
78 | if(_y[i+1]<_y[i]) {
|
---|
79 | cout<<"InverseFunc::InverseFunc_Error: _y array not growing"<<endl;
|
---|
80 | throw ParmError("InverseFunc::InverseFunc_Error: _y array not growing");
|
---|
81 | }
|
---|
82 |
|
---|
83 | // define limits
|
---|
84 | _ymin = _y[0];
|
---|
85 | _ymax = _y[ns-1];
|
---|
86 |
|
---|
87 | }
|
---|
88 |
|
---|
89 | InverseFunc::~InverseFunc(void)
|
---|
90 | {
|
---|
91 | }
|
---|
92 |
|
---|
93 | int InverseFunc::ComputeLinear(long n,vector<double>& xfcty)
|
---|
94 | {
|
---|
95 | if(n<3) return -1;
|
---|
96 |
|
---|
97 | xfcty.resize(n);
|
---|
98 |
|
---|
99 | long i1,i2;
|
---|
100 | double x;
|
---|
101 | for(int_4 i=0;i<n;i++) {
|
---|
102 | double y = _ymin + i*(_ymax-_ymin)/(n-1.);
|
---|
103 | find_in_y(y,i1,i2);
|
---|
104 | double dy = _y[i2]-_y[i1];
|
---|
105 | if(dy==0.) {
|
---|
106 | x = (_x[i2]+_x[i1])/2.; // la fct a inverser est plate!
|
---|
107 | } else {
|
---|
108 | x = _x[i1] + (_x[i2]-_x[i1])/dy * (y-_y[i1]);
|
---|
109 | }
|
---|
110 | xfcty[i] = x;
|
---|
111 | }
|
---|
112 |
|
---|
113 | return 0;
|
---|
114 | }
|
---|
115 |
|
---|
116 | int InverseFunc::ComputeParab(long n,vector<double>& xfcty)
|
---|
117 | {
|
---|
118 | if(n<3) return -1;
|
---|
119 |
|
---|
120 | xfcty.resize(n);
|
---|
121 |
|
---|
122 | long i1,i2,i3;
|
---|
123 | double x;
|
---|
124 | for(int_4 i=0;i<n;i++) {
|
---|
125 | double y = _ymin + i*(_ymax-_ymin)/(n-1.);
|
---|
126 | find_in_y(y,i1,i2);
|
---|
127 | // On cherche le 3ieme point selon la position de y / au 2 premiers
|
---|
128 | double my = (_y[i1]+_y[i2])/2.;
|
---|
129 | if(y<my) {i3=i2; i2=i1; i1--;} else {i3=i2+1;}
|
---|
130 | // Protection
|
---|
131 | if(i1<0) {i1++; i2++; i3++;}
|
---|
132 | if(i3==_y.size()) {i1--; i2--; i3--;}
|
---|
133 | // Interpolation parabolique
|
---|
134 | double dy = _y[i3]-_y[i1];
|
---|
135 | if(dy==0.) {
|
---|
136 | x = (_x[i3]+_x[i1])/2.; // la fct a inverser est plate!
|
---|
137 | } else {
|
---|
138 | double X1=_x[i1]-_x[i2], X3=_x[i3]-_x[i2];
|
---|
139 | double Y1=_y[i1]-_y[i2], Y3=_y[i3]-_y[i2];
|
---|
140 | double den = Y1*Y3*dy;
|
---|
141 | double a = (X3*Y1-X1*Y3)/den;
|
---|
142 | double b = (X1*Y3*Y3-X3*Y1*Y1)/den;
|
---|
143 | y -= _y[i2];
|
---|
144 | x = (a*y+b)*y + _x[i2];
|
---|
145 | }
|
---|
146 | xfcty[i] = x;
|
---|
147 | }
|
---|
148 |
|
---|
149 | return 0;
|
---|
150 | }
|
---|
151 |
|
---|
152 | //-------------------------------------------------------------------
|
---|
153 | int FuncToHisto(GenericFunc& func,Histo& h,bool logaxex)
|
---|
154 | // Remplit l'histo 1D "h" avec la fonction "func"
|
---|
155 | // INPUT:
|
---|
156 | // logaxex = false : remplissage lineaire
|
---|
157 | // les abscisses "x" des bins sont remplis avec f(x)
|
---|
158 | // logaxex = true : remplissage logarithmique (base 10)
|
---|
159 | // les abscisses "x" des bins sont remplis avec f(10^x)
|
---|
160 | // RETURN:
|
---|
161 | // 0 = OK
|
---|
162 | // 1 = error
|
---|
163 | {
|
---|
164 | if(h.NBins()<=0) return 1;
|
---|
165 |
|
---|
166 | h.Zero();
|
---|
167 |
|
---|
168 | for(int_4 i=0;i<h.NBins();i++) {
|
---|
169 | double x = h.BinCenter(i);
|
---|
170 | if(logaxex) x = pow(10.,x);
|
---|
171 | h.SetBin(i,func(x));
|
---|
172 | }
|
---|
173 |
|
---|
174 | return 0;
|
---|
175 | }
|
---|
176 |
|
---|
177 | int FuncToVec(GenericFunc& func,TVector<r_8>& v,double xmin,double xmax,bool logaxex)
|
---|
178 | // Remplit le TVector avec la fonction "func"
|
---|
179 | // INPUT:
|
---|
180 | // logaxex = false : remplissage lineaire
|
---|
181 | // les abscisses "x" des bins sont remplis avec f(x)
|
---|
182 | // logaxex = true : remplissage logarithmique (base 10)
|
---|
183 | // les abscisses "x" des bins sont remplis avec f(10^x)
|
---|
184 | // RETURN:
|
---|
185 | // 0 = OK
|
---|
186 | // 1 = error
|
---|
187 | // Remarque:
|
---|
188 | // v(i) = f(xmin+i*dx) avec dx = (xmax-xmin)/v.NElts()
|
---|
189 | {
|
---|
190 | if(v.NElts()<=0 || xmax<=xmin) return 1;
|
---|
191 |
|
---|
192 | v = 0.;
|
---|
193 | double dx = (xmax-xmin)/v.NElts();
|
---|
194 |
|
---|
195 | for(int_4 i=0;i<v.NElts();i++) {
|
---|
196 | double x = xmin + i * dx;;
|
---|
197 | if(logaxex) x = pow(10.,x);
|
---|
198 | v(i) = func(x);
|
---|
199 | }
|
---|
200 |
|
---|
201 | return 0;
|
---|
202 | }
|
---|
203 |
|
---|
204 | //-------------------------------------------------------------------
|
---|
205 | double AngSol(double dtheta,double dphi,double theta0)
|
---|
206 | // Retourne l'angle solide d'un "rectangle" et coordonnees spheriques
|
---|
207 | // de DEMI-COTE "dtheta" x "dphi" et centre en "theta0"
|
---|
208 | // Attention: Le "theta0" de l'equateur est Pi/2 (et non pas zero)
|
---|
209 | // Les unites des angles sont en radians
|
---|
210 | // theta0 in [0,Pi]
|
---|
211 | // dtheta in [0,Pi]
|
---|
212 | // dphi in [0,2Pi]
|
---|
213 | // Return: l'angle solide en steradian
|
---|
214 | {
|
---|
215 | double theta1 = theta0-dtheta, theta2 = theta0+dtheta;
|
---|
216 | if(theta1<0.) theta1=0.;
|
---|
217 | if(theta2>M_PI) theta2=M_PI;
|
---|
218 |
|
---|
219 | return 2.*dphi * (cos(theta1)-cos(theta2));
|
---|
220 | }
|
---|
221 |
|
---|
222 | double AngSol(double dtheta)
|
---|
223 | // Retourne l'angle solide d'une calotte spherique de demi-ouverture "dtheta"
|
---|
224 | // Attention: Les unites des angles sont en radians
|
---|
225 | // dtheta in [0,Pi]
|
---|
226 | // Return: l'angle solide en steradian
|
---|
227 | // Approx pour theta petit: PI theta^2
|
---|
228 | {
|
---|
229 | return 2.*M_PI * (1.-cos(dtheta));
|
---|
230 | }
|
---|
231 |
|
---|
232 | //-------------------------------------------------------------------
|
---|
233 | unsigned long PoissRandLimit(double mu,double mumax)
|
---|
234 | {
|
---|
235 | double pp,ppi,x;
|
---|
236 | unsigned long n;
|
---|
237 |
|
---|
238 | if(mu>=mumax) {
|
---|
239 | pp = sqrt(mu);
|
---|
240 | while( (x=pp*NorRand()) < -mu );
|
---|
241 | return (unsigned long)(mu+x+0.5);
|
---|
242 | }
|
---|
243 |
|
---|
244 | ppi = pp = exp(-mu);
|
---|
245 | x = drand01();
|
---|
246 | n = 0;
|
---|
247 | while (x > ppi) {
|
---|
248 | n++;
|
---|
249 | pp = mu*pp/(double)n;
|
---|
250 | ppi += pp;
|
---|
251 | }
|
---|
252 | return n;
|
---|
253 | }
|
---|