[3115] | 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)
|
---|
[3157] | 21 | // ou les x_i sont regulierement espaces
|
---|
| 22 | // et x_0=xmin et x_{n-1}=xmax (xmax inclus!)
|
---|
[3115] | 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;
|
---|
[3157] | 31 | _dx = (_xmax-_xmin)/(double)_nm1;
|
---|
[3115] | 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;
|
---|
[3157] | 38 | long i = long(x/_dx); // On prend le "i" juste en dessous
|
---|
[3115] | 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;
|
---|
[3157] | 47 | long i = long(x/_dx+0.5); // On prend le "i" le + proche
|
---|
[3115] | 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 | //-------------------------------------------------------------------
|
---|
[3157] | 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 | //-------------------------------------------------------------------
|
---|
[3115] | 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 | }
|
---|