void smf_open_asdouble( const Grp *igrp, size_t index, const smfArray* darks, const smfArray* flatramps, AstKeyMap * heateffmap, int ensureflat, smfData **data, int *status ) { if( *status != SAI__OK ) return; /* Load data, flatfielding and/or opening raw as double as necessary */ if( ensureflat ) { smf_open_and_flatfield( igrp, NULL, index, darks, flatramps, heateffmap, data, status ); } else { /* open as raw if raw else just open as whatever we have */ smfData *tmpdata = NULL; smf_open_file( igrp, index, "READ", SMF__NOCREATE_DATA, &tmpdata, status ); if (tmpdata && tmpdata->file && tmpdata->file->isSc2store) { smf_open_raw_asdouble( igrp, index, darks, data, status ); } else { smf_open_and_flatfield( igrp, NULL, index, darks, flatramps, heateffmap, data, status ); } smf_close_file( &tmpdata, status ); } }
void smurf_extinction( int * status ) { /* Local Variables */ smfArray *bbms = NULL; /* Bad bolometer masks */ smfArray *darks = NULL; /* Dark data */ AstKeyMap *extpars = NULL; /* Tau relation keymap */ Grp *fgrp = NULL; /* Filtered group, no darks */ smfArray *flatramps = NULL;/* Flatfield ramps */ int has_been_sky_removed = 0;/* Data are sky-removed */ AstKeyMap *heateffmap = NULL; /* Heater efficiency data */ size_t i; /* Loop counter */ Grp *igrp = NULL; /* Input group */ AstKeyMap *keymap=NULL; /* Keymap for storing parameters */ smf_tausrc tausrc; /* enum value of optical depth source */ smf_extmeth extmeth; /* Extinction correction method */ char tausource[LEN__METHOD]; /* String for optical depth source */ char method[LEN__METHOD]; /* String for extinction airmass method */ smfData *odata = NULL; /* Output data struct */ Grp *ogrp = NULL; /* Output group */ size_t outsize; /* Total number of NDF names in the output group */ size_t size; /* Number of files in input group */ double tau = 0.0; /* Zenith tau at this wavelength */ ThrWorkForce *wf = NULL; /* Pointer to a pool of worker threads */ if (*status != SAI__OK) return; /* Main routine */ ndfBegin(); /* Find the number of cores/processors available and create a pool of threads of the same size. */ wf = thrGetWorkforce( thrGetNThread( SMF__THREADS, status ), status ); /* Read the input file */ kpg1Rgndf( "IN", 0, 1, "", &igrp, &size, status ); /* Filter out darks */ smf_find_science( igrp, &fgrp, 0, NULL, NULL, 1, 1, SMF__NULL, &darks, &flatramps, &heateffmap, NULL, status ); /* input group is now the filtered group so we can use that and free the old input group */ size = grpGrpsz( fgrp, status ); grpDelet( &igrp, status); igrp = fgrp; fgrp = NULL; if (size > 0) { /* Get output file(s) */ kpg1Wgndf( "OUT", igrp, size, size, "More output files required...", &ogrp, &outsize, status ); } else { msgOutif(MSG__NORM, " ","All supplied input frames were DARK," " nothing to extinction correct", status ); } /* Get group of pixel masks and read them into a smfArray */ smf_request_mask( "BBM", &bbms, status ); /* Read the tau relations from config file or group. We do not allow sub instrument overloading because these are all values based on filter name. */ keymap = kpg1Config( "TAUREL", "$SMURF_DIR/smurf_extinction.def", NULL, 1, status ); /* and we need to use the EXT entry */ astMapGet0A( keymap, "EXT", &extpars ); keymap = astAnnul( keymap ); /* Get tau source */ parChoic( "TAUSRC", "Auto", "Auto,CSOtau,CSOFit, Filtertau, WVMraw", 1, tausource, sizeof(tausource), status); /* Decide how the correction is to be applied - convert to flag */ parChoic( "METHOD", "ADAPTIVE", "Adaptive,Quick,Full,", 1, method, sizeof(method), status); /* Place parameters into a keymap and extract values */ if( *status == SAI__OK ) { keymap = astKeyMap( " " ); if( astOK ) { astMapPut0C( keymap, "TAUSRC", tausource, NULL ); astMapPut0C( keymap, "TAUMETHOD", method, NULL ); smf_get_extpar( keymap, &tausrc, &extmeth, NULL, status ); } } for (i=1; i<=size && ( *status == SAI__OK ); i++) { /* Flatfield - if necessary */ smf_open_and_flatfield( igrp, ogrp, i, darks, flatramps, heateffmap, &odata, status ); if (*status != SAI__OK) { /* Error flatfielding: tell the user which file it was */ msgSeti("I",i); errRep(TASK_NAME, "Unable to open the ^I th file", status); } /* Mask out bad pixels - mask data array not quality array */ smf_apply_mask( odata, bbms, SMF__BBM_DATA, 0, status ); /* Now check that the data are sky-subtracted */ if ( !smf_history_check( odata, "smf_subtract_plane", status ) ) { /* Should we override remsky check? */ parGet0l("HASSKYREM", &has_been_sky_removed, status); if ( !has_been_sky_removed && *status == SAI__OK ) { *status = SAI__ERROR; msgSeti("I",i); errRep("", "Input data from file ^I are not sky-subtracted", status); } } /* If status is OK, make decisions on source keywords the first time through. */ if ( *status == SAI__OK && i == 1 ) { if (tausrc == SMF__TAUSRC_CSOTAU || tausrc == SMF__TAUSRC_AUTO || tausrc == SMF__TAUSRC_TAU) { double deftau; const char * param = NULL; smfHead *ohdr = odata->hdr; /* get default CSO tau -- this could be calculated from CSO fits */ deftau = smf_calc_meantau( ohdr, status ); /* Now ask for desired CSO tau */ if ( tausrc == SMF__TAUSRC_CSOTAU || tausrc == SMF__TAUSRC_AUTO) { param = "CSOTAU"; } else if (tausrc == SMF__TAUSRC_TAU) { param = "FILTERTAU"; deftau = smf_cso2filt_tau( ohdr, deftau, extpars, status ); } parGdr0d( param, deftau, 0.0,1.0, 1, &tau, status ); } else if ( tausrc == SMF__TAUSRC_CSOFIT || tausrc == SMF__TAUSRC_WVMRAW ) { /* Defer a message until after extinction correction */ } else { *status = SAI__ERROR; errRep("", "Unsupported opacity source. Possible programming error.", status); } } /* Apply extinction correction - note that a check is made to determine whether the data have already been extinction corrected */ smf_correct_extinction( wf, odata, &tausrc, extmeth, extpars, tau, NULL, NULL, status ); if ( tausrc == SMF__TAUSRC_WVMRAW ) { msgOutif(MSG__VERB," ", "Used Raw WVM data for extinction correction", status); } else if ( tausrc == SMF__TAUSRC_CSOFIT ) { msgOutif(MSG__VERB," ", "Used fit to CSO data for extinction correction", status); } else if ( tausrc == SMF__TAUSRC_CSOTAU ) { msgOutif(MSG__VERB," ", "Used an explicit CSO tau value for extinction correction", status); } else if ( tausrc == SMF__TAUSRC_TAU ) { msgOutif(MSG__VERB," ", "Used an explicit filter tau value for extinction correction", status); } else { if (*status == SAI__OK) { const char * taustr = smf_tausrc_str( tausrc, status ); *status = SAI__ERROR; errRepf( "", "Unexpected opacity source used for extinction correction of %s." " Possible programming error.", status, taustr ); } } /* Set character labels */ smf_set_clabels( "Extinction corrected",NULL, NULL, odata->hdr, status); smf_write_clabels( odata, status ); /* Free resources for output data */ smf_close_file( &odata, status ); } /* Write out the list of output NDF names, annulling the error if a null parameter value is supplied. */ if( *status == SAI__OK && ogrp ) { grpList( "OUTFILES", 0, 0, NULL, ogrp, status ); if( *status == PAR__NULL ) errAnnul( status ); } /* Tidy up after ourselves: release the resources used by the grp routines */ if (darks) smf_close_related( &darks, status ); if (bbms) smf_close_related( &bbms, status ); if( flatramps ) smf_close_related( &flatramps, status ); if (heateffmap) heateffmap = smf_free_effmap( heateffmap, status ); grpDelet( &igrp, status); grpDelet( &ogrp, status); if( keymap ) keymap = astAnnul( keymap ); if (extpars) extpars = astAnnul( extpars ); ndfEnd( status ); }
void smurf_flatfield( int *status ) { smfArray *bbms = NULL; /* Bad bolometer masks */ smfData *ffdata = NULL; /* Pointer to output data struct */ Grp *fgrp = NULL; /* Filtered group, no darks */ smfArray *flatramps = NULL;/* Flatfield ramps */ AstKeyMap *heateffmap = NULL; /* Heater efficiency data */ size_t i = 0; /* Counter, index */ Grp *igrp = NULL; /* Input group of files */ Grp *ogrp = NULL; /* Output group of files */ size_t outsize; /* Total number of NDF names in the output group */ size_t size; /* Number of files in input group */ /* Main routine */ ndfBegin(); /* Get input file(s) */ kpg1Rgndf( "IN", 0, 1, "", &igrp, &size, status ); /* Filter out darks */ smf_find_science( NULL, igrp, &fgrp, 0, NULL, NULL, 1, 1, SMF__NULL, NULL, &flatramps, &heateffmap, NULL, status ); /* input group is now the filtered group so we can use that and free the old input group */ size = grpGrpsz( fgrp, status ); grpDelet( &igrp, status); igrp = fgrp; fgrp = NULL; if (size > 0) { /* Get output file(s) */ kpg1Wgndf( "OUT", igrp, size, size, "More output files required...", &ogrp, &outsize, status ); } else { msgOutif(MSG__NORM, " ","All supplied input frames were DARK," " nothing to flatfield", status ); } /* Get group of bolometer masks and read them into a smfArray */ smf_request_mask( NULL, "BBM", &bbms, status ); for (i=1; i<=size; i++ ) { int didflat; if (*status != SAI__OK) break; /* Call flatfield routine */ didflat = smf_open_and_flatfield( NULL, igrp, ogrp, i, NULL, flatramps, heateffmap, &ffdata, status); /* Report failure by adding a message indicating which file failed */ msgSeti("I",i); if (*status != SAI__OK) { msgSeti("N",size); errRep(FUNC_NAME, "Unable to flatfield data from file ^I of ^N", status); break; } /* in verbose mode report whether flatfielding occurred or not */ if (!didflat) { msgOutif(MSG__VERB," ", "Data from file ^I are already flatfielded", status); } else { msgOutif(MSG__VERB," ", "Flat field applied to file ^I", status); } /* Mask out bad bolometers - mask data array not quality array */ smf_apply_mask( NULL, ffdata, bbms, SMF__BBM_DATA, 0, status ); /* Free resources for output data */ smf_close_file( NULL, &ffdata, status ); } /* Write out the list of output NDF names, annulling the error if a null parameter value is supplied. */ if( *status == SAI__OK && ogrp ) { grpList( "OUTFILES", 0, 0, NULL, ogrp, status ); if( *status == PAR__NULL ) errAnnul( status ); } /* Tidy up after ourselves: release the resources used by the grp routines */ if (igrp) grpDelet( &igrp, status); if (ogrp) grpDelet( &ogrp, status); if (bbms) smf_close_related( NULL, &bbms, status ); if( flatramps ) smf_close_related( NULL, &flatramps, status ); if (heateffmap) heateffmap = smf_free_effmap( heateffmap, status ); ndfEnd( status ); }
void smurf_smurfcopy ( int * status ) { smfData * data = NULL; /* input file struct */ size_t dtypsz; /* Number of bytes in data type */ Grp *fgrp = NULL; /* Filtered group, no darks */ size_t i; /* Loop counter */ smfFile * ifile = NULL; /* Input smfFile */ Grp *igrp = NULL; /* Input group */ unsigned char * inptr = NULL; /* Pointer to start of section to copy */ int islice; /* int time slice from parameter */ int lbnd[2]; /* Lower coordinate bounds of output file */ size_t nelem; /* Number of elements to copy */ smfData * odata = NULL; /* output file struct */ size_t offset; /* offset into data array */ smfFile * ofile = NULL; /* output smfFile */ Grp *ogrp = NULL; /* Output group */ size_t outsize; /* Total number of NDF names in the output group */ dim_t slice; /* Time index to extract */ size_t size; /* Number of files in input group */ int ubnd[2]; /* Upper coordinate bounds of output file */ if (*status != SAI__OK) return; ndfBegin(); /* Read the input file */ /* As a proof of concept do not allow multiple input files */ kpg1Rgndf( "IN", 1, 1, "", &igrp, &size, status ); /* Filter out darks */ smf_find_science( igrp, &fgrp, 1, NULL, NULL, 0, 0, SMF__NULL, NULL, NULL, NULL, NULL, status ); /* input group is now the filtered group so we can use that and free the old input group */ size = grpGrpsz( fgrp, status ); grpDelet( &igrp, status); igrp = fgrp; fgrp = NULL; if (size > 0) { /* Get output file(s) */ kpg1Wgndf( "OUT", igrp, size, size, "More output files required...", &ogrp, &outsize, status ); } else { msgOutif(MSG__NORM, " ","All supplied input frames were DARK," " nothing to extract", status ); } /* Allow the user to specify a text file containing a table of pointing corrections. Corresponding Mappings are created form the column data in this table and stored in the "igrp" group as items of metadata. */ smf_pread( igrp, "POINTING", status ); /* Use a loop so that we look like other routines and simplify the change if we support multiple input files */ for (i=1; i<=size; i++) { /* Open the input file using standard routine */ smf_open_and_flatfield( igrp, NULL, i, NULL, NULL, NULL, &data, status ); if (*status != SAI__OK) break; if (*status == SAI__OK) { if (!data->file->isTstream || data->ndims != 3) { smf_close_file( &data, status ); *status = SAI__ERROR; errRep(" ", "Input data do not represent time series", status); break; } } /* get the slice position - knowing the maximum allowed Somewhat problematic in a loop if we want to allow different slices per file. Best bet is to allow multiple slices in a single file but only one file. */ msgSeti( "MAX", (data->dims)[2] ); msgOutif( MSG__NORM, " ", "File has ^MAX slices.", status ); parGdr0i( "SLICE",1, 0, (data->dims)[2], 1, &islice, status); slice = islice; if (slice == 0) slice = (data->dims)[2]; /* construct output bounds */ lbnd[0] = (data->lbnd)[0]; lbnd[1] = (data->lbnd)[1]; ubnd[0] = lbnd[0] + (data->dims)[0] - 1; ubnd[1] = lbnd[1] + (data->dims)[1] - 1; /* Open an output file (losing history) but we do not want to propagate the full NDF size to the output file */ smf_open_newfile( ogrp, i, data->dtype, 2, lbnd, ubnd, 0, &odata, status ); ofile = odata->file; ifile = data->file; /* protect against null pointer smfFile */ if (*status == SAI__OK) { /* sort out provenance */ smf_accumulate_prov( data, igrp, i, ofile->ndfid, "SMURF:SMURFCOPY", NULL, status ); /* copy the slice in */ dtypsz = smf_dtype_size( odata, status ); nelem = (data->dims)[0] * (data->dims)[1]; offset = (slice - 1) * nelem * dtypsz; inptr = (data->pntr)[0]; memcpy( (odata->pntr)[0], inptr + offset, nelem * dtypsz ); /* World coordinates - note the 0 indexing relative to GRID */ smf_tslice_ast( data, slice-1, 1, status ); ndfPtwcs( data->hdr->wcs, ofile->ndfid, status ); /* Write the FITS header */ kpgPtfts( ofile->ndfid, data->hdr->fitshdr, status ); /* JCMTSTATE */ sc2store_writejcmtstate( ofile->ndfid, 1, &((data->hdr->allState)[slice-1]), status ); } /* cleanup */ smf_close_file( &data, status ); smf_close_file( &odata, status ); } /* tidy */ if (igrp) { smf_pread( igrp, NULL, status ); grpDelet( &igrp, status ); } if (ogrp) grpDelet( &ogrp, status ); ndfEnd(status); }