1 /*
2   stars.c
3   sky_model
5   Created by Jayant Murthy on 07/10/12.
6   Copyright (c) 2012 Jayant Murthy. All rights reserved.
7 */
9 #include "sky_model.h"
10 /*Function to read single line from current position in stars file*/
12 int HIP_READ_LINE(FILE *star_file, struct STARS *line)
13 {
14     int i, tst;
15     char hip_line[HIP_MAIN_REC_LEN], *token, *read_res, s_tmp[13], s_tmp1[13];
16     double  gl, gb;
18     read_res = fgets(hip_line, HIP_MAIN_REC_LEN, star_file);/*Read first bracket*/
19     if (read_res == NULL)
20         return(EXIT_FAILURE);
21     token = strtok(hip_line, HIP_DELIM); /*Set up tokens*/
22     for (i = 1; i < 77; ++i) {
23         token = strtok(NULL, HIP_DELIM); /*read token*/
24         switch (i) {
25             case 1:  line->HIP_NO   = atoi(token);
26                 break;
27             case 8:  line->ra       = atof(token);
28                 break;
29             case 9:  line->dec      = atof(token);
30                 break;
31             case 11: if (atof(token) > 0)
32                 line->distance = 1000./atof(token);
33             else line->distance = 1.e6;
34                 break;
35             case 32: line->B_mag    = atof(token);
36                 break;
37             case 34: line->V_mag    = atof(token);
38                 break;
39             case 71: line->HD_NO    = atoi(token);
40                 break;
41             case 76: strcpy(s_tmp, token);
42                 sscanf(s_tmp, "%s", s_tmp1);
43                 strcpy(line->sp_type, s_tmp1);
44                 break;
45         }/*End switch*/
46         tst = CONV_EQ_TO_GAL(line->ra, line->dec, &gl, &gb);
47         line->gl = gl;
48         line->gb = gb;
50         line->x = cos(DEGRAD(line->gl))*cos(DEGRAD(line->gb))*line->distance;
51         line->y = sin(DEGRAD(line->gl))*cos(DEGRAD(line->gb))*line->distance;
52         line->z = sin(DEGRAD(line->gb))*line->distance;
53     }/*End for*/
54     return(0);
55 }/*End READ_LINE*/
56 /*********************************************************************/
57 int READ_CASTELLI_SPECTRA(char *spec_dir, struct SPECTRA
58                           *stellar_spectra)
59 {
60     int status = 0, anynull;
61     fitsfile *fptr;
62     char filename[MAX_FILE_LENGTH];
63     int i;
64     int temper[N_CASTELLI_MODELS], gindex[N_CASTELLI_MODELS];
65     float nullval;
66     char stemper[6];
68     /*Lookup table for temperatures and g*/
69     for (i = 0; i <= 37; ++i)
70         temper[i] = 50000 - i*1000;
71     for (i = 38; i < 76; ++i)
72         temper[i] = 13000 - (i - 37)*250;
73     for (i = 0; i <= 4; ++i)
74         gindex[i] = 12;
75     for (i = 5; i <= 10; ++i)
76         gindex[i] = 11;
77     for (i = 11; i <= 63; ++i)
78         gindex[i] = 10;
79     for (i = 64; i <= 75; ++i)
80         gindex[i] = 11;
82     /*Read stellar spectra*/
83     for (i = 0; i < N_CASTELLI_MODELS; ++i) {
84         strcpy(filename, spec_dir);
85         strcat(filename, "/ckp00_");
86         sprintf(stemper, "%i", temper[i]);
87         strcat(filename, stemper);
88         strcat(filename, ".fits");
89         sprintf(stellar_spectra[i].filename, "%i", temper[i]);
90         fits_open_file(&fptr, filename, READONLY, &status);
91         fits_movabs_hdu(fptr, 2, NULL, &status);
92         fits_read_col(fptr, TFLOAT, gindex[i], 1, 1, N_CASTELLI_SPECTRA,
93                       &nullval, stellar_spectra[i].spectrum, &anynull,
94                       &status);
95         fits_read_col(fptr, TFLOAT, 1, 1, 1, N_CASTELLI_SPECTRA,
96                       &nullval, stellar_spectra[i].wavelength, &anynull,
97                       &status);
99         fits_close_file(fptr, &status);
100     }
102     return(EXIT_SUCCESS);
105 int GET_STAR_TEMP(struct STARS *hipline)
107     char sptype[10];
108     char *str=sptype;
110     if (strncmp(hipline->sp_type, "sd", 2) == 0) {
111         strcpy(sptype, hipline->sp_type);
112         str = str + 2;
113         strcpy(hipline->sp_type, str);
114     }
115     if (strncmp(hipline->sp_type, "O3", 2) == 0) {
116         hipline->temperature = 5;
117     }
118     else if (strncmp(hipline->sp_type, "O4", 2) == 0) {
119         hipline->temperature = 7;
120     }
121     else if (strncmp(hipline->sp_type, "O5", 2) == 0) {
122         hipline->temperature = 10;
123     }
124     else if (strncmp(hipline->sp_type, "O6", 2) == 0) {
125         hipline->temperature = 11;
126     }
127     else if (strncmp(hipline->sp_type, "O7", 2) == 0) {
128         hipline->temperature = 13;
129     }
130     else if (strncmp(hipline->sp_type, "O8", 2) == 0) {
131         hipline->temperature = 15;
132     }
133     else if (strncmp(hipline->sp_type, "O9", 2) == 0) {
134         hipline->temperature = 18;
135     }
136     else if (strncmp(hipline->sp_type, "B0", 2) == 0) {
137         hipline->temperature = 20;
138     }
139     else if (strncmp(hipline->sp_type, "B1", 2) == 0) {
140         hipline->temperature = 25;
141     }
142     else if (strncmp(hipline->sp_type, "B2", 2) == 0) {
143         hipline->temperature = 28;
144     }
145     else if (strncmp(hipline->sp_type, "B3", 2) == 0) {
146         hipline->temperature = 31;
147     }
148     else if (strncmp(hipline->sp_type, "B4", 2) == 0) {
149         hipline->temperature = 33;
150     }
151     else if (strncmp(hipline->sp_type, "B5", 2) == 0) {
152         hipline->temperature = 35;
153     }
154     else if (strncmp(hipline->sp_type, "B6", 2) == 0) {
155         hipline->temperature = 36;
156     }
157     else if (strncmp(hipline->sp_type, "B7", 2) == 0) {
158         hipline->temperature = 37;
159     }
160     else if (strncmp(hipline->sp_type, "B8", 2) == 0) {
161         hipline->temperature = 41;
162     }
163     else if (strncmp(hipline->sp_type, "B9", 2) == 0) {
164         hipline->temperature = 49;
165     }
166     else if (strncmp(hipline->sp_type, "A0", 2) == 0) {
167         hipline->temperature = 51;
168     }
169     else if (strncmp(hipline->sp_type, "A1", 2) == 0) {
170         hipline->temperature = 52;
171     }
172     else if (strncmp(hipline->sp_type, "A2", 2) == 0) {
173         hipline->temperature = 53;
174     }
175     else if (strncmp(hipline->sp_type, "A3", 2) == 0) {
176         hipline->temperature = 56;
177     }
178     else if (strncmp(hipline->sp_type, "A4", 2) == 0) {
179         hipline->temperature = 56;
180     }
181     else if (strncmp(hipline->sp_type, "A5", 2) == 0) {
182         hipline->temperature = 56;
183     }
184     else if (strncmp(hipline->sp_type, "A6", 2) == 0) {
185         hipline->temperature = 57;
186     }
187     else if (strncmp(hipline->sp_type, "A7", 2) == 0) {
188         hipline->temperature = 58;
189     }
190     else if (strncmp(hipline->sp_type, "A8", 2) == 0) {
191         hipline->temperature = 59;
192     }
193     else if (strncmp(hipline->sp_type, "A9", 2) == 0) {
194         hipline->temperature = 60;
195     }
196     else if (strncmp(hipline->sp_type, "F0", 2) == 0) {
197         hipline->temperature = 60;
198     }
199     else if (strncmp(hipline->sp_type, "F1", 2) == 0) {
200         hipline->temperature = 63;
201     }
202     else if (strncmp(hipline->sp_type, "F2", 2) == 0) {
203         hipline->temperature = 61;
204     }
205     else if (strncmp(hipline->sp_type, "F3", 2) == 0) {
206         hipline->temperature = 62;
207     }
208     else if (strncmp(hipline->sp_type, "F4", 2) == 0) {
209         hipline->temperature = 62;
210     }
211     else if (strncmp(hipline->sp_type, "F5", 2) == 0) {
212         hipline->temperature = 63;
213     }
214     else if (strncmp(hipline->sp_type, "F6", 2) == 0) {
215         hipline->temperature = 63;
216     }
217     else if (strncmp(hipline->sp_type, "F7", 2) == 0) {
218         hipline->temperature = 63;
219     }
220     else if (strncmp(hipline->sp_type, "F8", 2) == 0) {
221         hipline->temperature = 64;
222     }
223     else if (strncmp(hipline->sp_type, "F9", 2) == 0) {
224         hipline->temperature = 65;
225     }
226     else if (strncmp(hipline->sp_type, "G0", 2) == 0) {
227         hipline->temperature = 65;
228     }
229     else if (strncmp(hipline->sp_type, "G1", 2) == 0) {
230         hipline->temperature = 66;
231     }
232     else if (strncmp(hipline->sp_type, "G2", 2) == 0) {
233         hipline->temperature = 66;
234     }
235     else if (strncmp(hipline->sp_type, "G3", 2) == 0) {
236         hipline->temperature = 66;
237     }
238     else if (strncmp(hipline->sp_type, "G4", 2) == 0) {
239         hipline->temperature = 66;
240     }
241     else if (strncmp(hipline->sp_type, "G5", 2) == 0) {
242         hipline->temperature = 66;
243     }
244     else if (strncmp(hipline->sp_type, "G6", 2) == 0) {
245         hipline->temperature = 66;
246     }
247     else if (strncmp(hipline->sp_type, "G7", 2) == 0) {
248         hipline->temperature = 67;
249     }
250     else if (strncmp(hipline->sp_type, "G8", 2) == 0) {
251         hipline->temperature = 67;
252     }
253     else if (strncmp(hipline->sp_type, "G9", 2) == 0) {
254         hipline->temperature = 67;
255     }
256     else if (strncmp(hipline->sp_type, "K0", 2) == 0) {
257         hipline->temperature = 68;
258     }
259     else if (strncmp(hipline->sp_type, "K1", 2) == 0) {
260         hipline->temperature = 69;
261     }
262     else if (strncmp(hipline->sp_type, "K2", 2) == 0) {
263         hipline->temperature = 70;
264     }
265     else if (strncmp(hipline->sp_type, "K3", 2) == 0) {
266         hipline->temperature = 70;
267     }
268     else if (strncmp(hipline->sp_type, "K4", 2) == 0) {
269         hipline->temperature = 71;
270     }
271     else if (strncmp(hipline->sp_type, "K5", 2) == 0) {
272         hipline->temperature = 72;
273     }
274     else if (strncmp(hipline->sp_type, "K6", 2) == 0) {
275         hipline->temperature = 72;
276     }
277     else if (strncmp(hipline->sp_type, "K7", 2) == 0) {
278         hipline->temperature = 73;
279     }
280     else if (strncmp(hipline->sp_type, "K8", 2) == 0) {
281         hipline->temperature = 73;
282     }
283     else if (strncmp(hipline->sp_type, "K9", 2) == 0) {
284         hipline->temperature = 73;
285     }
286     else if (strncmp(hipline->sp_type, "M0", 2) == 0) {
287         hipline->temperature = 74;
288     }
289     else if (strncmp(hipline->sp_type, "M1", 2) == 0) {
290         hipline->temperature = 74;
291     }
292     else if (strncmp(hipline->sp_type, "M2", 2) == 0) {
293         hipline->temperature = 75;
294     }
295     else if (strncmp(hipline->sp_type, "M3", 2) == 0) {
296         hipline->temperature = 75;
297     }
298     else if (strncmp(hipline->sp_type, "M4", 2) == 0) {
299         hipline->temperature = 75;
300     }
301     else if (strncmp(hipline->sp_type, "M5", 2) == 0) {
302         hipline->temperature = 75;
303     }
304     else if (strncmp(hipline->sp_type, "M6", 2) == 0) {
305         hipline->temperature = 75;
306     }
307     else if (strncmp(hipline->sp_type, "M7", 2) == 0) {
308         hipline->temperature = 75;
309     }
310     else if (strncmp(hipline->sp_type, "M8", 2) == 0) {
311         hipline->temperature = 75;
312     }
313     else if (strncmp(hipline->sp_type, "M9", 2) == 0) {
314         hipline->temperature = 75;
315     }
316     else if (strncmp(hipline->sp_type, "O", 1) == 0) {
317         hipline->temperature = 13;
318     }
319     else if (strncmp(hipline->sp_type, "B", 1) == 0) {
320         hipline->temperature = 35;
321     }
322     else if (strncmp(hipline->sp_type, "M", 1) == 0) {
323         hipline->temperature = 75;
324     }
325     else if (strncmp(hipline->sp_type, "C", 1) == 0) {
326         hipline->temperature = 75;
327     }
328     else if (strncmp(hipline->sp_type, "A", 1) == 0) {
329         hipline->temperature = 56;
330     }
331     else if (strncmp(hipline->sp_type, "R", 1) == 0) {
332         hipline->temperature = 75;
333     }
334     else if (strncmp(hipline->sp_type, "G", 1) == 0) {
335         hipline->temperature = 66;
336     }
337     else if (strncmp(hipline->sp_type, "W", 1) == 0) {
338         hipline->temperature = 35;
339     }
340     else if (strncmp(hipline->sp_type, "K", 1) == 0) {
341         hipline->temperature = 72;
342     }
343     else if (strncmp(hipline->sp_type, "N", 1) == 0) {
344         hipline->temperature = 72;
345     }
346     else if (strncmp(hipline->sp_type, "S", 1) == 0) {
347         hipline->temperature = 72;
348     }
349     else if (strncmp(hipline->sp_type, "F", 1) == 0) {
350         hipline->temperature = 63;
351     }
352     else if (strncmp(hipline->sp_type, "DA", 2) == 0) {
353         hipline->temperature = 35;
354     }
355     /*Special Cases*/
356     else {
357         printf("Unimplemented spectral type: %s\n", hipline->sp_type);
358         hipline->temperature = 66;
359     }
360     return (EXIT_SUCCESS);
362 /**************************************************************************/
364 int READ_CROSS_SEC(struct SPECTRA line, struct INP_PAR file_list)
366     FILE    *fp;
367     float   wave, cross_sec, t1, t2, t3;
368     char    str[132], *read_res;
369     int i = 0, j;
370     struct SPECTRA temp;
372     /*  The following steps are to find out the Absorption CrossSection from
373      the cross-section file corresponding to our wavelength of interest. This
374      file was taken directly from Draine's page:
375      ftp://ftp.astro.princeton.edu/draine/dust/mix/kext_albedo_WD_MW_3.1_60_D03.all
376      */
378     if ((fp = fopen(file_list.sigma_file, "r")) == NULL){
379         printf("Error opening Cross Section File:::\n");
380         exit(EXIT_FAILURE);
381     }
382     temp.spectrum = malloc(sizeof(float) * MAX_SPEC_ELEM);
383     temp.wavelength = malloc(sizeof(float) * MAX_SPEC_ELEM);
385     /*Skip all lines until we reach -*/
386     strcpy(str, "          ");
387     while ((strncmp("-", str, 1) != 0)) {
388         read_res = fgets(str, 132, fp);
389     }
390     /*Find the cross section at the nearest wavelength*/
391     i = 0;
392     while (feof(fp) == 0){
393         read_res = fgets(str, 132, fp);/*Read first bracket*/
394         sscanf(str, "%f %f %f %e %e",
395                &wave, &t1, &t2, &cross_sec, &t3);
396         temp.wavelength[i] = wave*10000;/*convert to Å*/
397         temp.spectrum[i]   = cross_sec;
398         i = i + 1;
399     }
400     /*We have to reverse the wavelengths because of Draine's format*/
401     for (j=0; j < i; ++j) {
402         line.wavelength[j] = temp.wavelength[i-j-1];
403         line.spectrum[j] = temp.spectrum[i-j-1];
404     }
405     fclose(fp);
406     free(temp.spectrum);
407     free(temp.wavelength);
408     return (i);
410 /**************************************************************************/
412 float CALC_FLUX(struct STARS *hipstars, struct INP_PAR files,
413                 struct SPECTRA cross_sec,
414                 struct SPECTRA *stellar_spectra,
415                 struct SPECTRA filters,
416                 float gl, float gb, float dist, float lambda,
417                 float ave_sigma)
419     int istars, windex, sindex, cindex;
420     float x, y, z;
421     float dstarsq, tau, flux = 0;
422     struct SPECTRA star_flux;
424     /*Distance from star to point of interest*/
425     x = cos(DEGRAD(gl))*cos(DEGRAD(gb))*dist;
426     y = sin(DEGRAD(gl))*cos(DEGRAD(gb))*dist;
427     z = sin(DEGRAD(gb))*dist;
429     star_flux.wavelength = (float *) malloc(sizeof(float) * N_CASTELLI_SPECTRA);
430     star_flux.spectrum   = (float *) malloc(sizeof(float) * N_CASTELLI_SPECTRA);
431     star_flux.nelements  = N_CASTELLI_SPECTRA;
433     istars = 0;
434     dstarsq = pow((hipstars[istars].x - x),2) +
435     pow((hipstars[istars].y - y),2) +
436     pow((hipstars[istars].z - z),2);
437     sindex = hipstars[istars].temperature;
438     cindex = 0;
439     for (windex = 0; windex < star_flux.nelements; ++windex) {
440         star_flux.wavelength[windex] = stellar_spectra[sindex].wavelength[windex];
441         while ((cross_sec.wavelength[cindex] < star_flux.wavelength[windex])
442                && (cindex < cross_sec.nelements))
443             ++cindex;
444         tau = cross_sec.spectrum[cindex]*sqrt(dstarsq)*ave_sigma*PCinCM(1.);
445         star_flux.spectrum[windex] =
446         stellar_spectra[sindex].spectrum[windex] * expf(-tau) *
447         hipstars[istars].scale/dstarsq*
448         1e9*stellar_spectra[sindex].wavelength[windex]/6.626/3.;
449     }
450     flux = CALC_SCALE_FACTOR(filters, star_flux);
451     return(flux);
454 int GET_SCALE_FACTOR(struct STARS *hipstars,
455                      struct SPECTRA *stellar_spectra)
457     float scale;
458     int bindex, vindex, sindex, doprint;
459     float ebv, b_mag, v_mag, bflux, vflux, bv;
461     if (hipstars->V_mag == 0){
462         hipstars->scale = 0;/* A few stars are bad*/
463     } else {
464         sindex = hipstars->temperature;
465         /*We scale at 4400 and 5500 Å*/
466         vindex = 0;
467         while (stellar_spectra[sindex].wavelength[vindex] < 5500)
468             ++vindex;
469         bindex = 0;
470         while (stellar_spectra[sindex].wavelength[bindex] < 4400)
471             ++bindex;
473         bflux = stellar_spectra[sindex].spectrum[bindex];
474         vflux = stellar_spectra[sindex].spectrum[vindex];
475         b_mag = -2.5 * log10(bflux/6.61);/*Convert flux into magnitudes*/
476         v_mag = -2.5 * log10(vflux/3.64);
477         bv = hipstars->B_mag - hipstars->V_mag;
478         ebv = bv - (b_mag - v_mag);
479         if (ebv < 0) ebv = 0;
480         hipstars->ebv = ebv;
481         /*Scale factor to convert model to Earth with no extinction*/
482         scale = 3.64e-9*pow(10, -0.4 * (hipstars->V_mag - 3.2*ebv))/
483         vflux;
484         /*Scale to a distance of 1 pc*/
485         hipstars->scale = scale*hipstars->distance*hipstars->distance;
487         doprint = 0;
488         if (doprint > 0)
489             printf("%li %s %s %i %10.3e %10.3e\n", hipstars->HIP_NO, hipstars->sp_type,
490                    stellar_spectra[sindex].filename, sindex, bflux, vflux);
491     }
493     return(EXIT_SUCCESS);
496 int READ_HIPPARCOS_CAT(struct INP_PAR inp_par, struct SPECTRA *stellar_spectra,
497                        struct STARS *hipstars, struct SPECTRA filter)
499     FILE *hipfile_ptr=NULL;
500     int i, tst;
501     struct STARS hipline;
502     struct SPECTRA cross_sec;
504     tst = READ_CASTELLI_SPECTRA(inp_par.castelli_file, stellar_spectra);
505     cross_sec.spectrum = malloc(sizeof(float) * MAX_SPEC_ELEM);
506     cross_sec.wavelength = malloc(sizeof(float) * MAX_SPEC_ELEM);
507     cross_sec.nelements = READ_CROSS_SEC(cross_sec, inp_par);
509     hipfile_ptr = fopen(inp_par.hipparcos_file, "r");
510     if (hipfile_ptr == NULL){
511         printf("%s %s\n", "Can't find stellar file:", inp_par.hipparcos_file);
512         exit(EXIT_FAILURE);
513     }
514     i = 0;
515     while (feof(hipfile_ptr) == 0) {
516         tst   = HIP_READ_LINE(hipfile_ptr, &hipline);
517         tst = GET_STAR_TEMP(&hipline);
518         tst = GET_SCALE_FACTOR(&hipline, stellar_spectra);
519         hipline.flux_at_earth = CALC_FLUX(&hipline, inp_par, cross_sec, stellar_spectra, filter,
520                                           0, 0, 0, 2300, 1);
521         hipstars[i] = hipline;
522         ++i;
523     }
524     hipstars[0].nstars = i-1;
525     fclose(hipfile_ptr);
526     return (EXIT_SUCCESS);