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

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