| 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 | }
 | 
|---|