source: Sophya/trunk/Cosmo/RadioBeam/specpk.cc@ 3983

Last change on this file since 3983 was 3947, checked in by ansari, 15 years ago

Amelioration et modifs diverses lors de la redaction du papier, Reza 13/02/2011

File size: 15.6 KB
Line 
1
2/* ------------------------ Projet BAORadio --------------------
3 Classes to compute 3D power spectrum and noise power spectrum
4 R. Ansari - Nov 2008 ... Dec 2010
5--------------------------------------------------------------- */
6
7#include "specpk.h"
8#include "randr48.h"
9#include "ctimer.h"
10
11//------------------------------------
12// Class SpectralShape
13// -----------------------------------
14
15double Pnu1(double nu)
16{
17 return ( sqrt(sqrt(nu)) / ((nu+1.0)/0.2) *
18 (1+0.2*cos(2*M_PI*(nu-2.)*0.15)*exp(-nu/50.)) );
19}
20
21double Pnu2(double nu)
22{
23 if (nu < 1.e-9) return 0.;
24 return ((1.-exp(-nu/0.5))/nu*(1+0.25*cos(2*M_PI*nu*0.1)*exp(-nu/20.)) );
25}
26
27
28double Pnu3(double nu)
29{
30 return ( log(nu/100.+1)*(1+sin(2*M_PI*nu/300))*exp(-nu/4000) );
31}
32
33
34double Pnu4(double nu)
35{
36 double x = (nu-0.5)/0.05;
37 double rc = 2*exp(-x*x);
38 x = (nu-3.1)/0.27;
39 rc += exp(-x*x);
40 x = (nu-7.6)/1.4;
41 rc += 0.5*exp(-x*x);
42 return ( rc+2.*exp(-x*x) );
43}
44
45//--------------------------------------------------
46// -- SpectralShape class : test P(k) class
47//--------------------------------------------------
48// Constructor
49SpectralShape::SpectralShape(int typ)
50{
51 typ_=typ;
52 SetRenormFac();
53}
54
55// Return the spectral power for a given wave number wk
56double SpectralShape::operator() (double wk)
57{
58 wk/=DeuxPI;
59 double retv=1.;
60 switch (typ_)
61 {
62 case 1:
63 retv=Pnu1(wk);
64 break;
65 case 2:
66 retv=Pnu2(wk);
67 break;
68 case 3:
69 retv=Pnu3(wk);
70 break;
71 case 4:
72 retv=Pnu4(wk);
73 break;
74 default :
75 {
76 // global shape
77 double csp = pow( (2*sin(sqrt(sqrt(wk/7.)))),2.);
78 if (csp < 0.) return 0.;
79
80 // Adding some pics
81 double picpos[5] = {75.,150.,225.,300.,375.,};
82
83 for(int k=0; k<5; k++) {
84 double x0 = picpos[k];
85 if ( (wk > x0-25.) && (wk < x0+25.) ) {
86 double x = (wk-x0);
87 csp *= (1.+0.5*exp(-(x*x)/(2.*5*5)));
88 break;
89 }
90 }
91 retv=csp;
92 }
93 break;
94 }
95 return retv*renorm_fac;
96}
97// Return a vector representing the power spectrum (for checking)
98Histo SpectralShape::GetPk(int n)
99{
100 if (n<16) n = 256;
101 Histo h(0.,1024.*DeuxPI,n);
102 for(int k=0; k<h.NBins(); k++) h(k) = Value((k+0.5)*h.BinWidth());
103 return h;
104}
105
106double SpectralShape::Sommek2Pk(double kmax, int n)
107{
108 double dk=kmax/(double)n;
109 double s=0.;
110 for(int i=1; i<=n; i++) {
111 double ck=(double)i*dk;
112 s += Value(ck)*ck*ck;
113 }
114 return s*dk*4.*M_PI;
115}
116//--------------------------------------------------
117// -- Four2DResponse class : test P(k) class
118
119//---------------------------------------------------------------
120// -- Four3DPk class : 3D fourier amplitudes and power spectrum
121//---------------------------------------------------------------
122// Constructeur avec Tableau des coeff. de Fourier en argument
123Four3DPk::Four3DPk(TArray< complex<TF> > & fourcoedd, RandomGeneratorInterface& rg)
124 : rg_(rg), fourAmp(fourcoedd)
125{
126 SetPrtLevel();
127 SetCellSize();
128}
129// Constructor
130Four3DPk::Four3DPk(RandomGeneratorInterface& rg, sa_size_t szx, sa_size_t szy, sa_size_t szz)
131 : rg_(rg), fourAmp(szx, szy, szz)
132{
133 SetPrtLevel();
134 SetCellSize();
135}
136
137
138// Generate mass field Fourier Coefficient
139void Four3DPk::ComputeFourierAmp(SpectralShape& pk)
140{
141 // We generate a random gaussian real field
142 // fourAmp represent 3-D fourier transform of a real input array.
143 // The second half of the array along Y and Z contain negative frequencies
144 // double fnorm = 1./sqrt(2.*fourAmp.Size());
145 double fnorm = 1.;
146 double kxx, kyy, kzz;
147 // sa_size_t is large integer type
148 for(sa_size_t kz=0; kz<fourAmp.SizeZ(); kz++) {
149 kzz = (kz>fourAmp.SizeZ()/2) ? (double)(fourAmp.SizeZ()-kz)*dkz_ : (double)kz*dkz_;
150 for(sa_size_t ky=0; ky<fourAmp.SizeY(); ky++) {
151 kyy = (ky>fourAmp.SizeY()/2) ? (double)(fourAmp.SizeY()-ky)*dky_ : (double)ky*dky_;
152 for(sa_size_t kx=0; kx<fourAmp.SizeX(); kx++) {
153 double kxx=(double)kx*dkx_;
154 double wk = sqrt(kxx*kxx+kyy*kyy+kzz*kzz);
155 double amp = sqrt(pk(wk)*fnorm/2.);
156 fourAmp(kx, ky, kz) = complex<TF>(rg_.Gaussian(amp), rg_.Gaussian(amp)); // renormalize fourier coeff usin
157 }
158 }
159 }
160 if (prtlev_>2)
161 cout << " Four3DPk::ComputeFourierAmp() done ..." << endl;
162}
163
164// Generate mass field Fourier Coefficient
165void Four3DPk::ComputeNoiseFourierAmp(Four2DResponse& resp, bool crmask)
166{
167 TMatrix<r_4> mask(fourAmp.SizeY(), fourAmp.SizeX());
168 // fourAmp represent 3-D fourier transform of a real input array.
169 // The second half of the array along Y and Z contain negative frequencies
170 double kxx, kyy, kzz, rep, amp;
171 // sa_size_t is large integer type
172 for(sa_size_t kz=0; kz<fourAmp.SizeZ(); kz++) {
173 kzz = (kz>fourAmp.SizeZ()/2) ? -(double)(fourAmp.SizeZ()-kz)*dkz_ : (double)kz*dkz_;
174 for(sa_size_t ky=0; ky<fourAmp.SizeY(); ky++) {
175 kyy = (ky>fourAmp.SizeY()/2) ? -(double)(fourAmp.SizeY()-ky)*dky_ : (double)ky*dky_;
176 for(sa_size_t kx=0; kx<fourAmp.SizeX(); kx++) {
177 kxx=(double)kx*dkx_;
178 rep = resp(kxx, kyy);
179 if (crmask&&(kz==0)) mask(ky,kx)=((rep<1.e-8)?9.e9:(1./rep));
180 if (rep<1.e-8) fourAmp(kx, ky, kz) = complex<TF>(9.e9,0.);
181 else {
182 amp = 1./sqrt(rep)/sqrt(2.);
183 fourAmp(kx, ky, kz) = complex<TF>(rg_.Gaussian(amp), rg_.Gaussian(amp));
184 }
185 }
186 }
187 }
188 if (prtlev_>2) fourAmp.Show();
189 if (crmask) {
190 POutPersist po("mask.ppf");
191 po << mask;
192 }
193 if (prtlev_>0)
194 cout << " Four3DPk::ComputeNoiseFourierAmp() done ..." << endl;
195}
196
197// Compute mass field from its Fourier Coefficient
198TArray<TF> Four3DPk::ComputeMassDens()
199{
200 TArray<TF> massdens;
201// Backward fourier transform of the fourierAmp array
202 FFTWServer ffts(true);
203 ffts.setNormalize(true);
204 ffts.FFTBackward(fourAmp, massdens, true);
205 // cout << " Four3DPk::ComputeMassDens() done NbNeg=" << npbz << " / NPix=" << massDens.Size() << endl;
206 cout << " Four3DPk::ComputeMassDens() done NPix=" << massdens.Size() << endl;
207 return massdens;
208}
209
210// Compute power spectrum as a function of wave number k
211// cells with amp^2=re^2+im^2>s2cut are ignored
212// Output : power spectrum (profile histogram)
213HProf Four3DPk::ComputePk(double s2cut, int nbin, double kmin, double kmax)
214{
215 // The second half of the array along Y (matrix rows) contain
216 // negative frequencies
217 // int nbh = sqrt(fourAmp.SizeX()*fourAmp.SizeX()+fourAmp.SizeY()*fourAmp.SizeY()/4.+fourAmp.SizeZ()*fourAmp.SizeY()/4.);
218 // The profile histogram will contain the mean value of FFT amplitude
219 // as a function of wave-number k = sqrt((double)(kx*kx+ky*ky))
220 // if (nbin < 1) nbin = nbh/2;
221 if ((kmax<0.)||(kmax<kmin)) {
222 kmin=0.;
223 double maxx=fourAmp.SizeX()*dkx_;
224 double maxy=fourAmp.SizeY()*dky_/2;
225 double maxz=fourAmp.SizeZ()*dkz_/2;
226 kmax=sqrt(maxx*maxx+maxy*maxy+maxz*maxz);
227 }
228 if (nbin<2) nbin=128;
229 HProf hp(kmin, kmax, nbin);
230 hp.SetErrOpt(false);
231 ComputePkCumul(hp, s2cut);
232 return hp;
233}
234
235// Compute power spectrum as a function of wave number k
236// Cumul dans hp - cells with amp^2=re^2+im^2>s2cut are ignored
237void Four3DPk::ComputePkCumul(HProf& hp, double s2cut)
238{
239 uint_8 nmodeok=0;
240 // fourAmp represent 3-D fourier transform of a real input array.
241 // The second half of the array along Y and Z contain negative frequencies
242 double kxx, kyy, kzz;
243 // sa_size_t is large integer type
244 // We ignore 0th term in all frequency directions ...
245 for(sa_size_t kz=1; kz<fourAmp.SizeZ(); kz++) {
246 kzz = (kz > fourAmp.SizeZ()/2) ? (double)(fourAmp.SizeZ()-kz)*dkz_ : (double)kz*dkz_;
247 for(sa_size_t ky=1; ky<fourAmp.SizeY(); ky++) {
248 kyy = (ky > fourAmp.SizeY()/2) ? (double)(fourAmp.SizeY()-ky)*dky_ : (double)ky*dky_;
249 for(sa_size_t kx=1; kx<fourAmp.SizeX(); kx++) { // ignore the 0th coefficient (constant term)
250 double kxx=(double)kx*dkx_;
251 complex<TF> za = fourAmp(kx, ky, kz);
252 if (za.real()>8.e9) continue;
253 double wk = sqrt(kxx*kxx+kyy*kyy+kzz*kzz);
254 double amp2 = za.real()*za.real()+za.imag()*za.imag();
255 if ((s2cut>1.e-9)&&(amp2>s2cut)) continue;
256 hp.Add(wk, amp2);
257 nmodeok++;
258 }
259 }
260 }
261 if ((prtlev_>1)||((prtlev_>0)&&(s2cut>1.e-9))) {
262 cout << " Four3DPk::ComputePkCumul/Info : NModeOK=" << nmodeok << " / NMode=" << fourAmp.Size()
263 << " -> " << 100.*(double)nmodeok/(double)fourAmp.Size() << "%" << endl;
264 }
265 return;
266}
267
268// Compute noise power spectrum as a function of wave number k
269// No random generation, computes profile of noise sigma^2
270// cells with amp^2=re^2+im^2>s2cut are ignored
271// Output : noise power spectrum (profile histogram)
272HProf Four3DPk::ComputeNoisePk(Four2DResponse& resp, Histo& fracmodok, DataTable& dt,
273 double s2cut, int nbin, double kmin, double kmax)
274{
275 // The second half of the array along Y (matrix rows) contain
276 // negative frequencies
277 // int nbh = sqrt(fourAmp.SizeX()*fourAmp.SizeX()+fourAmp.SizeY()*fourAmp.SizeY()/4.+fourAmp.SizeZ()*fourAmp.SizeY()/4.);
278 // The profile histogram will contain the mean value of noise sigma^2
279 // as a function of wave-number k = sqrt((double)(kx*kx+ky*ky))
280 // if (nbin < 1) nbin = nbh/2;
281 if ((kmax<0.)||(kmax<kmin)) {
282 kmin=0.;
283 double maxx=fourAmp.SizeX()*dkx_;
284 double maxy=fourAmp.SizeY()*dky_/2;
285 double maxz=fourAmp.SizeZ()*dkz_/2;
286 kmax=sqrt(maxx*maxx+maxy*maxy+maxz*maxz);
287 }
288 if (nbin<2) nbin=128;
289 HProf hp(kmin, kmax, nbin);
290 hp.SetErrOpt(false);
291 Histo hmcnt(kmin, kmax, nbin);
292 Histo hmcntok(kmin, kmax, nbin);
293
294 uint_8 nmodeok=0;
295 // fourAmp represent 3-D fourier transform of a real input array.
296 // The second half of the array along Y and Z contain negative frequencies
297 double kxx, kyy, kzz;
298 // sa_size_t is large integer type
299 // We ignore 0th term in all frequency directions ...
300 for(sa_size_t kz=1; kz<fourAmp.SizeZ(); kz++) {
301 kzz = (kz > fourAmp.SizeZ()/2) ? (double)(fourAmp.SizeZ()-kz)*dkz_ : (double)kz*dkz_;
302 for(sa_size_t ky=1; ky<fourAmp.SizeY(); ky++) {
303 kyy = (ky > fourAmp.SizeY()/2) ? (double)(fourAmp.SizeY()-ky)*dky_ : (double)ky*dky_;
304 for(sa_size_t kx=1; kx<fourAmp.SizeX(); kx++) { // ignore the 0th coefficient (constant term)
305 double kxx=(double)kx*dkx_;
306 double wk = sqrt(kxx*kxx+kyy*kyy+kzz*kzz);
307 double amp2 = 1./resp(kxx, kyy);
308 hmcnt.Add(wk);
309 if ((s2cut>1.e-9)&&(amp2>s2cut)) continue;
310 hmcntok.Add(wk);
311 hp.Add(wk, amp2);
312 nmodeok++;
313 }
314 }
315 }
316 if ((prtlev_>1)||((prtlev_>0)&&(s2cut>1.e-9))) {
317 cout << " Four3DPk::ComputeNoisePk/Info : NModeOK=" << nmodeok << " / NMode=" << fourAmp.Size()
318 << " -> " << 100.*(double)nmodeok/(double)fourAmp.Size() << "%" << endl;
319 }
320
321 fracmodok=hmcntok/hmcnt;
322
323 char* nomcol[5] = {"k","pnoise","nmode","nmodok","fracmodok"};
324 dt.Clear();
325 dt.AddDoubleColumn(nomcol[0]);
326 dt.AddDoubleColumn(nomcol[1]);
327 dt.AddIntegerColumn(nomcol[2]);
328 dt.AddIntegerColumn(nomcol[3]);
329 dt.AddFloatColumn(nomcol[4]);
330 DataTableRow dtr = dt.EmptyRow();
331 for(int_4 ib=0; ib<hp.NBins(); ib++) {
332 dtr[0]=hp.BinCenter(ib);
333 dtr[1]=hp(ib);
334 dtr[2]=hmcnt(ib);
335 dtr[3]=hmcntok(ib);
336 dtr[4]=fracmodok(ib);
337 dt.AddRow(dtr);
338 }
339 return hp;
340}
341
342//-----------------------------------------------------
343// -- MassDist2D class : 2D mass distribution
344// --- PkNoiseCalculator : Classe de calcul du spectre de bruit PNoise(k)
345// determine par une reponse 2D de l'instrument
346//-----------------------------------------------------
347PkNoiseCalculator::PkNoiseCalculator(Four3DPk& pk3, Four2DResponse& rep, double s2cut, int ngen,
348 const char* tit)
349 : pkn3d(pk3), frep(rep), S2CUT(s2cut), NGEN(ngen), title(tit)
350{
351 SetPrtLevel();
352}
353
354HProf PkNoiseCalculator::Compute()
355{
356 Timer tm(title.c_str());
357 tm.Nop();
358 HProf hnd;
359 cout << "PkNoiseCalculator::Compute() " << title << " NGEN=" << NGEN << " S2CUT=" << S2CUT << endl;
360 for(int igen=0; igen<NGEN; igen++) {
361 pkn3d.ComputeNoiseFourierAmp(frep);
362 if (igen==0) hnd = pkn3d.ComputePk(S2CUT);
363 else pkn3d.ComputePkCumul(hnd,S2CUT);
364 if ((prtlev_>0)&&(igen>0)&&(((igen-1)%prtmodulo_)==0))
365 cout << " PkNoiseCalculator::Compute() - done igen=" << igen << " / MaxNGen=" << NGEN << endl;
366 }
367 return hnd;
368}
369
370
371//-----------------------------------------------------
372// -- MassDist2D class : 2D mass distribution
373//-----------------------------------------------------
374// Constructor
375MassDist2D::MassDist2D(GenericFunc& pk, int size, double meandens)
376: pkSpec(pk) , sizeA((size>16)?size:16) , massDens(sizeA, sizeA),
377 meanRho(meandens) , fg_fourAmp(false) , fg_massDens(false)
378{
379}
380
381// To the computation job
382void MassDist2D::Compute()
383{
384 ComputeFourierAmp();
385 ComputeMassDens();
386}
387
388// Generate mass field Fourier Coefficient
389void MassDist2D::ComputeFourierAmp()
390{
391 if (fg_fourAmp) return; // job already done
392 // We generate a random gaussian real field
393 double sigma = 1.;
394// The following line fills the array by gaussian random numbers
395//--Replaced-- massDens = RandomSequence(RandomSequence::Gaussian, 0., sigma);
396// Can be replaced by
397 DR48RandGen rg;
398 for(sa_size_t ir=0; ir<massDens.NRows(); ir++) {
399 for(sa_size_t jc=0; jc<massDens.NCols(); jc++) {
400 massDens(ir, jc) = rg.Gaussian(sigma);
401 }
402 }
403// --- End of random filling
404
405 // Compute fourier transform of the random gaussian field -> white noise
406 FFTWServer ffts(true);
407 ffts.setNormalize(true);
408 ffts.FFTForward(massDens, fourAmp);
409
410 // fourAmp represent 2-D fourier transform of a real input array.
411 // The second half of the array along Y (matrix rows) contain
412 // negative frequencies
413// double fnorm = 1./sqrt(2.*fourAmp.Size());
414// PUT smaller value for fnorm and check number of zeros
415 double fnorm = 1.;
416 // sa_size_t is large integer type
417 for(sa_size_t ky=0; ky<fourAmp.NRows(); ky++) {
418 double kyy = ky;
419 if (ky > fourAmp.NRows()/2) kyy = fourAmp.NRows()-ky; // negative frequencies
420 for(sa_size_t kx=0; kx<fourAmp.NCols(); kx++) {
421 double wk = sqrt((double)(kx*kx+kyy*kyy));
422 double amp = pkSpec(wk)*fnorm;
423 fourAmp(ky, kx) *= amp; // renormalize fourier coeff using
424 }
425 }
426 fg_fourAmp = true;
427 cout << " MassDist2D::ComputeFourierAmp() done ..." << endl;
428}
429
430// Compute mass field from its Fourier Coefficient
431void MassDist2D::ComputeMassDens()
432{
433 if (fg_massDens) return; // job already done
434 if (!fg_fourAmp) ComputeFourierAmp(); // Check fourier amp generation
435
436// Backward fourier transform of the fourierAmp array
437 FFTWServer ffts(true);
438 ffts.setNormalize(true);
439 ffts.FFTBackward(fourAmp, massDens, true);
440// We consider that massDens represents delta rho/rho
441// rho = (delta rho/rho + 1) * MeanDensity
442 massDens += 1.;
443// We remove negative values
444 sa_size_t npbz = 0;
445 for (sa_size_t i=0; i<massDens.NRows(); i++)
446 for (sa_size_t j=0; j<massDens.NCols(); j++)
447 if (massDens(i,j) < 0.) { npbz++; massDens(i,j) = 0.; }
448 massDens *= meanRho;
449 cout << " MassDist2D::ComputeMassDens() done NbNeg=" << npbz << " / NPix=" << massDens.Size() << endl;
450}
451
452// Compute power spectrum as a function of wave number k
453// Output : power spectrum (profile histogram)
454HProf MassDist2D::ReconstructPk(int nbin)
455{
456 // The second half of the array along Y (matrix rows) contain
457 // negative frequencies
458 int nbh = sqrt(2.0)*fourAmp.NCols();
459 // The profile histogram will contain the mean value of FFT amplitude
460 // as a function of wave-number k = sqrt((double)(kx*kx+ky*ky))
461 if (nbin < 1) nbin = nbh/2;
462 HProf hp(-0.5, nbh-0.5, nbin);
463 hp.SetErrOpt(false);
464
465 for(int ky=0; ky<fourAmp.NRows(); ky++) {
466 double kyy = ky;
467 if (ky > fourAmp.NRows()/2) kyy = fourAmp.NRows()-ky; // negative frequencies
468 for(int kx=0; kx<fourAmp.NCols(); kx++) {
469 double wk = sqrt((double)(kx*kx+kyy*kyy));
470 complex<r_8> za = fourAmp(ky, kx);
471 double amp = sqrt(za.real()*za.real()+za.imag()*za.imag());
472 hp.Add(wk, amp);
473 }
474 }
475 return hp;
476}
477
Note: See TracBrowser for help on using the repository browser.