Ejemplo n.º 1
0
/**
 * The function fills the keywords XOFFS and YOFFS
 * from the primary header of the fitscube file
 * into the according items of the fitscube structure.
 * In case that those keywords are not present,
 * they are set to 0.
 *
 * @param  fcube_file - the file name of the fluxcube
 * @param  fcube      - the fluxcube structure
 *
 * @return 1          - always true
 */
int
load_offsets(const char fcube_file[], flux_cube *fcube)
{
  char tmp[MAXCHAR];

  double dtmp=0.0;

  // avoid problems with the 'const' declaration
  strcpy(tmp, fcube_file);

  // read XOFFS from the primary header
  dtmp = get_float_from_keyword(tmp, 1, "XOFFS");

  // store the keyword value or 0 (if not present) in the fcube structure
  if (isnan(dtmp))
    fcube->xoffs = 0;
  else
    fcube->xoffs = (int)dtmp;

  // read XOFFS from the primary header
  dtmp = get_float_from_keyword(tmp, 1, "YOFFS");

  // store the keyword value or 0 (if not present) in the fcube structure
  if (isnan(dtmp))
    fcube->yoffs = 0;
  else
    fcube->yoffs = (int)dtmp;

  return 1;
}
Ejemplo n.º 2
0
/*
 * 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;
}
Ejemplo n.º 3
0
/**
 * 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;
}
Ejemplo n.º 4
0
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);
}