MUSE Pipeline Reference Manual  1.0.2
muse_lsf_fwhm.c
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set sw=2 sts=2 et cin: */
3 /*
4  * This file is part of the MUSE Instrument Pipeline
5  * Copyright (C) 2007-2014 European Southern Observatory
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  */
21 
22 #include <muse.h>
23 #include <string.h>
24 #include <strings.h>
25 
26 /*----------------------------------------------------------------------------*/
60 /*----------------------------------------------------------------------------*/
61 
64 #define PRINT_USAGE(rc) \
65  fprintf(stderr, "Usage: %s [ -v ] [ -c IFUNUM ] [ -l LAMBDA ] LSF_PROFILE\n",\
66  argv[0]); \
67  cpl_end(); return (rc);
68 
69 int main(int argc, char **argv)
70 {
71  cpl_init(CPL_INIT_DEFAULT);
72 
73  if (argc <= 1) {
74  /* filename is needed at least */
75  PRINT_USAGE(1);
76  }
77 
78  cpl_boolean verbose = CPL_FALSE;
79  char *iname = NULL; /* table name */
80  unsigned char nifu = 0;
81  double lambda = -1.;
82 
83  /* argument processing */
84  int i;
85  for (i = 1; i < argc; i++) {
86  if (strncmp(argv[i], "-v", 3) == 0) { /* verbose */
87  verbose = CPL_TRUE;
88  } else if (strncmp(argv[i], "-c", 3) == 0) { /* channel */
89  /* skip to next arg to last slice number */
90  i++;
91  if (i < argc) {
92  nifu = atoi(argv[i]);
93  } else {
94  PRINT_USAGE(2);
95  }
96  } else if (strncmp(argv[i], "-l", 3) == 0) { /* channel */
97  /* skip to next arg to last slice number */
98  i++;
99  if (i < argc) {
100  lambda = atof(argv[i]);
101  } else {
102  PRINT_USAGE(3);
103  }
104  } else if (strncmp(argv[i], "-", 1) == 0) { /* unallowed options */
105  PRINT_USAGE(9);
106  } else {
107  if (iname) {
108  break; /* we have the possible names, skip the rest */
109  }
110  iname = argv[i] /* set the name for the table */;
111  }
112  } /* for i (all arguments) */
113 
114  muse_lsf_params **detpars = muse_lsf_params_load(iname, NULL, nifu);
115  if (!detpars) {
116  PRINT_USAGE(10);
117  }
118 
119 #define SPEC_LENGTH 1000 /* [pix] */
120 #define SPEC_SAMPLING 0.01 /* [Angstrom] */
121 #define LINE_FLUX 10000 /* [counts] */
122  /* output a kind of header */
123  printf("# FWHM computed from LSF profile function for several wavelengths "
124  "as mean +/- stdev median\n""# conversion to value in pixels and "
125  "spectral resolution R using %.3f Angstrom/pix\n",
126  kMuseSpectralSamplingA);
127  if (verbose) {
128  printf("%soutput of detailed parameters and results for each slice; "
129  "columns:\n%slambda: ifu.slice\tref_lambda slitwidth binwidth\t "
130  "specmean +/- specstdev (specmedian) specmin..specmax "
131  "(maxidx)\tleftvalue (lidx) rightvalue (ridx) ==> FWHM\n",
132  verbose ? "# " : "", verbose ? "# " : "");
133  }
134  /* line wavelengths for which we want the LSF width */
135  double lpos[] = { 4650., 5000., 6000., 7000., 8000., 9000., 9300., -1. };
136  if (lambda > 0) { /* replace with input wavelength */
137  lpos[0] = lambda;
138  lpos[1] = -1.;
139  }
140  int ilpos = -1;
141  while (lpos[++ilpos] > 0) {
142  cpl_vector *vfwhm = cpl_vector_new(50); /* result for this wavelength */
143  int ifwhm = 0;
144  for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
145  int nslice;
146  for (nslice = 1; nslice <= kMuseSlicesPerCCD; nslice++) {
147  muse_lsf_params *dp = muse_lsf_params_get(detpars, nifu, nslice);
148  if (!dp) {
149  continue;
150  }
151  cpl_errorstate es = cpl_errorstate_get();
152  double fwhm = muse_lsf_fwhm_lambda(dp, lpos[ilpos], LINE_FLUX,
153  SPEC_SAMPLING, SPEC_LENGTH,
154  verbose ? stdout : NULL);
155  if (!cpl_errorstate_is_equal(es)) {
156  continue;
157  }
158  cpl_vector_set(vfwhm, ifwhm++, fwhm);
159  fflush(stdout);
160  } /* for nslice */
161  } /* for nifu */
162  cpl_vector_set_size(vfwhm, ifwhm);
163  double mean = cpl_vector_get_mean(vfwhm),
164  stdev = cpl_vector_get_stdev(vfwhm),
165  median = cpl_vector_get_median(vfwhm);
166  printf("%sFWHM at %.3f Angstrom is %.3f +/- %.3f %.2f [Angstrom], ~%.3f "
167  "[pix], R is %.1f\n", verbose ? "# " : "", lpos[ilpos], mean, stdev,
168  median, mean / kMuseSpectralSamplingA, lpos[ilpos] / mean);
169  cpl_vector_delete(vfwhm);
170  } /* while lpos > 0 */
171  muse_lsf_params_delete(detpars);
172 
173  cpl_end();
174  return 0;
175 }
176 
muse_lsf_params * muse_lsf_params_get(muse_lsf_params **aParams, int aIFU, int aSlice)
Get the slice LSF parameters for one slice.
double muse_lsf_fwhm_lambda(const muse_lsf_params *aDP, double aLambda, double aFlux, double aSampling, unsigned int aLength, FILE *aOutstream)
Measure the FWHM of an LSF at a given wavelength.
muse_lsf_params ** muse_lsf_params_load(const char *aFile, muse_lsf_params **aParams, int aIFU)
Load slice LSF parameters from the extension "SLICE_PARAM".
Structure definition of detector (slice) parameters.
Definition: muse_lsf.h:50
void muse_lsf_params_delete(muse_lsf_params **aParams)
Delete an allocated array of muse_lsf_params structure.