FORS Pipeline Reference Manual 4.9.20
|
00001 /* $Id: fors_qc.c,v 1.10 2010/09/14 07:49:30 cizzo Exp $ 00002 * 00003 * This file is part of the FORS Library 00004 * Copyright (C) 2002-2010 European Southern Observatory 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 00021 /* 00022 * $Author: cizzo $ 00023 * $Date: 2010/09/14 07:49:30 $ 00024 * $Revision: 1.10 $ 00025 * $Name: fors-4_9_20 $ 00026 */ 00027 00028 #ifdef HAVE_CONFIG_H 00029 #include <config.h> 00030 #endif 00031 00032 #include <stdio.h> 00033 #include <stdlib.h> 00034 #include <ctype.h> 00035 #include <string.h> 00036 #include <unistd.h> 00037 #include <math.h> 00038 00039 #include <cpl.h> 00040 #include <fors_utils.h> 00041 #include <fors_paf.h> 00042 #include <fors_dfs.h> 00043 #include <fors_qc.h> 00044 00045 #define DICT_LINE_LENGTH (80) 00046 #define MAX_PAF_NAME_LENGTH (80) 00047 #define PAF_ROOT_NAME "qc" 00048 00056 const char *const fors_qc_dic_version = "2.0"; 00057 00058 static ForsPAF *pafFile = NULL; 00059 static int pafIndex = 0; 00060 00061 00077 cpl_error_code fors_qc_start_group(cpl_propertylist *header, 00078 const char *qcdic_version, 00079 const char *instrument) 00080 { 00081 char pafName[MAX_PAF_NAME_LENGTH]; 00082 00083 if (pafFile) 00084 return cpl_error_set("fors_qc_start_group", CPL_ERROR_FILE_ALREADY_OPEN); 00085 00086 sprintf(pafName, "%s%.4d.paf", PAF_ROOT_NAME, pafIndex); 00087 00088 if (!(pafFile = newForsPAF(pafName, "QC1 parameters", NULL, NULL))) 00089 return cpl_error_set("fors_qc_start_group", CPL_ERROR_FILE_NOT_CREATED); 00090 00091 fors_qc_write_qc_string(header, 00092 "QC.DID", qcdic_version, "QC1 dictionary", 00093 instrument); 00094 00095 return CPL_ERROR_NONE; 00096 00097 } 00098 00099 #undef cleanup 00100 #define cleanup \ 00101 do { \ 00102 cpl_propertylist_delete(header); \ 00103 } while(0) 00104 00115 void fors_qc_write_group_heading(const cpl_frame *raw_frame, 00116 const char *pro_catg, 00117 const char *instrument) 00118 { 00119 cpl_propertylist *header = NULL; 00120 assure( raw_frame != NULL, return, NULL ); 00121 assure( cpl_frame_get_filename(raw_frame) != NULL, return, NULL ); 00122 00123 header = cpl_propertylist_load(cpl_frame_get_filename(raw_frame), 0); 00124 assure( !cpl_error_get_code(), return, "Could not load %s header", 00125 cpl_frame_get_filename(raw_frame)); 00126 00127 fors_qc_write_string("PRO.CATG", pro_catg, 00128 "Product category", instrument); 00129 assure( !cpl_error_get_code(), return, "Cannot write product category to " 00130 "QC log file"); 00131 00132 fors_qc_keyword_to_paf(header, "ESO DPR TYPE", NULL, 00133 "DPR type", instrument); 00134 assure( !cpl_error_get_code(), return, "Missing keyword DPR TYPE in raw " 00135 "frame header"); 00136 00137 fors_qc_keyword_to_paf(header, "ESO TPL ID", NULL, 00138 "Template", instrument); 00139 assure( !cpl_error_get_code(), return, "Missing keyword TPL ID in raw " 00140 "frame header"); 00141 00142 if (cpl_propertylist_has(header, "ESO INS FILT1 NAME")) { 00143 fors_qc_keyword_to_paf(header, "ESO INS FILT1 NAME", NULL, 00144 "Filter name", instrument); 00145 assure( !cpl_error_get_code(), return, "Failed to write ESO INS FILT1 NAME"); 00146 } 00147 00148 fors_qc_keyword_to_paf(header, "ESO INS COLL NAME", NULL, 00149 "Collimator name", instrument); 00150 assure( !cpl_error_get_code(), return, "Missing keyword INS COLL NAME in raw " 00151 "frame header"); 00152 00153 fors_qc_keyword_to_paf(header, "ESO DET CHIP1 ID", NULL, 00154 "Chip identifier", instrument); 00155 assure( !cpl_error_get_code(), return, "Missing keyword DET CHIP1 ID in raw " 00156 "frame header"); 00157 00158 fors_qc_keyword_to_paf(header, "ESO DET WIN1 BINX", NULL, 00159 "Binning factor along X", instrument); 00160 assure( !cpl_error_get_code(), return, "Missing keyword ESO DET WIN1 BINX " 00161 "in raw frame header"); 00162 00163 fors_qc_keyword_to_paf(header, "ESO DET WIN1 BINY", NULL, 00164 "Binning factor along Y", instrument); 00165 assure( !cpl_error_get_code(), return, "Missing keyword ESO DET WIN1 BINY " 00166 "in raw frame header"); 00167 00168 fors_qc_keyword_to_paf(header, "ARCFILE", NULL, 00169 "Archive name of input data", 00170 instrument); 00171 assure( !cpl_error_get_code(), return, "Missing keyword ARCFILE in raw " 00172 "frame header"); 00173 00174 { 00175 char *pipefile = dfs_generate_filename(pro_catg); 00176 fors_qc_write_string("PIPEFILE", pipefile, 00177 "Pipeline product name", instrument); 00178 cpl_free(pipefile); pipefile = NULL; 00179 assure( !cpl_error_get_code(), return, "Cannot write PIPEFILE to QC log file"); 00180 } 00181 00182 cleanup; 00183 return; 00184 } 00185 00186 00187 00200 cpl_error_code fors_qc_end_group(void) 00201 { 00202 00203 if (!pafFile) 00204 return cpl_error_set("fors_qc_end_group", CPL_ERROR_DATA_NOT_FOUND); 00205 00206 if (!forsPAFIsEmpty(pafFile)) { 00207 forsPAFWrite(pafFile); 00208 pafIndex++; 00209 } 00210 00211 deleteForsPAF(pafFile); 00212 pafFile = NULL; 00213 00214 return CPL_ERROR_NONE; 00215 00216 } 00217 00218 00235 cpl_error_code fors_qc_write_string(const char *name, const char *value, 00236 const char *comment, const char *instrument) 00237 { 00238 00239 int status; 00240 int length = strlen(instrument) + 3; 00241 char *allComment; 00242 00243 00244 if (comment == NULL || name == NULL || instrument == NULL) 00245 return cpl_error_set("fors_qc_write_string", CPL_ERROR_NULL_INPUT); 00246 00247 length += strlen(comment) + 1; 00248 00249 allComment = cpl_malloc(length * sizeof(char)); 00250 00251 sprintf(allComment, "%s [%s]", comment, instrument); 00252 00253 status = forsPAFAppendString(pafFile, name, value, allComment); 00254 00255 cpl_free(allComment); 00256 00257 if (status) 00258 cpl_msg_error("fors_qc_write_string", 00259 "Cannot write parameter %s to QC1 PAF", name); 00260 00261 cpl_msg_debug(cpl_func, "%s [%s] = '%s'", comment, name, value); 00262 00263 return CPL_ERROR_NONE; 00264 00265 } 00266 00267 cpl_error_code fors_qc_write_string_chat(const char *name, const char *value, 00268 const char *comment, const char *instrument) 00269 { 00270 00271 int status; 00272 int length = strlen(instrument) + 3; 00273 char *allComment; 00274 00275 00276 if (comment == NULL || name == NULL || instrument == NULL) 00277 return cpl_error_set("fors_qc_write_string_chat", CPL_ERROR_NULL_INPUT); 00278 00279 length += strlen(comment) + 1; 00280 00281 allComment = cpl_malloc(length * sizeof(char)); 00282 00283 sprintf(allComment, "%s [%s]", comment, instrument); 00284 00285 status = forsPAFAppendString(pafFile, name, value, allComment); 00286 00287 cpl_free(allComment); 00288 00289 if (status) 00290 cpl_msg_error("fors_qc_write_string_chat", 00291 "Cannot write parameter %s to QC1 PAF", name); 00292 00293 cpl_msg_info(cpl_func, "%s [%s] = '%s'", comment, name, value); 00294 00295 return CPL_ERROR_NONE; 00296 00297 } 00298 00299 00321 cpl_error_code fors_qc_write_double(const char *name, double value, 00322 const char *unit, const char *comment, 00323 const char *instrument) 00324 { 00325 00326 cpl_error_code status; 00327 int length = strlen(instrument) + 3; 00328 char *allComment; 00329 00330 00331 if (comment == NULL || name == NULL || instrument == NULL) 00332 return cpl_error_set("fors_qc_write_double", CPL_ERROR_NULL_INPUT); 00333 00334 length += strlen(comment) + 1; 00335 00336 if (unit) 00337 length += strlen(unit) + 3; 00338 00339 allComment = cpl_malloc(length * sizeof(char)); 00340 00341 if (unit) 00342 sprintf(allComment, "%s (%s) [%s]", comment, unit, instrument); 00343 else 00344 sprintf(allComment, "%s [%s]", comment, instrument); 00345 00346 status = forsPAFAppendDouble(pafFile, name, value, allComment); 00347 00348 cpl_free(allComment); 00349 00350 if (status) 00351 cpl_msg_error("fors_qc_write_double", 00352 "Cannot write parameter %s to QC1 PAF", name); 00353 00354 cpl_msg_info(cpl_func, "%s [%s] = %f %s", 00355 comment, name, value, (unit != NULL) ? unit : ""); 00356 00357 return CPL_ERROR_NONE; 00358 00359 } 00360 00361 00362 cpl_error_code fors_qc_write_int(const char *name, int value, const char *unit, 00363 const char *comment, const char *instrument) 00364 { 00365 00366 cpl_error_code status; 00367 int length = strlen(instrument) + 3; 00368 char *allComment; 00369 00370 00371 if (comment == NULL || name == NULL || instrument == NULL) 00372 return cpl_error_set("fors_qc_write_int", CPL_ERROR_NULL_INPUT); 00373 00374 length += strlen(comment) + 1; 00375 00376 if (unit) 00377 length += strlen(unit) + 3; 00378 00379 allComment = cpl_malloc(length * sizeof(char)); 00380 00381 if (unit) 00382 sprintf(allComment, "%s (%s) [%s]", comment, unit, instrument); 00383 else 00384 sprintf(allComment, "%s [%s]", comment, instrument); 00385 00386 status = forsPAFAppendInt(pafFile, name, value, allComment); 00387 00388 cpl_free(allComment); 00389 00390 if (status) 00391 cpl_msg_error("fors_qc_write_int", 00392 "Cannot write parameter %s to QC1 PAF", name); 00393 00394 cpl_msg_info(cpl_func, "%s [%s] = %d %s", 00395 comment, name, value, (unit != NULL) ? unit : ""); 00396 00397 return CPL_ERROR_NONE; 00398 00399 } 00400 00401 00425 cpl_error_code fors_qc_keyword_to_paf(cpl_propertylist *header, 00426 const char *name, const char *unit, 00427 const char *comment, 00428 const char *instrument) 00429 { 00430 00431 const char func[] = "fors_qc_keyword_to_paf"; 00432 00433 char *keyName; 00434 char *keep; 00435 char *pos; 00436 int ivalue; 00437 float fvalue; 00438 double dvalue; 00439 char *svalue = NULL; 00440 int status; 00441 int i; 00442 00443 00444 if (header == NULL) { 00445 cpl_msg_error(func, "Empty header"); 00446 return cpl_error_set(func, CPL_ERROR_NULL_INPUT); 00447 } 00448 00449 if (!cpl_propertylist_has(header, name)) { 00450 cpl_msg_error(func, "Keyword %s not found", name); 00451 return cpl_error_set(func, CPL_ERROR_DATA_NOT_FOUND); 00452 } 00453 00454 switch (cpl_propertylist_get_type(header, name)) { 00455 case CPL_TYPE_INT : 00456 ivalue = cpl_propertylist_get_int(header, name); 00457 break; 00458 case CPL_TYPE_FLOAT : 00459 fvalue = cpl_propertylist_get_float(header, name); 00460 break; 00461 case CPL_TYPE_DOUBLE : 00462 dvalue = cpl_propertylist_get_double(header, name); 00463 break; 00464 case CPL_TYPE_STRING : 00465 svalue = (char *)cpl_propertylist_get_string(header, name); 00466 break; 00467 default : 00468 cpl_msg_error(func, "Unsupported keyword type"); 00469 return cpl_error_set(func, CPL_ERROR_INVALID_TYPE); 00470 } 00471 00472 00473 /* 00474 * Construct entry name for PAF 00475 */ 00476 00477 keep = keyName = cpl_strdup(name); 00478 00479 pos = strstr(keyName, "ESO "); 00480 00481 if (pos == keyName) 00482 keyName += 4; 00483 00484 for (i = 0; keyName[i] != '\0'; i++) 00485 if (keyName[i] == ' ') 00486 keyName[i] = '.'; 00487 00488 /* 00489 * Now write entry to PAF object. 00490 */ 00491 00492 switch (cpl_propertylist_get_type(header, name)) { 00493 case CPL_TYPE_INT : 00494 status = fors_qc_write_int(keyName, ivalue, unit, comment, instrument); 00495 break; 00496 case CPL_TYPE_FLOAT : 00497 dvalue = fvalue; 00498 case CPL_TYPE_DOUBLE : 00499 status = fors_qc_write_double(keyName, dvalue, unit, comment, instrument); 00500 break; 00501 default : /* CPL_TYPE_STRING */ 00502 status = fors_qc_write_string(keyName, svalue, comment, instrument); 00503 } 00504 00505 if (status) 00506 cpl_msg_error(func, "Could not copy keyword value to QC1 PAF!"); 00507 00508 cpl_free(keep); 00509 00510 return status; 00511 00512 } 00513 00535 cpl_error_code fors_qc_write_qc_string(cpl_propertylist *header, 00536 const char *name, const char *value, 00537 const char *comment, 00538 const char *instrument) 00539 { 00540 const char func[] = "fors_qc_write_qc_string"; 00541 00542 char *header_name; 00543 int i; 00544 00545 if (strcmp("QC.DID", name)) { 00546 if (fors_qc_write_string_chat(name, value, comment, instrument)) { 00547 cpl_error_set_where(func); 00548 return cpl_error_get_code(); 00549 } 00550 } 00551 else { 00552 if (fors_qc_write_string(name, value, comment, instrument)) { 00553 cpl_error_set_where(func); 00554 return cpl_error_get_code(); 00555 } 00556 } 00557 00558 header_name = cpl_malloc((strlen(name) + 6) * sizeof(char *)); 00559 00560 strcpy(header_name, "ESO "); 00561 strcat(header_name, name); 00562 00563 for (i = 0; header_name[i] != '\0'; i++) 00564 if (header_name[i] == '.') 00565 header_name[i] = ' '; 00566 00567 if (cpl_propertylist_update_string(header, header_name, value)) { 00568 cpl_free(header_name); 00569 cpl_error_set_where(func); 00570 return cpl_error_get_code(); 00571 } 00572 00573 cpl_propertylist_set_comment(header, header_name, comment); 00574 00575 cpl_free(header_name); 00576 00577 return CPL_ERROR_NONE; 00578 } 00579 00604 cpl_error_code fors_qc_write_qc_double(cpl_propertylist *header, double value, 00605 const char *name, const char *unit, 00606 const char *comment, 00607 const char *instrument) 00608 { 00609 00610 const char func[] = "fors_qc_write_qc_double"; 00611 00612 char *header_name; 00613 int i; 00614 00615 00616 if (fors_qc_write_double(name, value, unit, comment, instrument)) { 00617 cpl_error_set_where(func); 00618 return cpl_error_get_code(); 00619 } 00620 00621 header_name = cpl_malloc((strlen(name) + 6) * sizeof(char *)); 00622 00623 strcpy(header_name, "ESO "); 00624 strcat(header_name, name); 00625 00626 for (i = 0; header_name[i] != '\0'; i++) 00627 if (header_name[i] == '.') 00628 header_name[i] = ' '; 00629 00630 if (cpl_propertylist_update_double(header, header_name, value)) { 00631 cpl_free(header_name); 00632 cpl_error_set_where(func); 00633 return cpl_error_get_code(); 00634 } 00635 00636 cpl_propertylist_set_comment(header, header_name, comment); 00637 00638 cpl_free(header_name); 00639 00640 return CPL_ERROR_NONE; 00641 00642 } 00643 00644 00645 cpl_error_code fors_qc_write_qc_int(cpl_propertylist *header, int value, 00646 const char *name, const char *unit, 00647 const char *comment, 00648 const char *instrument) 00649 { 00650 00651 const char func[] = "fors_qc_write_qc_int"; 00652 00653 char *header_name; 00654 int i; 00655 00656 00657 if (fors_qc_write_int(name, value, unit, comment, instrument)) { 00658 cpl_error_set_where(func); 00659 return cpl_error_get_code(); 00660 } 00661 00662 header_name = cpl_malloc((strlen(name) + 6) * sizeof(char *)); 00663 00664 strcpy(header_name, "ESO "); 00665 strcat(header_name, name); 00666 00667 for (i = 0; header_name[i] != '\0'; i++) 00668 if (header_name[i] == '.') 00669 header_name[i] = ' '; 00670 00671 if (cpl_propertylist_update_int(header, header_name, value)) { 00672 cpl_free(header_name); 00673 cpl_error_set_where(func); 00674 return cpl_error_get_code(); 00675 } 00676 00677 cpl_propertylist_set_comment(header, header_name, comment); 00678 00679 cpl_free(header_name); 00680 00681 return CPL_ERROR_NONE; 00682 00683 } 00684 00685 /* 00686 * @brief 00687 * Write an integer value to the active QC1 PAF object and to a header. 00688 * 00689 * @return @c CPL_ERROR_NONE on success 00690 * 00691 * @param filnam Name of existing FITS file. 00692 * @param value Value to write. 00693 * @param name QC1 PAF entry name. 00694 * @param unit Optional unit to be associated to value. 00695 * @param comment Optional comment to be associated to value. 00696 * 00697 * @doc 00698 * This function writes the header entries directly to the header 00699 * of the FITS file written to disk, using the qfits_replace_card() call. 00700 * An entry with the specified @em name is written to the current QC1 PAF 00701 * object. From the entry @em name, the name of the QC keyword that 00702 * should be written to header is derived prepending the string "ESO " 00703 * and replacing all '.' with a blank (e.g., "QC.BIAS.MASTER.MEAN" 00704 * becomes "ESO QC BIAS MASTER MEAN"). Finally, the new keyword 00705 * is written to the header. Note that before calling this funtion 00706 * a QC1 PAF object must be created with a call to fors_qc_start_group(). 00707 */ 00708 00709 /* 00710 cpl_error_code fors_qc_write_qc_int(char *filnam, int value, const char *name, 00711 const char *unit, const char *comment, 00712 const char *instrument) 00713 { 00714 00715 const char func[] = "fors_qc_write_qc_int"; 00716 00717 char line[81]; 00718 char val[81]; 00719 char *descName; 00720 int i; 00721 00722 00723 if (fors_qc_write_int(name, value, unit, comment, instrument)) { 00724 cpl_msg_error(func, "Could not copy value to QC1 PAF!"); 00725 cpl_error_set_where(func); 00726 return cpl_error_get_code(); 00727 } 00728 00729 descName = cpl_malloc((strlen(name) + 15) * sizeof(char *)); 00730 00731 strcpy(descName, "HIERARCH ESO "); 00732 strcat(descName, name); 00733 00734 for (i = 0; descName[i] != '\0'; i++) 00735 if (descName[i] == '.') 00736 descName[i] = ' '; 00737 00738 sprintf(val, "%d", value); 00739 keytuple2str(line, descName, val, (char *)comment); 00740 qfits_replace_card(filnam, descName, line); 00741 00742 cpl_free(descName); 00743 00744 return CPL_ERROR_NONE; 00745 00746 } 00747 00748 00749 cpl_error_code fors_qc_write_qc_double(char *filnam, double value, 00750 const char *name, const char *unit, 00751 const char *comment, 00752 const char *instrument) 00753 { 00754 00755 const char func[] = "fors_qc_write_qc_double"; 00756 00757 char line[81]; 00758 char val[81]; 00759 char *descName; 00760 int i; 00761 00762 00763 if (fors_qc_write_double(name, value, unit, comment, instrument)) { 00764 cpl_msg_error(func, "Could not copy value to QC1 PAF!"); 00765 cpl_error_set_where(func); 00766 return cpl_error_get_code(); 00767 } 00768 00769 descName = cpl_malloc((strlen(name) + 15) * sizeof(char *)); 00770 00771 strcpy(descName, "HIERARCH ESO "); 00772 strcat(descName, name); 00773 00774 for (i = 0; descName[i] != '\0'; i++) 00775 if (descName[i] == '.') 00776 descName[i] = ' '; 00777 00778 sprintf(val, "%1.6e", value); 00779 keytuple2str(line, descName, val, (char *)comment); 00780 qfits_replace_card(filnam, descName, line); 00781 00782 cpl_free(descName); 00783 00784 return CPL_ERROR_NONE; 00785 00786 } 00787 00788 */ 00789