source: trunk/MagicSoft/Simulation/Detector/Starfield/starfield.cxx@ 5110

Last change on this file since 5110 was 5110, checked in by moralejo, 20 years ago
Commited to CVS all changes to adapt headers to current C++ syntaxis
File size: 10.3 KB
Line 
1/////////////////////////////////////////////////////////////////////////
2// Starfield Generator
3//
4// (c) 2000 D. Petry
5//
6// 15/09/2004, A. Moralejo:
7// - Adapted to gcc 3.2 under root 3.05.07
8// - Fixed algorithm to calculate director cosines of incident photons.
9// Former algorithm resulted in mirrored images on the camera (which we
10// must not have after reflection on a parabollic dish).
11//
12/////////////////////////////////////////////////////////////////////////
13
14
15#include "starfield.h"
16
17#define PROGRAMID "$Id: starfield.cxx,v 1.4 2004-09-17 17:36:25 moralejo Exp $"
18
19/////////////////////////////////////////////////////////////////////////
20
21int main(int argc, char **argv)
22{
23
24 parameters pars;
25 star stars[iMAXSTARS];
26 photon *photons;
27
28 ifstream in;
29 FILE *catfile;
30 char parfilename[160];
31 char catfilename[160];
32
33
34 int i, j, k, numstars, subnumstars, starnumber, totalnumphot, photinside;
35 int totalphotinside, idum;
36 int istart_ra_h, iend_ra_h;
37 int nph[4]; // numbers of photons in the four wavebands
38 float lmin_nm[4] = {ULMIN_nm, BLMIN_nm, VLMIN_nm, RLMIN_nm}; // wave band definitions
39 float lmax_nm[4] = {ULMAX_nm, BLMAX_nm, VLMAX_nm, RLMAX_nm};
40 float theta_rad, costheta, sintheta, phi_rad, randtime, lambda_nm, xdum_m, ydum_m;
41 float cosa, cosA, sinA;
42 float angdist;
43
44 //welcome
45
46 cout << "This is STARFIELD. (c) 2000 D. Petry\n";
47 cout << PROGRAMID << "\n";
48
49 // check command line arguments
50
51 if(argc == 1){
52 sprintf(parfilename, "starfield.par");
53 }
54 else{ // a filename was given
55 sprintf(parfilename, "%s", argv[1]);
56 }
57
58 // read parameter file
59
60 in.open(parfilename, ios::in); // open the parameter file
61
62 if(!in){
63 cout << "Failed to open " << parfilename << "\n"
64 << "Value of stream \"in\" was " << in << "\n";
65 cout << "\nThere shoud be a parameter file "<< parfilename
66 <<" in the working directory with the following format:\n-----\n";
67 pars.usage(&cout);
68 cout << "-----\nExiting.\n";
69 exit(1);
70 }
71
72 cout << "Opened " << parfilename << " for reading ...\n";
73
74 if( !(pars.readparameters(&in)) ){ // read not OK?
75 if(!in.eof()){ // was the error not due to EOF?
76 cout << "Error: rdstate = " << in.rdstate() << "\n";
77 }
78 else{
79 cout << "Error: premature EOF in parameter file.\n";
80 }
81 exit(1);
82 }
83
84 in.close();
85
86 // Allocate memory for photons
87
88 photons=new photon[iMAXPHOT];
89
90
91 // prepare loop over star catalog files
92
93 cout << "SKY2000 - Master Star Catalog - Star Catalog Database, Version 2\n";
94 cout << "Sande C.B., Warren W.H.Jr., Tracewell D.A., Home A.T., Miller A.C.\n";
95 cout << "<Goddard Space Flight Center, Flight Dynamics Division (1998)>\n";
96
97 angdist = fmod( (float) (pars.catalog_fov_deg/cos( pars.ct_dec_rad )),
98 (float) 360.);
99
100 if(angdist > 180.){ // too near to the pole, have to loop over all files
101
102 istart_ra_h = 0;
103 iend_ra_h = 23;
104
105 }
106 else{ // can loop over selected files only
107
108 istart_ra_h = (int) (pars.ct_ra_h - angdist / 360. * 24.) - 1;
109 iend_ra_h = (int) (pars.ct_ra_h + angdist / 360. * 24. ) + 1;
110
111 }
112
113 //read catalog
114
115 i = 0;
116 for (j = istart_ra_h; j <= iend_ra_h; j++){
117
118 subnumstars = 0;
119
120 if ( j < 0){
121 idum = j + 24;
122 }
123 else if ( j > 23 ){
124 idum = j - 24;
125 }
126 else {
127 idum = j;
128 }
129
130 sprintf(catfilename, "%s/sky%02d.dat", pars.datapath, idum);
131
132 if((catfile = fopen(catfilename, "r")) == NULL){ // open the star catalog
133 cout << "Failed to open " << catfilename << "\n";
134 exit(1);
135 }
136 cout << "Opened file " << catfilename << " for reading ...\n";
137
138 while( stars[i].readstar(catfile, pars.verbose) ){ // read next star OK
139
140 angdist = acos( cos( pars.ct_dec_rad ) * cos( stars[i].dec_rad ) *
141 cos( stars[i].ra_rad - pars.ct_ra_rad ) +
142 sin( pars.ct_dec_rad ) * sin( stars[i].dec_rad ) );
143
144 if( angdist < pars.catalog_fov_deg / 180. * PI ){ // star in Field Of View?
145
146 stars[i].calcmissingmags(pars.verbose);
147 if (pars.verbose) stars[i].printstar();
148
149 if( stars[i].umag > -100. ){
150 i++; // accept star
151 subnumstars++;
152 }
153 else{
154 cout << "Star rejected.\n";
155 }
156
157 if( i > iMAXSTARS ){
158 i--;
159 cout << "Error: Star memory full. Accepted " << i << " stars.\n";
160 break;
161 }
162 }
163 }
164 if( feof(catfile) ){ // was EOF reached?
165 cout << "EOF reached; accepted "<< subnumstars << " stars from this segment.\n";
166 }
167 if( ferror(catfile) ){ // did an error occur?
168 cout << "Error while reading catalog file.\n";
169 exit(1);
170 }
171 fclose(catfile);
172 if(i == iMAXSTARS){
173 break;
174 }
175 }
176
177 cout << "Accepted "<< i << " stars in total.\n";
178 numstars = i;
179
180 // loop over all photons from all stars, filling their fields
181
182 totalnumphot=0;
183
184 totalphotinside=0;
185
186 for(i=0; i<numstars;i++){
187
188 starnumber=stars[i].icatnum;
189
190 // calculate director cosines (see Montenbruck & Pfleger, 1989, p. 196)
191
192 costheta = cos( pars.ct_dec_rad ) * cos( stars[i].dec_rad ) *
193 cos( stars[i].ra_rad - pars.ct_ra_rad ) +
194 sin( pars.ct_dec_rad ) * sin( stars[i].dec_rad );
195
196 if(costheta == 0.){
197 cout << "Star number " << i << " (catalog number " << stars[i].icatnum <<
198 ") seems to be at 90 degrees distance from optical axis.\n ... will ignore it.";
199 continue;
200 }
201
202 sintheta = sqrt(1.-costheta*costheta);
203
204 //
205 // A. Moralejo, 15/09/2004
206 // We want the director cosines of the down-going versors along the photon
207 // incident directions. This is what the Reflector program expects (also from the
208 // normal Corsika output). We have used simple spherical trigonometry to obtain
209 // the formulae.
210 //
211
212 // "cosa" is the cosine of the angle "a" between the star direction and the direction
213 // defined by declination = 0 and right ascension = ct_ra. "a" is one of the sides of
214 // a spherical triangle. It is a quantity needed for the calculations.
215
216 cosa = cos( stars[i].ra_rad - pars.ct_ra_rad ) * cos( stars[i].dec_rad );
217
218 // cosA is the angle between the great circle of constant right ascension = ct_ra and
219 // the great circle defined by the star direction and the telescope direction. "A" would
220 // be the angle opposite to the side "a" of a spherical triangle (see above)
221
222 cosA = (cosa - costheta*cos(pars.ct_dec_rad)) / (sintheta*sin(pars.ct_dec_rad));
223
224 // We now want A to be defined in the 0 - 2pi range, so that it becomes the azimuth angle
225 // of the star in a system defined by the telescope direction. "A" will be defined between
226 // 0 and pi if sin (star_ra - ct_ra) > 0, and between pi and 2 pi otherwise.
227
228 sinA = sqrt (1.-cosA*cosA);
229 if ( sin(stars[i].ra_rad - pars.ct_ra_rad ) < 0. )
230 sinA *= -1.;
231
232 stars[i].u = -1. * sintheta * cosA;
233 stars[i].v = -1. * sintheta * sinA;
234
235
236 // Old implementation, commented out 15/09/2004:
237 //
238 // This produced director cosines which, when fed to reflector, makes on the camera plane
239 // a mirror-inverted image of the FOV (with respect to what one would see "by eye"). That
240 // is NOT what we want! After reflection on the parabollic mirror, the image on the camera
241 // is NOT mirrored, but just rotated by 180 degree. The new implementation above produces
242 // the correct FOV (tested with Reflector 0.6)
243 //
244 // stars[i].u = -1. * cos( stars[i].dec_rad ) * sin( stars[i].ra_rad - pars.ct_ra_rad ) / costheta;
245 // stars[i].v = -1. * ( sin( pars.ct_dec_rad ) * cos( stars[i].dec_rad ) *
246 // cos( stars[i].ra_rad - pars.ct_ra_rad ) -
247 // cos( pars.ct_dec_rad ) * sin( stars[i].dec_rad )
248 // ) / costheta;
249
250
251 // calculate the "zenith angle" theta and "azimuth" phi of the star assuming
252 // the telecope points at the zenith
253 // take into account the ambiguity of acos()
254
255 theta_rad = acos(costheta);
256
257 if( stars[i].v >= 0. ){
258 phi_rad = acos(stars[i].u);
259 }
260 else{
261 phi_rad = 2.*PI - acos(stars[i].u);
262 }
263
264 // calculate number of photons
265
266 // mag_nphot() translates the star magnitude into number of photons,
267 // using the expression log(flux)=-0.4*m-22.42 for each waveband
268 // the resulting numbers ar stored in the array nph
269
270 stars[i].mag_nphot(nph, pars.integtime_s, pars.mirr_radius_m, pars.verbose);
271
272 // loop over all photons
273
274 photinside=0;
275
276 for(k=0; k < 4; k++){ // loop over wavebands
277
278 for(j=0; j<nph[k]; j++){ // loop over photons of this waveband
279
280 // Check if we have overflowed the alllowed ph number
281
282 if(totalphotinside >= iMAXPHOT){
283 cout << "Warning: photon memory full. Can only store " << iMAXPHOT << " photons.\n";
284 break;
285 //exit(1);
286 }
287
288 // for every photon, a pair of uniform random x,y coordinates ( x*x+y*y<300 ) is generated
289 // and a uniform random arrival time inside a time window given by the integration time.
290
291 xdum_m=rand_coord(pars.mirr_radius_m);
292 ydum_m=rand_coord(pars.mirr_radius_m);
293
294 if((xdum_m*xdum_m+ydum_m*ydum_m)<pars.mirr_radius_m*pars.mirr_radius_m){
295
296 randtime = rand_time(pars.integtime_s);
297 lambda_nm = rand_lambda(lmin_nm[k], lmax_nm[k]);
298
299 //fill the photon fields by using the member functions defined in photon.hxx
300
301 photons[totalphotinside].starnum = starnumber;
302 photons[totalphotinside].arrtime_sec = randtime;
303 photons[totalphotinside].x_m = xdum_m;
304 photons[totalphotinside].y_m = ydum_m;
305 photons[totalphotinside].u = stars[i].u;
306 photons[totalphotinside].v = stars[i].v;
307 photons[totalphotinside].lambda_nm = lambda_nm;
308
309 if(pars.verbose > 2)
310 cout << "PH " << starnumber << " " << randtime << " " << xdum_m << " "
311 << ydum_m << " " << stars[i].u << " " << stars[i].v << " " << lambda_nm
312 << "\n";
313
314 photinside++;
315
316 totalphotinside++;
317
318 totalnumphot++;
319
320 }
321 else{
322
323 totalnumphot++;
324 continue;
325
326 } // end if
327
328 } // end photon loop
329 } // end waveband loop
330
331 stars[i].numphot = photinside;
332 //if (i>81) break;
333 if (pars.verbose) cout<<"Star number= "<<i<< " (catalog number " <<
334 starnumber << ") Number of photons accepted = "<< photinside<<endl;
335
336 } // end star loop
337
338 cout << "Total number of photons accepted = " << totalphotinside << "\n";
339
340 convertcorsika(
341 ((int)pars.ct_ra_h*10)*1000 + (int)(fabs(pars.ct_dec_deg)*10), // the file id
342 totalphotinside, photons, pars.integtime_s, pars.verbose, pars.output_file);
343
344 return 0;
345
346} // end main
Note: See TracBrowser for help on using the repository browser.