/** * Routine to read in the DLD1P_?_PRANGE keyword ? for a specific beam * from the configuration file. This is only for a prismatic dispersion * solution * * @param filename filename of the configuration file * @param beamID beamID of the beam of interest (A=0, B=1, etc...) * * @return v gsl-vector [pmin, pmax] */ gsl_vector * get_prange (char *filename, int beamID) { char beam[MAXCHAR]; gsl_vector *v = NULL; struct CfgStrings DispConfig[] = { {NULL, NULL}, {NULL, NULL} }; DispConfig[0].name = beam; sprintf (beam, "DLD1P_%c_PRANGE", BEAM (beamID)); CfgRead (filename, DispConfig); if (DispConfig[0].data != NULL){ v = string_to_gsl_array (DispConfig[0].data); if (v->size != 2) aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "get_prange: two items, PMIN and PMAX must be given, not %i\n", v->size); if (gsl_vector_get(v,0) > gsl_vector_get(v,1)) aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "get_prange: PMIN must be smaller than PMAX, however PMIN: %f, PMAX %f\n", gsl_vector_get(v,0), gsl_vector_get(v,1)); } return v; }
/** * Function: get_fits_header * Returns the header of extension hdunum from a fits file filename * * Parameters: * @param filename The name of the FITS file * @param hdunum the number of the HDU to access * * Returns: * @return a pointer to a newly allocated string containing the entire header */ char * get_fits_header (char filename[], int hdunum) { fitsfile *input; int f_status = 0, hdutype; int nkeys, i; char card[FLEN_CARD]; char *header, *p; // Open the file for creating/appending fits_open_file (&input, filename, READONLY, &f_status); if (f_status) { ffrprt (stderr, f_status); aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "get_fits_header: Could not open" " file:", filename); } fits_movabs_hdu (input, hdunum, &hdutype, &f_status); if (f_status) { ffrprt (stderr, f_status); aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "get_fits_header: " "Could not read extention %d from file: %s", hdunum, filename); } fits_get_hdrspace (input, &nkeys, NULL, &f_status); /* get # of keywords */ header = (char *) malloc ((nkeys + 1) * FLEN_CARD * sizeof (char)); p = header; for (i = 0; i < nkeys; i++) { /* Read and print each keywords */ if (fits_read_record (input, i + 1, card, &f_status)) break; sprintf(p,"%-80s", card); p = p + 80; } /* Add END keyword */ sprintf (card, "END"); sprintf(p,"%-80s", card); return header; }
/** * The function creates and loads a fluximage structure * from an extention of a fluxcube file. * * @param fcube_file - the file name of the fluxcube * @param hdunum - the extension number to load in a fluximage * * @return fimage - pointer to the fluximage structure loaded */ flux_image * load_fluximage(const char fcube_file[], int hdunum) { flux_image *fimage; char tmp[MAXCHAR]; double wavelength; strcpy(tmp, fcube_file); // allocate space for the fluximage structure fimage = (flux_image *)malloc(sizeof(flux_image)); // load the array from the specified extension number fimage->flux = FITSimage_to_gsl(fcube_file, hdunum, 1); // get the keyword "WAVELENG' from the specified extension number wavelength = (double)get_float_from_keyword(tmp, hdunum, "WAVELENG"); // report an error in case that the extension does not have that keyword. // Otherwise store its content in the fluximage structure if (isnan(wavelength)) aXe_message(aXe_M_FATAL, __FILE__, __LINE__, "aXe_PETCONT: " "Missing keyword WAVELENGTH in fluxcube %s, extension %i!\n", fcube_file, hdunum); else fimage->wavelength = wavelength; return fimage; }
/** * Parses a configuration file, computes and return the value * of the order^th dispersion polynomial coefficient at a given * detector pixel. * * @param filename filename of the configuration file * @param beamID beamID of the beam of interest (A=0, B=1, etc...) * @param order order of the coefficient for which the 2D field dependent * @param p a d_point object containing the position to compute the * dispersion coefficient at. * * @return res the value of the order6th coefficient of beamID computed at * detector pixel p. */ float get_disp_coeff_at_pos (char *filename, const int for_grism, int beamID, int order, d_point p) { gsl_vector *v; float n, c, res; int i, j, k; v = get_beam_disp_order (filename, for_grism, beamID, order); n = 0.5 * (-1.0 + sqrt (1 + 8 * v->size)); if ((floor (n) - n) != 0) { aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "get_disp_coeff_at_pos: " "Order %d of Beam %d in %s does not contain a correct number of entries (i.e. " "1,3,6,10,15...,n^2/2+n/2", order, beamID, filename); } i = 0; res = 0; for (j = 0; j < n; j++) { for (k = 0; k < (j + 1); k++) { c = gsl_vector_get (v, i); res = res + c * pow (p.x, (j - k)) * pow (p.y, k); i++; } } gsl_vector_free (v); return res; }
/** * Parses a configuration file and searches for DISP_ORDER_%c * keywords. Returns the order of the field dependent * dispersion relation for that order. * * @param filename filename of the configuration file * @param beamID beamID of the beam of interest (A=0, B=1, etc...) * * @return disporder the order of the dispersion relation for the beam * of interest */ int get_beam_disp_norder (char *filename, int beamID) { char beam[MAXCHAR]; int disporder = -1, found = 0, i; struct CfgStrings DispConfig[] = { {NULL, NULL}, {NULL, NULL} }; DispConfig[0].name = beam; sprintf (beam, "DISP_ORDER_%c", BEAM (beamID)); CfgRead (filename, DispConfig); if ((DispConfig[0].name == beam) && (DispConfig[0].data != NULL)) { disporder = atoi (DispConfig[0].data); found = 1; } if (!found) { aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "get_beam_disp_norder: %s was not found in %s.\n", beam, filename); } i = 0; while(DispConfig[i].name!=NULL){ free(DispConfig[i++].data); } //free(DispConfig[0].data); return disporder; }
/** * Function: intpix_corr_pet * The function applies the intra-pixel sensitivity correction to * a list of PET pixels. The values in the pixels are corrected in * place using the correction function, gemoetrical parameters and * dispersion relation in the various parameters. * * Parameters: * @param actbeam - the beam to correct * @param conf_file_path - full path to the axe configuration file * @param ipcorr - the ipc correction function * @param PET - the list of PET pixels to correct * * Returns: * - */ void intpix_corr_pet(beam actbeam, char conf_file_path[], interpolator *ipcorr, ap_pixel *PET) { interpolator *ipclambda; aperture_conf *conf; int for_grism=0; // load the configuration file conf = get_aperture_descriptor(conf_file_path); // check whether it is grism (for_grism=1) // or prism (for_grism=0) data // give an error if there is a prism solution for_grism = check_for_grism (conf_file_path, actbeam.ID); if (!for_grism) aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "intpix_corr_beam: Only grism dispersion solution can be corrected.\n"); // determine the correction factor versus wavelength ipclambda = get_ipclambda(actbeam, conf_file_path, ipcorr); print_interp(ipclambda); // apply the correction to the PET apply_corr_pet(ipclambda, PET); // free the configuration structure free_aperture_conf(conf); // free the memory in the interpolator free_interp(ipclambda); }
/** * The function evaluates the a polynomial given in the input * at a specific point, which also is given in the input. * The polynomial follows the description of 2D vatriable * quantities as given in the aXe manual. * * @param coeffs - the coefficients of the polynomial * @param p - the point to evaluate the polynomial * @param beamID - beamID of the beam of interest (A=0, B=1, etc...) * * @return res - of the polynomial at point p * */ float eval_trace_off_at_pos(gsl_vector *coeffs, d_point p, int beamID) { float n, c, res; int i, j, k; n = 0.5 * (-1.0 + sqrt(1 + 8 * coeffs->size)); if ((floor(n) - n) != 0) { aXe_message(aXe_M_FATAL, __FILE__, __LINE__, "get_trace_xoff_at_pos: " "Beam %d in configuration file does not contain a correct number of entries (i.e. " "1,3,6,10,15...,n^2/2+n/2", beamID); } i = 0; res = 0; for (j = 0; j < n; j++) { for (k = 0; k < (j + 1); k++) { c = gsl_vector_get(coeffs, i); res = res + c * pow(p.x, (j - k)) * pow(p.y, k); i++; } } return res; }
/** * Function: get_lcolumn_from_SPC_opened * The function reads the values from a column with long specified * by its name into a array of type long. The array is returned. * * Parameters: * @param SPC_ptr - pointer to the SPC extension * @param count_col - name of the column to load * @param nelems - number of elements in the column * * Returns: * @return values - pointer to a filled array */ long * get_lcolumn_from_SPC_opened(fitsfile *SPC_ptr, char colname[], int nelems) { int colnum=0; int anynul; int f_status=0; long *values; // allocate the return array; // give an error if allocation fails values = (long *) malloc(nelems * sizeof(long)); if (!values) { aXe_message (aXe_M_ERROR, __FILE__, __LINE__, "Memory allocation failed"); } // get the desired column number; // give an error if the column name // can not be read fits_get_colnum (SPC_ptr, CASEINSEN, colname, &colnum, &f_status); if (f_status) { ffrprt (stderr, f_status); aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "get_dcolumn_from_SPC_opened: " "Could not determine column %s in " " table!\n", colname); } // read all data in the column fits_read_col (SPC_ptr, TLONG, colnum, 1, 1, nelems, NULL, values, &anynul, &f_status); if (f_status) { ffrprt (stderr, f_status); aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "get_dcolumn_from_SPC_opened: " "Could not read column %s" " from BINARY table!",colname); } // return the filled array return values; }
/** * Function: get_tlength_from_dispersion * The function computes and returnes the trace length for * a given diseprsion solution and wavelength. The tracelength * value is returned. Currently only linear and quadratic * dispersio solution are considered. * * Parameters: * @param cdisp - the dispersion coefficient polynomial * @param lambda - the wavelength * * Returns: * @return tlength - the trace length */ double get_tlength_from_dispersion(gsl_vector *cdisp, float lambda) { double tlength=0.0; //double tlength_a=0.0; double det; // check whether the polynomial is linear if (cdisp->size == 2) { // compute the tracelength for linear dispersion tlength = (lambda-gsl_vector_get(cdisp, 0))/gsl_vector_get(cdisp, 1); } // check whether the polynomial is quadratic else if (cdisp->size == 3) { // compute the determinante det = gsl_vector_get(cdisp, 1) * gsl_vector_get(cdisp, 1) - 4.0 * gsl_vector_get(cdisp, 0) * gsl_vector_get(cdisp, 2); // gove error if det < 0.0 if (det < 0.0) aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "get_tlength_from_dispersion: Can not determine the tracelength since det < 0.0!\n"); // compute the tracelength tlength = (-gsl_vector_get(cdisp, 1)+sqrt(det))/(2.0*gsl_vector_get(cdisp, 2)); // tlength_a = (-gsl_vector_get(cdisp, 1)-sqrt(det))/(2.0*gsl_vector_get(cdisp, 2)); // fprintf(stdout, "plus: %f, minus: f\n", tlength, tlength_a); } else { aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "get_tlength_from_dispersion: The dispersion solution has %i coefficients and can not be inverted!\n", cdisp->size); } // return the tracelength return tlength; }
/* * Function: get_crossdisp_matrix * The function extracts the drizzle coefficients stored in the * keyword headers of an image extension and creates a matrix * to store those coefficients. The matrix is returned. * Currently the drizzle coefficients are ALWAYS stored in the * primary header of the grism images. For this reason * all keywords are read from extension '1' (hardcoded). * * Parameters: * @param filename - the image filename * @param sci_numext - the extension number * * Returns: * @return ret - the matrix with the drizzle coefficients */ gsl_matrix * get_crossdisp_matrix(char * filename, int sci_numext) { int ncoeffs; int i; gsl_matrix * ret; px_point pixmax; char templt[FLEN_CARD]; float acoeff, tmp; // get the number of coefficients tmp = get_float_from_keyword(filename, 1, "DRZCNUM"); // tmp = get_float_from_keyword(filename, sci_numext, "DRZCNUM"); if (isnan(tmp)){ // in case that the keyword does not exist, // find a nice way out of the door aXe_message(aXe_M_FATAL, __FILE__, __LINE__, "Could not find drizzle keywords in: %s\n", filename); ret = gsl_matrix_alloc(1,1); gsl_matrix_set(ret, 0,0,GSL_NAN); return ret; } else { // cast the value to int ncoeffs = (int)tmp; } // allocate the matrix, set it to the default ret = gsl_matrix_alloc(2,ncoeffs); gsl_matrix_set_all (ret, 0.0); // go over the number of coefficients for (i=0; i<ncoeffs; i++){ // set the name for the x-coefficient, get it and store it sprintf (templt, "DRZ%1iX%02i", sci_numext, i+1); // acoeff = get_float_from_keyword(filename, sci_numext, templt); acoeff = get_float_from_keyword(filename, 1, templt); gsl_matrix_set(ret, 0,i,acoeff); // set the name for the y-coefficient, get it and store it sprintf (templt, "DRZ%1iY%02i", sci_numext, i+1); // acoeff = get_float_from_keyword(filename, sci_numext, templt); acoeff = get_float_from_keyword(filename, 1, templt); gsl_matrix_set(ret, 1,i,acoeff); } // return the matrix return ret; }
/** * Parses a configuration file and searches for DYDX_ORDER_%c * keywords. Returns the order of the field dependent * trace relation for that order. * @param filename filename of the configuration file * @param beamID beamID of the beam of interest (A=0, B=1, etc...) * * @return disporder the order of the dispersion relation for the beam of interest */ int get_beam_trace_norder(char *filename, int beamID) { char beam[MAXCHAR]; int disporder = -1; int found = 0; int i=0; struct CfgStrings DispConfig[] = { { NULL, NULL }, { NULL, NULL } }; DispConfig[0].name = beam; sprintf(beam, "DYDX_ORDER_%c", BEAM (beamID)); CfgRead(filename, DispConfig); if ((DispConfig[0].name == beam) && (DispConfig[0].data != NULL)) { disporder = atoi(DispConfig[0].data); found = 1; } if (!found) { aXe_message(aXe_M_FATAL, __FILE__, __LINE__, "get_beam_trace_norder: %s was not found in %s.\n", beam, filename); } if (disporder<0) aXe_message(aXe_M_FATAL, __FILE__, __LINE__, "Trace polynomial must at least have one coefficients (i.e. zeroth order).\n"); // release memory i=0; while (DispConfig[i].name!=NULL) free(DispConfig[i++].data); return disporder; }
/** * Function: get_model_sed * Extracts and returns the desired model spectrum from th model structure. * Translates from the object index [1, n_models] to the spectral model * structure index [0, n_model-1]. * * Parameters: * @param spectral_models - the spectral models structure * @param modspec - the index of the desired SED * * Returns: * @return - */ energy_distrib * get_model_sed(const spectral_models *spec_mod, const int modspec) { energy_distrib *sed; if (modspec > spec_mod->n_models) aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "aXe_PETCONT: " "Model number %i does NOT exist!", modspec); // extract the desired SED sed = spec_mod->SEDlist[modspec-1]; // return the SED return sed; }
/** * Function: get_dirim_emission * The function returns from a direct object model the direct emission * object addressed by the index. The function translates from the * object index, which is in [1, n_model] to the structure index * in [0, n_model-1] * * Parameters: * @param objmodels - the object model structure * @param objspec - the 'index' of the desired direct emission model * * Returns: * @return dirim - the desired direct emission model */ dirim_emission * get_dirim_emission(const object_models *objmodels, const int objspec) { dirim_emission *dirim; if (objspec > objmodels->n_models || objspec < 1) aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "aXe_PETCONT: " "Direct emission model number %i does NOT exist!", objspec); // extract the desired SED dirim = objmodels->obj_list[objspec-1]; // return the SED return dirim; }
int check_disp_order(const gsl_vector *tmp, const int beamID, const int order) { int n; n = 0.5 * (-1.0 + sqrt (1 + 8 * tmp->size)); if ((floor (n) - n) != 0) { aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "get_disp_coeff_at_pos: " "Order %d of Beam %d does not contain a correct number of entries (i.e. " "1,3,6,10,15...,n^2/2+n/2", order, beamID); } return 1; }
/** * The function creates and loads a new flux_cube structure * The data is taken from the file specified in the input. * * @param fcube_file - the file name of the fluxcube * * @return ret - the new flux_cube structure */ flux_cube * load_fluxcube(const char fcube_file[]) { flux_cube *fcube; gsl_matrix *test; int nflux, n_ext=0; int i; // get the number of extensions n_ext = FITSextnum(fcube_file); if (n_ext <3) aXe_message(aXe_M_FATAL, __FILE__, __LINE__, "aXe_PETCONT: " "the fluxcube file %s has only %i extensions!\n", fcube_file, n_ext); // determine the number of flux images and allocate // the space for the fluxcube structure nflux = n_ext-2; fcube = alloc_fluxcube(nflux); // load XOFFS and YOFFS load_offsets(fcube_file, fcube); // load the segmentation image into the structure fcube->segmentation = load_segmentation(fcube_file); // gsl_to_FITSimage (fcube->segmentation, "gogo.fits", 1, "MOO"); // load the fluximages for (i=0; i < nflux; i++) { fcube->fluxims[i] = load_fluximage(fcube_file, i+3); } // fill the number of fluximages fcube->n_fimage = nflux; // order the fluximages and store the // vector with the ordered indices fcube->fimage_order = order_fluxims(fcube); return fcube; }
/** * The program checks if the dispersion relation of a certain beam * is given in "grism" form (polynomial) or in "prism" form * (inverse polynomial) * * @param filename filename of the configuration file * @param beamID beamID of the beam of interest (A=0, B=1, etc...) * * @return c integer to declare grism (=1) or prism (=0) */ int check_for_grism (char *filename, int beamID) { int norder, i; int c=0; // get the order of the dispersion solution norder = get_beam_disp_norder (filename, beamID); // go over all orders and check the assumption // that it is a grism for (i = 0; i < norder + 1; i++) c += check_disp_coeff (filename, 1, beamID, i); // if the assumption is right, // set the return value for grism if (c == 0) { c = 1; } // if the assumption is wrong else { // reset the variable c = 0; // check the assumption that it is a grism for (i = 0; i < norder + 1; i++) c += check_disp_coeff (filename, 0, beamID, i); // if also this assumption is wrong, // raise an error that the configuration file // is inconsistent if (c != 0) aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "check_for_grism: " "The dispersion coefficients for beam %c in file", "%s are inconsistent.", beamID, filename); } // return the result return c; }
/** * Function: get_SPC_opened * The function opens an existing SPC file and returns the pointer * to it. * As of now, the mode of opening it is automatically READWRITE. * Later on a differentiation using the free parameter "mode" * might be added to generalize the function. * * Parameters: * @param SPCname - name of the SPC file * @param mode - mode to open it (not yet used) * * Returns: * @return SPC_ptr - pointer to the opened fits file * */ fitsfile * get_SPC_opened(char SPCname[], int mode) { fitsfile *SPC_ptr; int f_status=0; // Open the OPET file for reading/writing fits_open_file (&SPC_ptr, SPCname, READWRITE, &f_status); if (f_status) { ffrprt (stdout, f_status); aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "aXe_INTPIXCORR: Could not open file: %s\n", SPCname); } // return the pointer to the fits file return SPC_ptr; }
/** * Parses a configuration file and returns a gsl vector * containing the 2D polynomial coefficient allowing one to compute * a given dispersion relation coefficient anywhere on the detector. * * @param filename filename of the configuration file * @param beamID beamID of the beam of interest (A=0, B=1, etc...) * @param order order of the coefficient for which the 2D field dependent * coefficients are queried. * * @return v a gsl_vector() containing all of the 2D field * dependent polynomial coeffiecient */ gsl_vector * get_beam_disp_order (char *filename, const int for_grism, int beamID, int order) { char beam[MAXCHAR]; int norder, found = 0; int i; gsl_vector *v = NULL; struct CfgStrings DispConfig[] = { {NULL, NULL}, {NULL, NULL} }; DispConfig[0].name = beam; norder = get_beam_disp_norder (filename, beamID); if (for_grism == 1) { sprintf (beam, "DLDP_%c_%d", BEAM (beamID), order); } else { sprintf (beam, "DLD1P_%c_%d", BEAM (beamID), order); } CfgRead (filename, DispConfig); if ((DispConfig[0].name == beam) && (DispConfig[0].data != NULL)) { v = string_to_gsl_array (DispConfig[0].data); found = 1; } if (!found) { aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "get_beam_disp_order: %s was not found in %s.\n", beam, filename); } i = 0; while(DispConfig[i].name!=NULL){ free(DispConfig[i++].data); } return v; }
/** * Function: get_num_extensions * The function determines the number of extensions in * the fits file. Here the primary extension does not count. * * Parameters: * @param spectral_models_file - pathname to the spectral models file * * Returns: * @return n_models - the number of spectral models */ int get_num_extensions(const char spectral_models_file[]) { int n_ext=0; int n_models=0; int i; int f_status=0; fitsfile *s_models; // open the fits file // report any error fits_open_file (&s_models, spectral_models_file, READONLY, &f_status); if (f_status) { ffrprt (stderr, f_status); aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "aXe_PETCONT: " "Could not open file: %s", spectral_models_file); } // do until a fits error occurs while (!f_status) { // move one extension forward fits_movrel_hdu (s_models, 1, NULL, &f_status); // count up n_ext++; } // close the fits file fits_close_file (s_models, &f_status); // the zeroth extension // does nnot count!! n_models = n_ext - 1; // return the return n_models; }
/** Generate and returns a trace structure that is computed at the given pixel p detector location. @param filename filename of the configuration file @param beamID beamID of the beam of interest (A=0, B=1, etc...) @param p A d_point object containing the position to compute the dispersion coefficients at. @return res A dispersion structure computed for beam beamID at detector pixel p. */ tracestruct * get_tracestruct_at_pos(char *filename, int beamID, d_point p) { tracestruct *res; res = malloc(sizeof(tracestruct)); if (res == NULL) { aXe_message(aXe_M_FATAL, __FILE__, __LINE__, "get_tracestruct_at_pos:" "Could not allocate tracestruct"); } res->pol = get_trace_coeffs_at_pos(filename, beamID, p); res->offset.x = get_trace_xoff_at_pos(filename, beamID, p); res->offset.y = get_trace_yoff_at_pos(filename, beamID, p); res->ID = beamID; res->cpoint.x = p.x; res->cpoint.y = p.y; sprintf(res->file, "%s", filename); return res; }
/** * Parses a configuration file and returns a gsl vector * containing the 2D polynomial coefficient allowing one to compute * a given trace coefficient anywhere on the detector. * @param filename filename of the configuration file * @param beamID beamID of the beam of interest (A=0, B=1, etc...) * @param order order of the coefficient for which the 2D field dependent * coefficients are queried. * * @return v A gsl_vector() containing all of the 2D field dependent polynomial coeffiecient */ gsl_vector * get_beam_trace_order(char *filename, int beamID, int order) { char beam[MAXCHAR]; int norder; int found = 0; int i=0; gsl_vector *v= NULL; struct CfgStrings DispConfig[] = { { NULL, NULL }, { NULL, NULL } }; DispConfig[0].name = beam; norder = get_beam_disp_norder(filename, beamID); sprintf(beam, "DYDX_%c_%d", BEAM (beamID), order); CfgRead(filename, DispConfig); if ((DispConfig[0].name == beam) && (DispConfig[0].data != NULL)) { v = string_to_gsl_array(DispConfig[0].data); found = 1; } if (!found) { aXe_message(aXe_M_FATAL, __FILE__, __LINE__, "get_beam_trace_order: %s was not found in %s.\n", beam, filename); } // release memory i=0; while (DispConfig[i].name!=NULL) free(DispConfig[i++].data); return v; }
/** * The function creates a a dirobject on the basis * of an object and the pixel coos of a point * which is part of that object. * * @param flt_point - the fluxcube structure * @param actobject - the object list * * @return dirobject - the dirobject created */ dirobject * dirobject_from_segpoint(const px_point flt_point, const object *actobject) { dirobject *actdir; // allocate space for the dirobject actdir = (dirobject *) malloc (sizeof (dirobject)); if (actdir == NULL) aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "fill_dirobject:" " Could not allocate" " memory for a dirobject object"); // transfer refpoint and ID actdir->ID = actobject->ID; actdir->refpoint.x = actobject->beams[0].refpoint.x; actdir->refpoint.y = actobject->beams[0].refpoint.y; // derive and store min/max in x/y for the corners actdir->ix_min = flt_point.x; actdir->ix_max = flt_point.x; actdir->iy_min = flt_point.y; actdir->iy_max = flt_point.y; // derive the distortion scales along the major an minor axis actdir->drzscale.x = 1.0; actdir->drzscale.y = 1.0; // set the variable actdir->bb_sed = 0; // make it a dummy actdir->SED = NULL; // return the new dirobject return actdir; }
/** * Routine to read in the MMAG_MARK keyword for a specific beam * from the configuration file * * @param filename filename of the configuration file * @param beamID beamID of the beam of interest (A=0, B=1, etc...) * * @return mmag_mark mag_mark-value for that beam */ float get_beam_mmag_mark (char *filename, int beamID) { char beam[MAXCHAR]; float mmag_mark = -1; int found = 0; int i=0; struct CfgStrings DispConfig[] = { {NULL, NULL}, {NULL, NULL} }; DispConfig[0].name = beam; sprintf (beam, "MMAG_MARK_%c", BEAM (beamID)); CfgRead (filename, DispConfig); if ((DispConfig[0].name == beam) && (DispConfig[0].data != NULL)) { mmag_mark = atof (DispConfig[0].data); found = 1; } if (!found) { aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "get_beam_mmag_mark: %s was not found in %s.\n", beam, filename); } // release memory i=0; while(DispConfig[i].name!=NULL) free(DispConfig[i++].data); // return the value return mmag_mark; }
/** * Function: get_ipclambda * The function creates an interpolator for the intra-pixel correction * as a function of wavelength based on this correction as function * of fractional y-pixel and the full calibration information * on a beam. * The interpolator is created after stepping along the beam trace * and combining the wavelength values with the correction values * at the trace positions. * * Parameters: * @param actbeam - the beam to find the correction values for * @param conf_file_path - the full path to the aXe cofiguration file * @param ipcorr - the correction values as function of y-fraction * * Returns: * @return ipclambda - the correction values as function of wavelength */ interpolator * get_ipclambda(beam actbeam, char conf_file_path[], interpolator *ipcorr) { gsl_vector *xvalues; gsl_vector *cvalues; gsl_vector *lambdas; double *cv; double *lv; interpolator *ipclambda; int i=0; int j=0; // get the x values around the reference point xvalues = get_ipc_xvalues(actbeam); // get the correction factors for these x-values cvalues = get_ipc_cvalues(actbeam, ipcorr, xvalues); // get the wavelength at the correction factors lambdas = get_ipc_lambdas(actbeam, conf_file_path, xvalues); // allocate memory for the dependent values cv = (double *) malloc(cvalues->size * sizeof(double)); if (!cv) { aXe_message (aXe_M_ERROR, __FILE__, __LINE__, "Memory allocation failed"); } // allocate memory for the independent values lv = (double *) malloc(cvalues->size * sizeof(double)); if (!lv) { aXe_message (aXe_M_ERROR, __FILE__, __LINE__, "Memory allocation failed"); } if (gsl_vector_get(lambdas, lambdas->size-1) > gsl_vector_get(lambdas, 0)) { // transfer the values from the // gsl vectors to the c-vectors for (i = 0; i < cvalues->size; i++) { cv[i] = gsl_vector_get(cvalues, i); lv[i] = gsl_vector_get(lambdas, i); } } else { // transfer the values from the // gsl vectors to the c-vectors // invert the order from the // gsl-vectors j = cvalues->size - 1; for (i = 0; i < cvalues->size; i++) { cv[j] = gsl_vector_get(cvalues, i); lv[j] = gsl_vector_get(lambdas, i); j--; } } // create the interpolator ipclambda = create_interp(cvalues->size, FILTER_INTERP_TYPE, lv, cv); // free the memory allocated to // the vectors gsl_vector_free(xvalues); gsl_vector_free(cvalues); gsl_vector_free(lambdas); // return the interpolator return ipclambda; }
/** * Function: intpix_corr_beam * The functio corrects a full spectrum for the intrapixel sensitivity * variations. * For every spectral element its fractional y-value is determined, * and then the correction factor for this y-value is computed * and applied to the appropriate elements of the spectral bin. * * Parameters: * @param actbeam - the beam to examine * @param conf_file_path - the full pathname too the configuration file * @param ipcorr - the interpolator with the correction factor * @param SPC - the full spectrum to correct * * Returns: * @return - */ void intpix_corr_beam(beam actbeam, char conf_file_path[], interpolator *ipcorr, full_spectr *SPC) { int index=0; int for_grism=1; double cfactor; double lambda; gsl_vector *cdisp; d_point pixel; dispstruct *beam_disp; aperture_conf *conf; // load the configuration file conf = get_aperture_descriptor(conf_file_path); // check whether it is grism (for_grism=1) // or prism (for_grism=0) data // give an error if there is a prism solution for_grism = check_for_grism (conf_file_path, actbeam.ID); if (!for_grism) aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "intpix_corr_beam: Only grism dispersion solution can be corrected.\n"); // get the wavelength dispersion relation at // position "refpoint". conf->refx and conf->refy // are used at this point to allow for a non (0,0) centered // 2D field dependence. pixel.x = actbeam.refpoint.x - conf->refx; pixel.y = actbeam.refpoint.y - conf->refy; // derive the dispersion at the object position beam_disp = get_dispstruct_at_pos(conf_file_path, for_grism, actbeam.ID, pixel); // skipp high order zeroes in the dispersion solution cdisp = condense_dispersion(beam_disp->pol); for (index=0; index < SPC->nelems; index++) { lambda = SPC->fgr_spec->spec[index].lambda_mean; if (!gsl_isnan (lambda) && lambda) { cfactor = get_intpix_corr(&actbeam, cdisp, ipcorr, lambda); fprintf(stdout, "lambda: %e, factor: %e\n", lambda, cfactor); /* SPC->fgr_spec->spec[index].count = SPC->fgr_spec->spec[index].count / cfactor; SPC->fgr_spec->spec[index].error = SPC->fgr_spec->spec[index].error / cfactor; SPC->fgr_spec->spec[index].flux = SPC->fgr_spec->spec[index].flux / cfactor; SPC->fgr_spec->spec[index].ferror = SPC->fgr_spec->spec[index].ferror / cfactor; SPC->bck_spec->spec[index].count = SPC->bck_spec->spec[index].count / cfactor; SPC->bck_spec->spec[index].error = SPC->bck_spec->spec[index].error / cfactor; SPC->bck_spec->spec[index].flux = SPC->bck_spec->spec[index].flux / cfactor; SPC->bck_spec->spec[index].ferror = SPC->bck_spec->spec[index].ferror / cfactor; SPC->obj_spec->spec[index].count = SPC->obj_spec->spec[index].count / cfactor; SPC->obj_spec->spec[index].error = SPC->obj_spec->spec[index].error / cfactor; SPC->obj_spec->spec[index].flux = SPC->obj_spec->spec[index].flux / cfactor; SPC->obj_spec->spec[index].ferror = SPC->obj_spec->spec[index].ferror / cfactor; /* this is the wqrong version!! SPC->fgr_spec->spec[index].count = SPC->fgr_spec->spec[index].count * cfactor; SPC->fgr_spec->spec[index].error = SPC->fgr_spec->spec[index].error * cfactor; SPC->fgr_spec->spec[index].flux = SPC->fgr_spec->spec[index].flux * cfactor; SPC->fgr_spec->spec[index].ferror = SPC->fgr_spec->spec[index].ferror * cfactor; SPC->bck_spec->spec[index].count = SPC->bck_spec->spec[index].count * cfactor; SPC->bck_spec->spec[index].error = SPC->bck_spec->spec[index].error * cfactor; SPC->bck_spec->spec[index].flux = SPC->bck_spec->spec[index].flux * cfactor; SPC->bck_spec->spec[index].ferror = SPC->bck_spec->spec[index].ferror * cfactor; SPC->obj_spec->spec[index].count = SPC->obj_spec->spec[index].count * cfactor; SPC->obj_spec->spec[index].error = SPC->obj_spec->spec[index].error * cfactor; SPC->obj_spec->spec[index].flux = SPC->obj_spec->spec[index].flux * cfactor; SPC->obj_spec->spec[index].ferror = SPC->obj_spec->spec[index].ferror * cfactor; */ } } // free the configuration structure free_aperture_conf(conf); // free the dispersion struct free_dispstruct(beam_disp); // free the memory for the dispersion gsl_vector_free(cdisp); }
int main (int argc, char *argv[]) { char *opt; char grism_image[MAXCHAR]; char grism_image_path[MAXCHAR]; char sex_catalog[MAXCHAR]; char sex_catalog_path[MAXCHAR]; char aper_file[MAXCHAR]; char aper_file_path[MAXCHAR]; char conf_file[MAXCHAR]; char conf_file_path[MAXCHAR]; float mmag_extract, mmag_mark, mfwhm, dmag; int leaveout_ignored = 1; int auto_reorient = 1; int no_orient = 0; int slitless_geom=0; int num; char ext[MAXCHAR]; double lambda_mark=0.0; int bck_mode=0; aperture_conf *conf; SexObject **os; object **oblist; observation *obs; if ((argc < 3) || (opt = get_online_option ("help", argc, argv))) { fprintf (stdout, "ST-ECF European Coordinating Facility\n" "aXe_GOL2AF Version %s:\n" " aXe task to create an Object Aperture File (OAF)\n" " or a Background Aperture File (BAF) (-bck option) using an\n" " input Sextractor Grism Object List (GOL).\n" " The AF files contain information about each object (aperture)\n" " and information about the various beams (orders) in each of \n" " these apertures. These are simple text files which can be\n" " edited by hand. The IGNORE keywords can be set to 1 if a\n" " particular beam (order) is to be ignored during the extraction\n" " process. The MMAG_EXTRACT and MMAG_MARK keyword of each beam\n" " listed in the aXe configuration file determine if a particluar\n " " beam is flagged to be extracted or completely ignored.\n" " The -dmag switch can be used to adjust these. See the aXe manual\n" " for more details. An extraction width multiplicative factor can\n" " be set with the -mfwhm option (e.g. to generate BAF containing\n" " broader apertures).\n" " By default, when the extraction angle is too close to the\n" " dispersion direction, 90 degrees are added to the extraction\n" " angle. This can be overwritten by using the -no_auto_orient\n" " online parameter.\n" "\n" " Input FITS mages are looked for in $AXE_IMAGE_PATH\n" " aXe config file is looked for in $AXE_CONFIG_PATH\n" " All outputs are writen to $AXE_OUTPUT_PATH\n" "\n" "Usage:\n" " aXe_GOL2AF [g/prism image filename] [aXe filename] [options]\n" "\n" "Options:\n" " -bck - to generate a BAF instead of an OAF file\n" " -SCI_hdu=[integer] - overwrite the default from the \n" " configuration file \n" " -mfwhm=[float] - an extraction width multiplicative factor.\n" " -exclude_faint - do not even list faint object in the result.\n" " -out_AF=[string] - overwrites the default output aper filename.\n" " -in_GOL=[string] - overwrites the default input catalog name.\n" " -auto_orient=[0/1] - set to 0 to disable the automatic extraction\n" " orientation.\n" " -no_orient - disable tilted extraction (vertical\n" " extraction only).\n" " -dmag=[float] - A number to add to the MMAG_EXTRACT and\n" " MMAG_MARK values.\n" "\n" "Example: ./aXe_GOL2AF slim_grism.fits -bck -dmag=2 -mfwhm=2\n" "\n",RELEASE); exit (1); } fprintf (stdout, "aXe_GOL2AF: Starting...\n"); /* Get the Grism/Prism image name */ strcpy (grism_image, argv[1]); build_path (AXE_IMAGE_PATH, grism_image, grism_image_path); /* Get the name of the configuration file */ strcpy (conf_file, argv[2]); build_path (AXE_CONFIG_PATH, conf_file, conf_file_path); /* Read the configuration file */ conf = get_aperture_descriptor (conf_file_path); /* Determine where the various extensions are in the FITS file */ get_extension_numbers(grism_image_path, conf,conf->optkey1,conf->optval1); if ((opt = get_online_option ("SCI_hdu", argc, argv))) { char str[MAXCHAR]; strcpy(str,opt); conf->science_numext = atoi(str); } /* Get or set up the name of the output Aperture File */ if ((opt = get_online_option ("out_AF", argc, argv))) { /* get it */ strcpy (aper_file, opt); strcpy (aper_file_path, opt); } else { /* set the name automatically */ /* Get the name of the aperture file type, OAF or BAF */ if ((opt=get_online_option ("bck",argc,argv))) { strcpy (ext,".BAF"); bck_mode=1; } else { strcpy (ext,".OAF"); } strcpy (aper_file, argv[1]); replace_file_extension (grism_image, aper_file, ".fits", ext, conf->science_numext); build_path (AXE_OUTPUT_PATH, aper_file, aper_file_path); } /* Set the option extraction width multiplicative factor */ if ((opt = get_online_option ("mfwhm", argc, argv))) { { /*char str[MAXCHAR]; strcpy (str, opt); sscanf (str, "%f", &mfwhm);*/ mfwhm = atof(opt); } } else { mfwhm = 1.0; } if ((opt = get_online_option ("dmag", argc, argv))) { { /*char str[MAXCHAR]; strcpy (str, opt); sscanf (str, "%f", &mfwhm);*/ dmag = atof(opt); } } else { dmag = 0.0; } /* Set the option to include object that are too faint into the output aperture file. */ if ((opt = get_online_option ("exclude_faint", argc, argv))) { leaveout_ignored = 1; } else { leaveout_ignored = 0; } /* Set the auto orientation mode for extraction on or off, default is on (=1) if ((opt = get_online_option ("auto_orient",argc,argv))) { if (!atof(opt)) auto_reorient = 0; } else { auto_reorient = 1; } */ // set the flag for using slitless geometry, // to say extraction parameters optimized for // slitless geometry if ((opt = get_online_option ("slitless_geom",argc,argv))) if (!atof(opt)) //slitless_geom = 0; auto_reorient = 0; else //slitless_geom = 1; auto_reorient = 1; /* Set the option to disbale tilted extraction */ if ((opt = get_online_option ("orient", argc, argv))) { if (!atof(opt)) auto_reorient = 2; } /* Get or generate the name of the sextractor catalog to read */ if ((opt = get_online_option ("in_GOL", argc, argv))) { strcpy (sex_catalog, opt); strcpy (sex_catalog_path, opt); } else { strcpy (sex_catalog, argv[1]); replace_file_extension (grism_image, sex_catalog, ".fits", ".cat", conf->science_numext); build_path (AXE_OUTPUT_PATH, sex_catalog, sex_catalog_path); } if ((opt = get_online_option ("lambda_mark", argc, argv))) { lambda_mark = atof(opt); } else{ lambda_mark = 800.0; } // check the configuration file for the smoothin keywords if (!check_conf_for_slitlessgeom(conf, auto_reorient)) //if (!check_conf_for_slitlessgeom(conf, slitless_geom)) aXe_message(aXe_M_FATAL, __FILE__, __LINE__, "aXe_GOL2AF: Either the configuration file %s does not contain\n" "the necessary keywords for the slitless geometry: POBJSIZE,\n" "or this keyword has an unreasonable value < 0.0!\n", conf_file_path); fprintf (stdout, "aXe_GOL2AF: Main configuration file name: %s\n", conf_file_path); fprintf (stdout, "aXe_GOL2AF: Input data file name: %s\n", grism_image_path); fprintf (stdout, "aXe_GOL2AF: SCI extension number: %d\n", conf->science_numext); fprintf (stdout, "aXe_GOL2AF: Input grism object list (GOL): %s\n", sex_catalog_path); fprintf (stdout, "aXe_GOL2AF: Output aperture file name: %s\n", aper_file_path); fprintf (stdout, "aXe_GOL2AF: FWHM multiplicative factor: %f\n", mfwhm); fprintf (stdout, "aXe_GOL2AF: Dmag adjustment: %f\n", dmag); if (leaveout_ignored) fprintf (stdout, "aXe_GOL2AF: Ignored object will not " "be included in the output aperture file\n"); if (!leaveout_ignored) fprintf (stdout, "aXe_GOL2AF: Ignored object will be " "included in the output aperture file\n"); if (auto_reorient != 2) fprintf (stdout, "aXe_GOL2AF: Tilted extraction will be performed.\n"); if (auto_reorient == 0) fprintf (stdout, "aXe_GOL2AF: The extraction geometry follows the object\n"); if (auto_reorient == 1) //if (slitless_geom) fprintf (stdout, "aXe_GOL2AF: Extraction geometry is optimized for slitless spectroscopy.\n"); //else // fprintf (stdout, // "aXe_GOL2AF: The extraction geometry follows the object, but may switch.\n"); if (auto_reorient==2) fprintf (stdout, "aXe_GOL2AF: NO tilted extraction will be performed (e.g. vertical only).\n"); fprintf (stdout, "aXe_GOL2AF: Wavelength for object selection [nm]: %f\n", lambda_mark); fprintf(stdout,"\n\n"); // extend the beams when creating // BAF's if (bck_mode) extend_config_beams(conf); fprintf (stdout, "aXe_GOL2AF: Loading object list..."); os = get_SexObject_from_catalog (sex_catalog_path, lambda_mark); fprintf (stdout, "Done.\n");fflush(stdout); fprintf (stdout, "aXe_GOL2AF: Reading image..."); obs = load_empty_image (grism_image_path, conf->science_numext); fprintf (stdout, "Done.\n");fflush(stdout); fprintf (stdout, "aXe_GOL2AF: Generating aperture list..."); //if (!slitless_geom) //use the old, aXe-1.6 code //oblist = SexObjects_to_oblist(os, obs, conf, conf_file_path, mfwhm, dmag, // auto_reorient, bck_mode); // else // use the new aXe-1.7 code oblist = SexObjects_to_oblistII(os, obs, conf, conf_file_path, mfwhm, dmag, auto_reorient, bck_mode); fprintf (stdout, "Done.\n");fflush(stdout); fprintf (stdout, "aXe_GOL2AF: Writing aperture file...");fflush(stdout); num = object_list_to_file (oblist, aper_file_path, leaveout_ignored); fprintf (stdout, "%d beams written.\n", num); free_SexObjects (os); free_oblist (oblist); fprintf (stdout, "aXe_GOL2AF: Done...\n"); exit (0); }
/** * Function: load_SED_from_fitsext * The function creates a energy distribution from the data stored * in a fits file extension. The data must be stored in the columns * "wavelength" and "flux". * * Parameters: * @param spectral_models_file - pathname to the spectral models file * @param s_models - pointer to the fits file extension * * Returns: * @return sed - the energy distribution created */ energy_distrib * load_SED_from_fitsext(const char spectral_models_file[], fitsfile *s_models) { int f_status=0; int anynul; long nrows=0; int colnum1; int colnum2; energy_distrib *sed; double *sed_wavs; double *sed_flux; // allocate memory for the energy distribution sed = (energy_distrib *) malloc(sizeof(energy_distrib)); // get number of rows fits_get_num_rows (s_models, &nrows, &f_status); if (f_status) { ffrprt (stderr, f_status); aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "load_SED_from_fitsext: " "Could not determine the number of rows in" " table %s",spectral_models_file); } // allocate memory for the data sed_wavs = (double *) malloc(nrows*sizeof(double)); if (!sed_wavs) { aXe_message (aXe_M_ERROR, __FILE__, __LINE__, "Memory allocation failed"); } sed_flux = (double *) malloc(nrows*sizeof(double)); if (!sed_flux) { aXe_message (aXe_M_ERROR, __FILE__, __LINE__, "Memory allocation failed"); } // get the column number for the wavelength fits_get_colnum (s_models, CASEINSEN, "WAV_NM", &colnum1, &f_status); if (f_status) { ffrprt (stderr, f_status); aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "create_interp_ftable: " "Could not determine column %s in " " table %s", "WAV_NM", spectral_models_file); } // read the wavelength fits_read_col (s_models, TDOUBLE, colnum1, 1, 1, nrows, NULL, sed_wavs, &anynul, &f_status); if (f_status) { ffrprt (stderr, f_status); aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "load_SED_from_fitsext: " "Could not read content of WAVELENGTH column " " from BINARY table %s", spectral_models_file); } // get the column number for the flux fits_get_colnum (s_models, CASEINSEN, "FLUX", &colnum2, &f_status); if (f_status) { ffrprt (stderr, f_status); aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "create_interp_ftable: " "Could not determine column %s in " " table %s", "FLUX", spectral_models_file); } // read the flux column fits_read_col (s_models, TDOUBLE, colnum2, 1, 1, nrows, NULL, sed_flux, &anynul, &f_status); if (f_status) { ffrprt (stderr, f_status); aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "load_SED_from_fitsext: " "Could not read content of FLUX column " " from BINARY table %s", spectral_models_file); } // transfer the vector and length information // to the SED object sed->npoints = nrows; sed->wavelength = sed_wavs ; sed->flux = sed_flux; // allocate some structures for the interpolator sed->interp = gsl_interp_alloc (SMODEL_INTERP_TYPE, (size_t)sed->npoints ); sed->accel = gsl_interp_accel_alloc (); // initialize the iterpolator gsl_interp_init (sed->interp, sed->wavelength, sed->flux, (size_t)sed->npoints); // return the energy distribution return sed; }
/** * Function: get_ALL_from_next_in_SPC * The function creates and fills a full spectrum structure with * the content of a SPC table extension. This is only done when, * according to the beam ID, this beam should be corrected. * For extensions with higher order beams which are not corrected * an emply structure is returned. * * Parameters: * @param SPCn_ptr - pointer to the opened SPC file * @param aperID - pointer to aperture identification number * @param beamID - pointer to beam identification number * * Returns: * @return SPC - the full spectrum structure */ full_spectr * get_ALL_from_next_in_SPC(fitsfile *SPC_ptr, int *aperID, int *beamID) { int f_status=0, hdutype; long tmp; //long nrows=0; char comment[FLEN_COMMENT]; full_spectr *SPC; fits_movrel_hdu (SPC_ptr, 1, &hdutype, &f_status); if (f_status) { *aperID = -1; *beamID = -1; SPC = NULL; return SPC; } // read the beam ID number fits_read_key_lng (SPC_ptr, "BEAMID", &tmp, comment, &f_status); if (f_status) { ffrprt (stderr, f_status); aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "get_ALL_from_next_in_SPC: Error getting index keyword OBJECTID"); } *beamID = (int)tmp; // check whether this beam should be correct if (*beamID > CORRMAX) { // set it to NULL and return SPC = NULL; // fprintf (stdout, "aXe_PETFF: Skipping beam: %c.\n", BEAM(*beamID)); return SPC; } // the beam shall be corrected and // first must be read in SPC = (full_spectr *) malloc (sizeof (full_spectr )); // transfer the beam ID SPC->beamID = (int)tmp; // read the aperture number fits_read_key_lng (SPC_ptr, "OBJECTID", &tmp, comment, &f_status); if (f_status) { ffrprt (stderr, f_status); aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "get_ALL_from_next_in_SPC: Error getting index keyword OBJECTID"); } // transfer the aperture ID *aperID = (int)tmp; SPC->aperID = (int)tmp; // Get the number of rows fits_get_num_rows (SPC_ptr, &tmp, &f_status); if (f_status) { ffrprt (stderr, f_status); aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "get_ALL_from_next_in_SPC: " "Could not determine the number of rows in" " correction function table!"); } SPC->nelems = (int)tmp; // load the background subtracted object spectrum SPC->obj_spec = get_spectrum_from_SPC(SPC_ptr, "COUNT", "ERROR", SPC->nelems); // load the total object spectrum SPC->fgr_spec = get_spectrum_from_SPC(SPC_ptr, "TCOUNT", "TERROR", SPC->nelems); // load the background spectrum SPC->bck_spec = get_spectrum_from_SPC(SPC_ptr, "BCOUNT", "BERROR", SPC->nelems); // return the filled structure return SPC; }
int main (int argc, char *argv[]) { char *opt; char grism_file[MAXCHAR]; char grism_file_path[MAXCHAR]; char aper_file[MAXCHAR]; char aper_file_path[MAXCHAR]; char obj_PET_file[MAXCHAR]; char obj_PET_file_path[MAXCHAR]; char bck_PET_file[MAXCHAR]; char bck_PET_file_path[MAXCHAR]; char conf_file[MAXCHAR]; char conf_file_path[MAXCHAR]; char SPC_file[MAXCHAR]; char SPC_file_path[MAXCHAR]; char SPC_opt_file[MAXCHAR]; char SPC_opt_file_path[MAXCHAR]; char WHT_file[MAXCHAR]; char WHT_file_path[MAXCHAR]; char label[MAXCHAR]; int i, index, dobck = 0, noflux = 1; object **oblist; FITScards *cards; ap_pixel *obj_PET = NULL, *bck_PET = NULL; observation *obs; //tracestruct *trace; aperture_conf *conf; spectrum *obj_spec = NULL, *bck_spec = NULL, *sobj_spec = NULL; spectrum *resp; response_function *resp_func; calib_function *wl_calibration; fitsfile *OPET_ptr, *BPET_ptr; int f_status = 0; fitsfile *SPC_ptr, *SPC_opt_ptr, *WHT_ptr; gsl_matrix *weights; drzstamp *modvar; int obj_aperID, obj_beamID, objindex; int bck_aperID, bck_beamID; char table[MAXCHAR], table_path[MAXCHAR]; //char comment[FLEN_COMMENT]; int empty; int drizzle; int quant_cont=0; int opt_weights=0; int for_grism=0; int smooth_conv=0; d_point smooth_params; double exptime; double sky_cps; drzstamp_dim dimension; gsl_matrix *coverage; if (((argc < 3)) || (opt = get_online_option ("help", argc, argv))) { fprintf (stdout, "ST-ECF European Coordinating Facility\n" "Copyright (C) 2002 Martin Kuemmel\n" "aXe_PET2SPC Version %s:\n" " aXe task that produces 1-D, binned spectra using information\n" " contained in a OPET and a BPET. A 1-D spectrum is generated\n" " for each beam in each of both the OPET and the BPET files\n" " The binned background spectra of each beam (order) is then\n" " subtraced from the corresponding spectra form the OPET. Th\ne" " background subtraction (and reading a BPET altogether can be\n" " avoided by using the -noBPET option\n" " An SPC file, a multi-extension FITS file containing binned\n" " spectra is produced. Each extension (named after the beam ID,\n" " e.g. 11B for aperture (object) 11,beam (order) B) contains the\n" " following columns:\n" "\n" " LAMBDA ; the wavelength (in A)\n" " TCOUNT ; the total number of counts (in DN)\n" " TERROR ; the error in TERRORS (in DN)\n" " BCOUNT ; the estimated number of counts from the\n" " background (in DN)\n" " BERROR ; the error in BCOUNTS (in DN)\n" " COUNT ; the estimated number of counts from the\n" " object (in DN)\n" " ERROR ; the error in COUNTS (in DN)\n" " FLUX ; the estimated flux (in erg/s/cm^2/A)\n" " FERROR ; the error in FLUX (in erg/s/cm^s/A)\n" " WEIGHT ; weight (in pixels)\n" "\n" " Input FITS mages are looked for in $AXE_IMAGE_PATH\n" " aXe config file is looked for in $AXE_CONFIG_PATH\n" " All outputs are writen to $AXE_OUTPUT_PATH\n" "\n" "Usage:\n" " aXe_PET2SPC [g/prism image filename] [aXe config file name] [options]\n" "\n" "Options:\n" " -noBPET - to disable the use of a BPET file\n" " -noflux - to disable the flux calibration\n" " -drz - use $AXE_DRIZZLE_PATH to locate the grism-, OAF-\n" " - and PET-files instead of $AXE_IMAGE/OUTPUT_PATH\n" " -in_AF=[string] - overwrite the default input Aperture File name\n" " -OPET=[string] - overwrite the default input Object PET file name\n" " -BPET=[string] - overwrite the default input Background PET\n" " file name\n" " -out_SPC=[string] - overwrite the default output SPC file name\n" "\n" "Example:\n" " ./aXe_PET2SPC slim_grism.fits SLIM.conf.A.0\n" "\n",RELEASE); exit (1); } // make a general opening statement fprintf (stdout, "aXe_PET2SPC: Starting...\n"); // get the name of the flt-file index = 0; strcpy (grism_file, argv[++index]); if ((opt = get_online_option ("drz", argc, argv))) { build_path (AXE_DRIZZLE_PATH, grism_file, grism_file_path); drizzle=1; } else { build_path (AXE_IMAGE_PATH, grism_file, grism_file_path); drizzle=0; } // get the name of the configuration file strcpy (conf_file, argv[++index]); build_path (AXE_CONFIG_PATH, conf_file, conf_file_path); // load the configuration file conf = get_aperture_descriptor (conf_file_path); // Determine where the various extensions are in the FITS file get_extension_numbers(grism_file_path, conf,conf->optkey1,conf->optval1); // Build aperture file name replace_file_extension (grism_file, aper_file, ".fits", ".OAF", conf->science_numext); if (drizzle) build_path (AXE_DRIZZLE_PATH, aper_file, aper_file_path); else build_path (AXE_OUTPUT_PATH, aper_file, aper_file_path); // Build object PET file name replace_file_extension (grism_file, obj_PET_file, ".fits", ".PET.fits", conf->science_numext); // make the total filename if (drizzle) build_path (AXE_DRIZZLE_PATH, obj_PET_file, obj_PET_file_path); else build_path (AXE_OUTPUT_PATH, obj_PET_file, obj_PET_file_path); // Build background PET file name replace_file_extension (grism_file, bck_PET_file, ".fits", ".BCK.PET.fits", conf->science_numext); // make the total filename if (drizzle) build_path (AXE_DRIZZLE_PATH, bck_PET_file, bck_PET_file_path); else build_path (AXE_OUTPUT_PATH, bck_PET_file, bck_PET_file_path); // make a non-standard AF name if necessary if ((opt = get_online_option ("in_AF", argc, argv))) { strcpy(aper_file,opt); strcpy(aper_file_path,opt); } // make a non-standard PET name if necessary if ((opt = get_online_option ("OPET", argc, argv))) { strcpy(obj_PET_file,opt); strcpy(obj_PET_file_path,opt); } // make a non-standard BPET name if necessary if ((opt = get_online_option ("BPET", argc, argv))) { strcpy(bck_PET_file,opt); strcpy(bck_PET_file_path,opt); } // set the flagg for no background subtraction if ((opt = get_online_option ("noBPET",argc,argv))) { dobck = 0; strcpy(bck_PET_file,"None"); strcpy(bck_PET_file_path, "None"); } else { dobck = 1; } // set the flagg for flux if ((opt = get_online_option ("noflux",argc,argv))) noflux = 1; else noflux = 0; // check for the weights flagg, // set the file name if the flagg is set if ((opt = get_online_option ("opt_weights",argc,argv))) opt_weights = 1; else opt_weights = 0; // read the trigger for smoothing the sensitivity if ((opt = get_online_option ("smooth_conv",argc,argv))) smooth_conv = 1; else smooth_conv = 0; if ((opt = get_online_option ("out_SPC", argc, argv))) { strcpy (SPC_file, opt); strcpy (SPC_file_path, opt); if (opt_weights) { replace_file_extension (SPC_file, SPC_opt_file, ".fits", "_opt.SPC.fits", -1); replace_file_extension (SPC_file_path, SPC_opt_file_path, ".fits", "_opt.SPC.fits", -1); replace_file_extension (SPC_opt_file, WHT_file, ".SPC.fits", ".WHT.fits", -1); replace_file_extension (SPC_opt_file_path, WHT_file_path, ".SPC.fits", ".WHT.fits", -1); } } else { replace_file_extension (obj_PET_file, SPC_file, ".PET.fits", ".SPC.fits", -1); if (drizzle) build_path (AXE_DRIZZLE_PATH, SPC_file, SPC_file_path); else build_path (AXE_OUTPUT_PATH, SPC_file, SPC_file_path); if (opt_weights) { replace_file_extension (obj_PET_file, SPC_opt_file, ".PET.fits", "_opt.SPC.fits", -1); replace_file_extension (SPC_opt_file, WHT_file, ".SPC.fits", ".WHT.fits", -1); if (drizzle) { build_path (AXE_DRIZZLE_PATH, SPC_opt_file, SPC_opt_file_path); build_path (AXE_DRIZZLE_PATH, WHT_file, WHT_file_path); } else { build_path (AXE_OUTPUT_PATH, SPC_opt_file, SPC_opt_file_path); build_path (AXE_OUTPUT_PATH, WHT_file, WHT_file_path); } } } // check the configuration file for the smoothin keywords if (!check_conf_for_smoothing(conf, smooth_conv)) aXe_message(aXe_M_FATAL, __FILE__, __LINE__, "aXe_PET2SP: Either the configuration file %s does not contain\n" "the necessary keywords for the smoothing (POBJSIZE, SMFACTOR),\n" "or one of these keywords has an unreasonable value < 0.0!\n", conf_file_path); // give feedback onto the screen: // report on input and output // and also on specific parameter fprintf (stdout, "aXe_PET2SPC: Input configuration file name: %s\n", conf_file_path); fprintf (stdout, "aXe_PET2SPC: Input Object Aperture file name: %s\n", aper_file_path); fprintf (stdout, "aXe_PET2SPC: Input Object PET file name: %s\n", obj_PET_file_path); if (dobck) fprintf (stdout, "aXe_PET2SPC: Input Background PET file name: %s\n", bck_PET_file_path); fprintf (stdout, "aXe_PET2SPC: Output SPC file name: %s\n", SPC_file_path); if (opt_weights) { fprintf (stdout, "aXe_PET2SPC: Computing optimal weights.\n"); fprintf (stdout, "aXe_PET2SPC: Optimized SPC file name: %s\n", SPC_opt_file_path); fprintf (stdout, "aXe_PET2SPC: Output WHT file name: %s\n", WHT_file_path); } if (!noflux) { fprintf (stdout, "aXe_PET2SPC: Performing flux calibration.\n"); if (smooth_conv) fprintf (stdout, "aXe_PET2SPC: Using smoothed sensitivity curves.\n"); } fprintf (stdout, "\n\n"); // // try to get the descriptor 'exptime' from the 'sci'-extension // exptime = (double)get_float_from_keyword(grism_file_path, conf->science_numext, conf->exptimekey); if (isnan(exptime)) exptime = (double)get_float_from_keyword(grism_file_path, 1, conf->exptimekey); if (isnan(exptime)) exptime = 1.0; // // try to get the descriptor 'SKY_CPS' from the 'sci'-extension // sky_cps = (double)get_float_from_keyword(grism_file_path, conf->science_numext, "SKY_CPS"); if (isnan(sky_cps)) sky_cps = 0.0; // Open the OPET file for reading fits_open_file (&OPET_ptr, obj_PET_file_path, READONLY, &f_status); if (f_status) { ffrprt (stderr, f_status); aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "aXe_PET2SPC: Could not open file: %s\n", obj_PET_file_path); } // check whether the contamination is quantitative quant_cont = check_quantitative_contamination(OPET_ptr); if (opt_weights && !quant_cont) aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "aXe_PET2SPC: The optimal extractions needs quantitative contamination! " " Please re-run aXe with Gauss or Fluxcube contamination!"); obs = load_dummy_observation (); /* Loading the object list */ fprintf (stdout, "aXe_PET2SPC: Loading object aperture list..."); oblist = file_to_object_list_seq (aper_file_path, obs); fprintf (stdout,"%d objects loaded.\n",object_list_size(oblist)); if (dobck) { // Open the file for reading fits_open_file (&BPET_ptr, bck_PET_file_path, READONLY, &f_status); if (f_status) { ffrprt (stderr, f_status); aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "aXe_PET2SP: Could not open file: %s\n", bck_PET_file_path); } } /* Copy the header info from the grism image */ SPC_ptr = create_SPC_opened (SPC_file_path,1); cards = get_FITS_cards_opened(OPET_ptr); put_FITS_cards_opened(SPC_ptr, cards); free_FITScards(cards); if (opt_weights) { cards = get_FITS_cards_opened(OPET_ptr); // open the WHT file and add the header keywords WHT_ptr = create_FITSimage_opened (WHT_file_path, 1); put_FITS_cards_opened(WHT_ptr, cards); // open the opt_SPC and add the header keywords SPC_opt_ptr = create_SPC_opened (SPC_opt_file_path,1); put_FITS_cards_opened(SPC_opt_ptr, cards); // delete the header keywords free_FITScards(cards); } // do something only if there // exist valid objects i = 0; if (oblist!=NULL) { // turn until the end of the PET is reached while (1) { empty=0; // Get the PET for this object obj_PET = get_ALL_from_next_in_PET(OPET_ptr, &obj_aperID, &obj_beamID); // load the background PET if requested if (dobck) { bck_PET = get_ALL_from_next_in_PET(BPET_ptr, &bck_aperID, &bck_beamID); if ((bck_aperID!=obj_aperID)||(bck_beamID!=obj_beamID)) aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "Background PET and Object PET extensions are not" " in the same order and cannot be combined.\n"); } // end of PET reached: the break condition if ((obj_aperID==-1) && (obj_beamID==-1)) break; // signal an empty PET if (obj_PET==NULL) empty=1; // give feedback to the screen fprintf (stdout, "aXe_PET2SPC: BEAM %d; %d%c\n", i, obj_aperID, BEAM(obj_beamID));fflush(stdout); // identify the object which matches the PET objindex = find_object_in_object_list(oblist,obj_aperID); // look whether we are for grisms or prisms for_grism = check_for_grism (conf_file_path, obj_beamID); wl_calibration = get_calfunc_for_beam(oblist[objindex]->beams[obj_beamID], for_grism, conf_file_path, conf); // compute the object spectrum obj_spec = bin_naive (obj_PET, oblist[objindex]->beams[obj_beamID].width, oblist[objindex]->beams[obj_beamID].orient, quant_cont); // check for the existence of a background PET if (dobck) { // compute the background spectrum bck_spec = bin_naive (bck_PET, oblist[objindex]->beams[bck_beamID].width, oblist[objindex]->beams[bck_beamID].orient, quant_cont); } else { // create a dummy background spectrum bck_spec = empty_counts_spectrum_copy(obj_spec); } // subtract the background spectrum from the // object (or forground) spectrum sobj_spec = subtract_spectra (obj_spec, bck_spec); if(!noflux) { get_troughput_table_name(conf_file_path, oblist[objindex]->beams[obj_beamID].ID, table); if (strcmp(table,"None")) { build_path (AXE_CONFIG_PATH, table, table_path); resp=get_response_function_from_FITS(table_path,2); resp_func = create_response_function(table_path); if (resp->spec_len <2) { aXe_message (aXe_M_WARN1, __FILE__, __LINE__, "Throughput table %s contains only %d" " values. No sensitivity curve was applied.\n", table_path,resp->spec_len); } else { fprintf(stdout,"aXe_PET2SPC: Applying sensitivity contained in %s\n",table_path); smooth_params = get_smooth_pars_for_beam(conf, smooth_conv, oblist[objindex]->beams[obj_beamID]); if (smooth_params.x > 0.0) { // apply a smoothed flux conversion apply_smoothed_response(wl_calibration, for_grism, quant_cont, resp_func, smooth_params, sobj_spec); } else { // apply a normal flux conversion apply_response_function(sobj_spec,resp, quant_cont); } } // free the memory of the // response functions free_spectrum(resp); free_response_function(resp_func); } } if (empty!=1) { add_spectra_to_SPC_opened (SPC_ptr, obj_spec, bck_spec, sobj_spec, oblist[objindex]->ID, oblist[objindex]->beams[obj_beamID].ID); /* Copy header from OPET extension into this SPC extension */ cards = get_FITS_cards_opened(OPET_ptr); put_FITS_cards_opened(SPC_ptr,cards); free_FITScards(cards); } free_spectrum (bck_spec); free_spectrum (sobj_spec); free_spectrum (obj_spec); if (opt_weights) { // get the dimension in trace length // and crossdispersion dimension = get_all_dims(obj_PET, bck_PET, oblist[objindex]->beams[obj_beamID], dobck); // check for empty PET if (!dimension.resolution) { // create dummies in case of empty PET's weights = get_default_weight(); modvar = get_default_modvar(); } else { // prepare the PET's by computing the inverse variance. // Also the trace distances are shifted by 0.5 // to get a sampling comparable to the unweighted // extraction prepare_inv_variance(obj_PET, bck_PET, dobck, conf, exptime, sky_cps, 0.0); // compute the inverse variance and the profile // image in the trace distance - crossdispersion plane modvar = compute_modvar(obj_PET, oblist[objindex]->beams[obj_beamID], dimension); // compute the optimal weights weights = comp_allweight(modvar); } if (dimension.resolution && empty != 1) { sprintf (label, "WHT_%d%c", obj_aperID, BEAM (obj_beamID)); gsl_to_FITSimage_opened (weights, WHT_ptr ,0,label); // make and store the default header cards = beam_to_FITScards(oblist[objindex],obj_beamID); put_FITS_cards_opened(WHT_ptr,cards); free_FITScards(cards); } // create the optimal weighted // foreground spectrum obj_spec = bin_optimal (obj_PET,oblist[objindex]->beams[obj_beamID], quant_cont, weights, dimension, coverage); // check for the presence of a background PET if (dobck) { // create the optimal weighted // background spectrum bck_spec = bin_optimal (bck_PET,oblist[objindex]->beams[obj_beamID], quant_cont, weights, dimension, coverage); } else { // make a dummy background spectrum bck_spec = empty_counts_spectrum_copy(obj_spec); } // release memory gsl_matrix_free(weights); free_drzstamp(modvar); // subtract the background spectrum from the // object (or forground) spectrum sobj_spec = subtract_spectra (obj_spec, bck_spec); if(!noflux) { get_troughput_table_name(conf_file_path, oblist[objindex]->beams[obj_beamID].ID, table); if (strcmp(table,"None")) { build_path (AXE_CONFIG_PATH, table, table_path); resp=get_response_function_from_FITS(table_path,2); resp_func = create_response_function(table_path); if (resp->spec_len <2) { aXe_message (aXe_M_WARN1, __FILE__, __LINE__, "Throughput table %s contains only %d" " values. No sensitivity curve was applied.\n", table_path,resp->spec_len); } else { fprintf(stdout,"aXe_PET2SPC: Applying sensitivity contained in %s\n",table_path); smooth_params = get_smooth_pars_for_beam(conf, smooth_conv, oblist[objindex]->beams[obj_beamID]); if (smooth_params.x > 0.0) { apply_smoothed_response(wl_calibration, for_grism, quant_cont, resp_func, smooth_params, sobj_spec); } else { apply_response_function(sobj_spec,resp, quant_cont); } } // free the memory free_spectrum(resp); free_response_function(resp_func); } } if (empty!=1) { add_spectra_to_SPC_opened (SPC_opt_ptr, obj_spec, bck_spec, sobj_spec, oblist[objindex]->ID, oblist[objindex]->beams[obj_beamID].ID); /* Copy header from OPET extension into this SPC extension */ cards = get_FITS_cards_opened(OPET_ptr); put_FITS_cards_opened(SPC_opt_ptr,cards); free_FITScards(cards); } free_spectrum (bck_spec); free_spectrum (sobj_spec); free_spectrum (obj_spec); } // free memory free_calib (wl_calibration); if (bck_PET!=NULL) free (bck_PET); if (obj_PET!=NULL) free (obj_PET); i++; } } fits_close_file (SPC_ptr, &f_status); if (f_status) { ffrprt (stderr, f_status); aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "aXe_PET2SPC: " "Error closing SPC: %s\n", SPC_file_path); } if (opt_weights) { fits_close_file (WHT_ptr, &f_status); if (f_status) { ffrprt (stderr, f_status); aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "aXe_PET2SPC: " "Error closing WHT: %s\n", WHT_file_path); } fits_close_file (SPC_opt_ptr, &f_status); if (f_status) { ffrprt (stderr, f_status); aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "aXe_PET2SPC: " "Error closing PSC: %s\n", SPC_opt_file_path); } } if (oblist!=NULL) free_oblist (oblist); fprintf (stdout, "aXe_PET2SPC: Done...\n"); exit (0); }
int main (int argc, char *argv[]) { char *opt; char aper_file[MAXCHAR]; char aper_file_path[MAXCHAR]; char conf_file[MAXCHAR]; char conf_file_path[MAXCHAR]; char grism_file[MAXCHAR]; char grism_file_path[MAXCHAR]; char PET_file[MAXCHAR]; char PET_file_path[MAXCHAR]; // char outputroot[MAXCHAR]; // char outputroot_path[MAXCHAR]; char STP_file[MAXCHAR]; char STP_file_path[MAXCHAR]; // char output_path[MAXCHAR]; aperture_conf *conf; object **oblist; observation *obs; ap_pixel *PET; int index, i; char label[MAXCHAR]; fitsfile *PET_ptr, *STP_ptr; int f_status = 0; int aperID, beamID, objindex; FITScards *cards; FITScards *xymin_cards; gsl_matrix *rstamp; drzstamp *drzstmp; drzstamp_dim dim; int rectified = 0; //int drizzled = 0; int drizzle=0; int drzstamp=0; int for_grism=0; d_point stp_min; if ((argc < 3) || (opt = get_online_option ("help", argc, argv))) { fprintf (stdout, "ST-ECF European Coordinating Facility\n" "aXe_STAMPS Version %s:\n" " Task that generates some Postscript stamp images from the\n" " content of a Pixel Extraction Table (PET)\n" " The trace is overplotted and is generated from the group\n" " of pixels in the PET which have the smallest projected distance\n" " to the trace in the PET. No analytical a-priori trace function \n" " is used.\n" "\n" "Usage:\n" " aXe_STAMPS g/prism_filename configuration_filename [options]\n" "\n" "Options:\n" " -rectified - produces rectified stamp image following the\n" " direction of the extraction process\n" " -drz - use $AXE_DRIZZLE_PATH to locate the grism-, OAF-\n" " and PET-files instead of $AXE_IMAGE/OUTPUT_PATH\n" " -in_AF=[string] - overwrite the automatically generated name\n" " of the input aperture file\n" " -in_PET=[string] - overwrite the automatically generated name\n" " of the input PET file\n" " -out_STP=[string] - overwrite the automatically generated name\n" " of the output stamp FITS image\n" "\n",RELEASE); exit (1); } fprintf (stdout, "aXe_STAMPS: Starting...\n"); index = 0; strcpy (grism_file, argv[++index]); if ((opt = get_online_option ("drz", argc, argv))){ build_path (AXE_DRIZZLE_PATH, grism_file, grism_file_path); drizzle=1; } else{ build_path (AXE_IMAGE_PATH, grism_file, grism_file_path); drizzle=0; } strcpy (conf_file, argv[++index]); build_path (AXE_CONFIG_PATH, conf_file, conf_file_path); conf = get_aperture_descriptor (conf_file_path); /* Determine where the various extensions are in the FITS file */ get_extension_numbers(grism_file_path, conf,conf->optkey1,conf->optval1); /* Build aperture file name */ if ((opt = get_online_option("in_AF", argc, argv))){ /* get it */ strcpy (aper_file, opt); strcpy (aper_file_path, opt); } else { replace_file_extension (grism_file, aper_file, ".fits", ".OAF", conf->science_numext); if (drizzle) build_path (AXE_DRIZZLE_PATH, aper_file, aper_file_path); else build_path (AXE_OUTPUT_PATH, aper_file, aper_file_path); } if ((opt = get_online_option("in_PET", argc, argv))){ /* get it */ strcpy (PET_file, opt); strcpy (PET_file_path, opt); } else{ /* Build object PET file name */ replace_file_extension (grism_file, PET_file, ".fits", ".PET.fits", conf->science_numext); if (drizzle) build_path (AXE_DRIZZLE_PATH, PET_file, PET_file_path); else build_path (AXE_OUTPUT_PATH, PET_file, PET_file_path); } if ( (opt = get_online_option ("out_STP", argc, argv)) ) { strcpy (STP_file, opt); // strcpy (STP_file_PATH, opt); } else { // replace_file_extension (PET_file, STP_file, ".PET.fits", ".STP.fits",-1); replace_file_extension (grism_file, STP_file, ".fits", ".STP.fits",conf->science_numext); } if (drizzle) build_path (AXE_DRIZZLE_PATH, STP_file, STP_file_path); else build_path (AXE_OUTPUT_PATH, STP_file, STP_file_path); if ((opt=get_online_option("rectified",argc,argv))) rectified = 1; else if ((opt = get_online_option ("drzstamp", argc, argv))) drzstamp=1; // give feedback onto the screen: // report on input and output // and also on specific parameters fprintf (stdout, "aXe_STAMPS: Input Image file name: %s\n", grism_file_path); fprintf (stdout, "aXe_STAMPS: Input Aperture file name: %s\n", aper_file_path); fprintf (stdout, "aXe_STAMPS: Input PET file name: %s\n", PET_file_path); fprintf (stdout, "aXe_STAMPS: Name of STP file : %s\n", STP_file_path); if (rectified) fprintf (stdout, "aXe_STAMPS: Producing rectified stamp images.\n"); else if (drzstamp) fprintf (stdout, "aXe_STAMPS: Producing drizzled stamp images.\n"); else fprintf (stdout, "aXe_STAMPS: Producing trace stamp images.\n"); // Loading the object list obs = load_dummy_observation (); fprintf (stdout, "\naXe_STAMPS: Loading object aperture list..."); oblist = file_to_object_list_seq (aper_file_path, obs); fprintf (stdout,"%d objects loaded.\n\n",object_list_size(oblist)); // Open the OPET file for reading fits_open_file (&PET_ptr, PET_file_path, READONLY, &f_status); if (f_status) { ffrprt (stdout, f_status); aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "aXe_STAMPS: Could not open file: %s\n", PET_file_path); } STP_ptr = create_FITSimage_opened (STP_file_path, 1); i = 0; if (oblist!=NULL) { while (1) { /* Get the PET for this object */ PET = get_ALL_from_next_in_PET(PET_ptr, &aperID, &beamID); if ((aperID==-1) && (beamID==-1)) break; fprintf (stdout, "aXe_STAMPS: BEAM %d%c.", aperID, BEAM(beamID)); objindex = find_object_in_object_list(oblist,aperID); sprintf (label, "%s.%d%c.ps/CPS", STP_file_path, oblist[objindex]->ID, BEAM (oblist[objindex]->beams[beamID].ID)); // determine the minimum in x and y stp_min.x = -1.0; stp_min.y = -1.0; // special treatment for FORS2: dirzzled stamp images if (drzstamp) { for_grism = check_for_grism (conf_file_path, beamID); if (!for_grism) aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "aXe_STAMPS: Drizzled stamp images are not\n" "supported for prism images. Please choose a different option!\n"); // get the dimensions of the drizzled stamp dim = get_stamp_dim(PET, oblist[objindex]->beams[beamID].width, conf, beamID, &stp_min); // fill the drzstamp structure (counts plus weight matrix) drzstmp = drizzled_stamp_img (PET,oblist[objindex]->beams[beamID].width, oblist[objindex]->beams[beamID].orient, dim); // does this make sense interpolate_over_NaN (drzstmp->counts); // give the extension name and store the counts sprintf (label, "BEAM_%d%c",oblist[objindex]->ID, BEAM (oblist[objindex]->beams[beamID].ID)); gsl_to_FITSimage_opened (drzstmp->counts, STP_ptr ,0,label); // in case that the stamp is no dummy, make and store the WCS header if (dim.resolution) { cards = get_WCS_FITScards(dim.xstart*dim.resolution, dim.resolution, dim.ystart); put_FITS_cards_opened(STP_ptr,cards); free_FITScards(cards); } // make and store the default header cards = beam_to_FITScards(oblist[objindex],beamID); xymin_cards = stpmin_to_FITScards(stp_min); put_FITS_cards_opened(STP_ptr,cards); put_FITS_cards_opened(STP_ptr,xymin_cards); free_FITScards(cards); free_FITScards(xymin_cards); // give the extension name and store the weight image sprintf (label, "WEIG_%d%c",oblist[objindex]->ID, BEAM (oblist[objindex]->beams[beamID].ID)); gsl_to_FITSimage_opened (drzstmp->weight, STP_ptr ,0,label); // in case that the stamp is no dummy, make and store the WCS header if (dim.resolution) { cards = get_WCS_FITScards(dim.xstart*dim.resolution, dim.resolution, dim.ystart); put_FITS_cards_opened(STP_ptr,cards); free_FITScards(cards); } // make and store the default header cards = beam_to_FITScards(oblist[objindex],beamID); xymin_cards = stpmin_to_FITScards(stp_min); put_FITS_cards_opened(STP_ptr,cards); put_FITS_cards_opened(STP_ptr,xymin_cards); free_FITScards(cards); free_FITScards(xymin_cards); // free the structure with the count and weight matrix free_drzstamp(drzstmp); } else { if (rectified) { rstamp = rectified_stamp_img (PET,oblist[objindex]->beams[beamID].width, &stp_min); } else { rstamp = stamp_img (PET,oblist[objindex]->beams[beamID].width, &stp_min); } sprintf (label, "BEAM_%d%c",oblist[objindex]->ID, BEAM (oblist[objindex]->beams[beamID].ID)); interpolate_over_NaN (rstamp); gsl_to_FITSimage_opened (rstamp, STP_ptr ,0,label); cards = beam_to_FITScards(oblist[objindex],beamID); xymin_cards = stpmin_to_FITScards(stp_min); put_FITS_cards_opened(STP_ptr,cards); put_FITS_cards_opened(STP_ptr,xymin_cards); free_FITScards(cards); free_FITScards(xymin_cards); free_stamp_img(rstamp); } if (PET!=NULL) free(PET); fprintf (stdout, " Done.\n"); i++; } } if (oblist!=NULL) free_oblist (oblist); fits_close_file (STP_ptr, &f_status); if (f_status) { ffrprt (stdout, f_status); aXe_message (aXe_M_FATAL, __FILE__, __LINE__, "aXe_STAMPS: Could not" " close STP file: %s\n", STP_file_path); } fprintf (stdout, "aXe_STAMPS: Done...\n"); /* Copy the header info from the grism image */ { FITScards *cards; cards = get_FITS_cards (PET_file_path, 1); put_FITS_cards(STP_file_path,1,cards); free_FITScards(cards); } exit (0); }