00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifdef HAVE_CONFIG_H
00023 #include <config.h>
00024 #endif
00025
00026
00027
00028
00029 #include <stdio.h>
00030 #include <float.h>
00031 #include <math.h>
00032 #include <string.h>
00033 #include <cpl.h>
00034 #include <muse.h>
00035 #include "muse_ampl_z.h"
00036
00037
00038
00039
00040
00041
00047
00048 static void
00049 muse_ampl_qc_header(muse_image *aImage, muse_imagelist *aList)
00050 {
00051
00052 unsigned int k;
00053 for (k = 0; k < muse_imagelist_get_size(aList); k++) {
00054 char *keyword = cpl_sprintf("ESO QC AMPL INPUT%d "QC_BASIC_NSATURATED, k+1);
00055 int nsaturated = cpl_propertylist_get_int(muse_imagelist_get(aList, k)->header,
00056 MUSE_HDR_TMP_NSAT);
00057 cpl_propertylist_update_int(aImage->header, keyword, nsaturated);
00058 cpl_free(keyword);
00059 }
00060 }
00061
00062
00069
00070 static cpl_table *
00071 muse_ampl_table_new(const double aAmpl[][2])
00072 {
00073 cpl_ensure(aAmpl, CPL_ERROR_NULL_INPUT, NULL);
00074 int i = -1, n = 0;
00075 while (aAmpl[++i][0] > 0.) n++;
00076 cpl_msg_debug(__func__, "creating table with %d entries", n);
00077 cpl_table *tampl = cpl_table_new(n);
00078 cpl_table_new_column(tampl, "lambda", CPL_TYPE_DOUBLE);
00079 cpl_table_new_column(tampl, "throughput", CPL_TYPE_DOUBLE);
00080 for (i = 0; i < n; i++) {
00081 cpl_table_set_double(tampl, "lambda", i, aAmpl[i][0]);
00082 cpl_table_set_double(tampl, "throughput", i, aAmpl[i][1]);
00083 }
00084 #if 0
00085 cpl_table_dump(tampl, 0, 100000, stdout);
00086 fflush(stdout);
00087 #endif
00088 return tampl;
00089 }
00090
00091
00098
00099 int
00100 muse_ampl_compute(muse_processing *aProcessing, muse_ampl_params_t *aParams)
00101 {
00102
00103 cpl_table *trace = muse_table_load(aProcessing, MUSE_TAG_TRACE_TABLE,
00104 aParams->nifu);
00105 cpl_table *wave = muse_table_load(aProcessing, MUSE_TAG_WAVECAL_TABLE,
00106 aParams->nifu);
00107 if (!trace || !wave) {
00108 cpl_msg_error(__func__, "Calibration could not be loaded:%s%s",
00109 !trace ? " "MUSE_TAG_TRACE_TABLE : "",
00110 !wave ? " "MUSE_TAG_WAVECAL_TABLE : "");
00111
00112 cpl_table_delete(trace);
00113 cpl_table_delete(wave);
00114 return -1;
00115 }
00116
00117
00118 muse_basicproc_params *bpars = muse_basicproc_params_new(aProcessing->parameters,
00119 "muse.muse_ampl");
00120 muse_imagelist *images = muse_basicproc_load(aProcessing, aParams->nifu, bpars);
00121 muse_basicproc_params_delete(bpars);
00122 if (!images) {
00123 cpl_error_set_message(__func__, cpl_error_get_code(),
00124 "Loading and processing raw data failed!");
00125 cpl_table_delete(trace);
00126 cpl_table_delete(wave);
00127 return -1;
00128 }
00129 muse_combinepar *cpars = muse_combinepar_new(aProcessing->parameters,
00130 "muse.muse_ampl");
00131 cpars->scale = CPL_TRUE;
00132 muse_image *image = muse_combine_images(cpars, images);
00133 muse_combinepar_delete(cpars);
00134 if (!image) {
00135 cpl_msg_error(__func__, "Combining input frames failed!");
00136 muse_imagelist_delete(images);
00137 cpl_table_delete(trace);
00138 cpl_table_delete(wave);
00139 return -1;
00140 }
00141
00142 cpl_propertylist_erase_regexp(image->header, MUSE_WCS_KEYS, 0);
00143 muse_ampl_qc_header(image, images);
00144 muse_basicproc_qc_saturated(image, "ESO QC AMPL MASTER");
00145 muse_imagelist_delete(images);
00146 if (aParams->savemaster) {
00147 muse_processing_save_image(aProcessing, aParams->nifu, image, "MASTER_AMPL");
00148 }
00149
00150
00151 const char *fname = muse_pfits_get_pam2_filter(image->header);
00152 cpl_table *filter = muse_table_load_filter(aProcessing, fname);
00153 if (!filter) {
00154 cpl_msg_error(__func__, "Filter \"%s\" could not be loaded from FILTER_LIST"
00155 " file!", fname);
00156 return -1;
00157 }
00158
00159
00160 muse_pixtable *pt = muse_pixtable_create(image, trace, wave, NULL);
00161 cpl_table_delete(trace);
00162 cpl_table_delete(wave);
00163 if (!pt) {
00164 cpl_msg_error(__func__, "pixel table was not created: %s",
00165 cpl_error_get_message());
00166 muse_image_delete(image);
00167 cpl_table_delete(filter);
00168 return -1;
00169 }
00170 cpl_table *geotable = muse_table_load(aProcessing, MUSE_TAG_GEOMETRY_TABLE, 0);
00171
00172 double fpsize = 60. / muse_pfits_get_focu_scale(pt->header),
00173 ifuarea = pow(fpsize / 10., 2) / kMuseNumIFUs;
00174 const char *modestring = muse_pfits_get_mode(pt->header) < MUSE_MODE_NFM_AO_N
00175 ? "WFM" : "NFM";
00176 if (!geotable) {
00177 if (muse_pfits_get_mode(pt->header) >= MUSE_MODE_NFM_AO_N) {
00178
00179 ifuarea /= pow(kMuseSpaxelSizeX_WFM / kMuseSpaxelSizeX_NFM, 2);
00180 }
00181 cpl_msg_warning(__func__, "assuming constant per-IFU area of %f cm**2 "
00182 "(mode %s)", ifuarea, modestring);
00183 } else {
00184
00185 ifuarea = muse_geo_table_ifu_area(geotable, aParams->nifu, fpsize / 10.);
00186 cpl_msg_info(__func__, "computed area of IFU %d in focal plane: %.3f cm**2 "
00187 "(mode %s)", aParams->nifu, ifuarea, modestring);
00188 cpl_table_delete(geotable);
00189 }
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 cpl_table_set_column_unit(pt->table, MUSE_PIXTABLE_DATA, "ph");
00204
00205 cpl_table_set_column_unit(pt->table, MUSE_PIXTABLE_STAT, "J");
00206
00207 const float *lbda = cpl_table_get_data_float_const(pt->table, MUSE_PIXTABLE_LAMBDA);
00208 float *data = cpl_table_get_data_float(pt->table, MUSE_PIXTABLE_DATA),
00209 *stat = cpl_table_get_data_float(pt->table, MUSE_PIXTABLE_STAT);
00210 cpl_table_unselect_all(pt->table);
00211 cpl_msg_debug(__func__, "Using black body correction with T = %.1f K",
00212 aParams->temp);
00213
00214
00215 double dsum = 0., esum = 0., lwmean = 0., wsum = 0.;
00216 cpl_size irow, nrow = cpl_table_get_nrow(pt->table);
00217 for (irow = 0; irow < nrow; irow++) {
00218 double resp = muse_flux_response_interpolate(filter, lbda[irow], NULL,
00219 MUSE_FLUX_RESP_FILTER);
00220 if (resp <= 0.) {
00221 cpl_table_select_row(pt->table, irow);
00222 continue;
00223 }
00224
00225 data[irow] *= resp;
00226
00227
00228
00229 stat[irow] = CPL_PHYS_H * CPL_PHYS_C / lbda[irow] * 1e10 * data[irow];
00230 dsum += data[irow];
00231 esum += stat[irow];
00232
00233
00234 double lbda_m = lbda[irow] / 1e10,
00235 fb = (CPL_PHYS_H * CPL_PHYS_C) / (CPL_PHYS_K * aParams->temp * lbda_m),
00236 Bn = 15. / lbda_m * pow(fb / CPL_MATH_PI, 4) / (exp(fb) - 1.);
00237 wsum += data[irow] / Bn;
00238 lwmean += lbda[irow] * data[irow] / Bn;
00239 }
00240 lwmean /= wsum;
00241 cpl_msg_info(__func__, "%"CPL_SIZE_FORMAT" of %"CPL_SIZE_FORMAT" pixel table "
00242 "rows (%.2f%%) unused", cpl_table_count_selected(pt->table), nrow,
00243 100. * cpl_table_count_selected(pt->table) / nrow);
00244 cpl_table_erase_selected(pt->table);
00245 muse_pixtable_compute_limits(pt);
00246 double exptime = muse_pfits_get_exptime(pt->header),
00247 power = esum / exptime;
00248
00249 double pdensity = power / ifuarea;
00250 cpl_msg_info(__func__, "Summed flux: %e ph, energy: %e J, power: %e W, power "
00251 "density: %e W/cm**2", dsum, esum, power, pdensity);
00252
00253
00254
00255
00256 cpl_table *tampl1 = muse_ampl_table_new(kMuseAmpl1),
00257 *tampl2 = muse_ampl_table_new(kMuseAmpl2);
00258 double sens1 = muse_flux_response_interpolate(tampl1, lwmean, NULL,
00259 MUSE_FLUX_RESP_FILTER)
00260 * kMuseAmplPhysicalSize,
00261 sens2 = muse_flux_response_interpolate(tampl2, lwmean, NULL,
00262 MUSE_FLUX_RESP_FILTER)
00263 * kMuseAmplPhysicalSize;
00264 cpl_table_delete(tampl1);
00265 cpl_table_delete(tampl2);
00266 cpl_msg_info(__func__, "mean photo diode sensitivities at weighted mean "
00267 "wavelength %.2f Angstrom: %f A/W*cm**2, %f A/W*cm**2", lwmean,
00268 sens1, sens2);
00269
00270 cpl_msg_debug(__func__, "using beam widening factor %.3f for photo diode 2",
00271 aParams->fbeam);
00272 sens2 /= aParams->fbeam;
00273
00274
00275
00276 cpl_errorstate state = cpl_errorstate_get();
00277 double pam1 = muse_pfits_get_pam_intensity(image->header, 1),
00278 pam2 = muse_pfits_get_pam_intensity(image->header, 2);
00279 if (!cpl_errorstate_is_equal(state)) {
00280 cpl_msg_error(__func__, "Pico-amplifier measurement(s) not found in header: %s",
00281 cpl_error_get_message());
00282 muse_image_delete(image);
00283 cpl_table_delete(filter);
00284 muse_pixtable_delete(pt);
00285 return -1;
00286 }
00287 double pam1stdev = muse_pfits_get_pam_stdev(image->header, 1),
00288 pam2stdev = muse_pfits_get_pam_stdev(image->header, 2),
00289 p1density = pam1 / sens1,
00290 p2density = pam2 / sens2;
00291 cpl_msg_info(__func__, "amplifiers: AMPL1 %.3e +/- %.3e A, %.2e W/cm**2, "
00292 "AMPL2 %.3e +/- %.3e A, %.2e W/cm**2", pam1, pam1stdev,
00293 p1density, pam2, pam2stdev, p2density);
00294
00295
00296
00297
00298
00299
00300 double thru1 = pdensity / p1density * 100.,
00301 thru2 = pdensity / p2density * 100.,
00302 areaerr = 0.03,
00303 filterr = lwmean > 5000 && lwmean < 8000 ? 0.01 : 0.02,
00304 beamerr = 0.04,
00305 thru2err = sqrt(areaerr*areaerr + beamerr*beamerr + filterr*filterr);
00306 cpl_msg_info(__func__, "throughput values: to AMPL1 %.3f %%, to "
00307 "AMPL2 %.3f +/- %.3f %%", thru1, thru2, thru2err * thru2);
00308
00309
00310 cpl_propertylist_erase_regexp(pt->header, "ESO QC", 0);
00311 cpl_propertylist_append_float(pt->header, "ESO QC AMPL PHOTONS", dsum);
00312 cpl_propertylist_append_float(pt->header, "ESO QC AMPL POWER", power);
00313 cpl_propertylist_append_float(pt->header, "ESO QC AMPL THRU1", thru1);
00314 cpl_propertylist_append_float(pt->header, "ESO QC AMPL THRU2", thru2);
00315 cpl_propertylist_append_float(pt->header, "ESO QC AMPL THRU2ERR", thru2 * thru2err);
00316
00317
00318 muse_pixtable **pts = muse_pixtable_extracted_get_slices(pt);
00319 double slicearea = ifuarea / kMuseSlicesPerCCD;
00320 cpl_msg_warning(__func__, "assuming constant per-slice area of %f cm**2",
00321 slicearea);
00322 int ipt;
00323 for (ipt = 0; ipt < muse_pixtable_extracted_get_size(pts); ipt++) {
00324 uint32_t origin = cpl_table_get_int(pts[ipt]->table, MUSE_PIXTABLE_ORIGIN,
00325 0, NULL);
00326 unsigned short slice = muse_pixtable_origin_get_slice(origin);
00327
00328
00329 double spower = cpl_table_get_column_mean(pts[ipt]->table, MUSE_PIXTABLE_STAT)
00330 * cpl_table_get_nrow(pts[ipt]->table) / exptime,
00331 spdensity = spower / slicearea,
00332 sthru2 = spdensity / p2density * 100.;
00333 char *keyword = cpl_sprintf("ESO QC AMPL SLICE%d THRU2", slice);
00334 cpl_propertylist_append_float(pt->header, keyword, sthru2);
00335 cpl_free(keyword);
00336 cpl_msg_info(__func__, "slice %2d: power %.3e W, throughput %.3f %%",
00337 slice, spower, sthru2);
00338 }
00339 muse_pixtable_extracted_delete(pts);
00340 if (aParams->savetable) {
00341
00342
00343
00344 muse_processing_save_table(aProcessing, aParams->nifu, pt->table,
00345 pt->header, "TABLE_AMPL", MUSE_TABLE_TYPE_CPL);
00346 }
00347
00348
00349
00350
00351 muse_imagelist *list = muse_pixtable_to_imagelist(pt);
00352 muse_image *outimage = muse_imagelist_get(list, 0);
00353 cpl_propertylist_copy_property_regexp(outimage->header, image->header,
00354 "^ESO QC", 0);
00355 cpl_propertylist_copy_property_regexp(outimage->header, pt->header,
00356 "^ESO QC", 0);
00357
00358 cpl_propertylist_erase_regexp(outimage->header, "^ESO DRS MUSE SLICE.* CENTER", 0);
00359
00360
00361
00362 muse_processing_save_header(aProcessing, aParams->nifu, outimage->header,
00363 "AMPL_CONVOLVED");
00364
00365
00366 cpl_frame *outframe = muse_frameset_find_master(aProcessing->outframes,
00367 "AMPL_CONVOLVED", aParams->nifu);
00368 const char *fn = cpl_frame_get_filename(outframe);
00369 cpl_propertylist *hext = cpl_propertylist_new();
00370 cpl_propertylist_append_string(hext, "EXTNAME", "PHOTONS");
00371 cpl_propertylist_set_comment(hext, "EXTNAME", "This extension contains photon counts");
00372 cpl_propertylist_append_string(hext, "BUNIT", cpl_table_get_column_unit(pt->table,
00373 MUSE_PIXTABLE_DATA));
00374 cpl_image_save(outimage->data, fn, CPL_TYPE_UNSPECIFIED, hext, CPL_IO_EXTEND);
00375 cpl_propertylist_update_string(hext, "EXTNAME", "ENERGY");
00376 cpl_propertylist_set_comment(hext, "EXTNAME", "This extension contains per-pixel energy");
00377 cpl_propertylist_update_string(hext, "BUNIT", cpl_table_get_column_unit(pt->table,
00378 MUSE_PIXTABLE_STAT));
00379 cpl_image_save(outimage->stat, fn, CPL_TYPE_UNSPECIFIED, hext, CPL_IO_EXTEND);
00380 #if 0
00381 cpl_propertylist_update_string(hext, "EXTNAME", EXTNAME_DQ);
00382 cpl_propertylist_set_comment(hext, "EXTNAME", EXTNAME_DQ_COMMENT);
00383 cpl_propertylist_erase(hext, "BUNIT");
00384 cpl_image_save(outimage->dq, fn, CPL_TYPE_UNSPECIFIED, hext, CPL_IO_EXTEND);
00385 #endif
00386 cpl_frame_delete(outframe);
00387 cpl_propertylist_delete(hext);
00388
00389
00390 muse_imagelist_delete(list);
00391 muse_pixtable_delete(pt);
00392 muse_image_delete(image);
00393 cpl_table_delete(filter);
00394
00395 return 0;
00396 }