int smf_validate_smfData( const smfData * data, int hashdr, int hasfile, int *status ) { if (*status != SAI__OK) return 0; if ( data == NULL ) { *status = SAI__ERROR; errRep( FUNC_NAME, "Supplied smfData is a NULL pointer. Possible programming error.", status); return 0; } if ( hasfile && data->file == NULL ) { *status = SAI__ERROR; errRep( FUNC_NAME, "No file associated with supplied smfData. " "Possible programming error.", status ); return 0; } if (hashdr) return smf_validate_smfHead( data->hdr, 0, 0, status ); return 1; }
void smf_check_flat ( const smfData *data, int *status ) { smfDA *da; smf_dtype dtype; if ( *status != SAI__OK ) return; if ( !data ) { *status = SAI__ERROR; errRep("", "Error checking if data are flatfielded. smfData is null." " (possible programming error)", status ); return; } /* Retrieve the smfDa struct */ da = data->da; dtype = data->dtype; /* Data need flatfielding if da is defined */ if ( da == NULL || dtype == SMF__DOUBLE) { /* No raw data struct => data flatfielded */ *status = SMF__FLATN; errRep(FUNC_NAME, "Data are already flatfielded", status); } }
void fts2_getmirrorpositions(smfData* data, double* positions, int* size, int* status) { if(*status != SAI__OK) { return; } char ftsMode[SZFITSTR]; size_t count = 0; /* Size */ HDSLoc* hdsLoc = NULL; /* Pointer to HDS location */ HDSLoc* hdsLocPos = NULL; /* Pointer to mirror positions */ smf_fits_getS(data->hdr, "FTS_MODE", ftsMode, sizeof(ftsMode), status); if(strncmp(ftsMode, "FSCAN", 5) == 0 ) { hdsLoc = smf_get_xloc(data, "JCMTSTATE", "EXT", "READ", 0, 0, status); datFind(hdsLoc, "FTS_POS", &hdsLocPos, status); datSize(hdsLocPos, &count, status); datGetVD(hdsLocPos, count, positions, &count, status); *size = (int) count; } else if(strncmp(ftsMode, "STEPINT", 7) == 0 ) { *status = SAI__ERROR; errRep(FUNC_NAME, "STEPINT mode is NOT supported!", status); } else { *status = SAI__ERROR; errRep(FUNC_NAME, "Unknown Scan Mode is found!", status); } if(hdsLoc) { datAnnul(&hdsLoc, status); } if(hdsLocPos) { datAnnul(&hdsLocPos, status); } }
void smf_find_dateobs( const smfHead* hdr, double *dateobs, double *dateend, int *status) { /* initialise error condition before checking status */ if (dateobs) *dateobs = VAL__BADD; if (dateend) *dateend = VAL__BADD; if (*status != SAI__OK) return; if (dateobs == NULL && dateend == NULL) { *status = SAI__ERROR; errRep(" ", FUNC_NAME " called with both dateobs and dateend NULL" " (possible programming error)", status); return; } if (!smf_validate_smfHead(hdr, 0, 0, status)) return; if (!hdr->allState && !hdr->fitshdr) { *status = SAI__ERROR; errRep( " ","Can not find date of observation without FITS header " "or JCMTSTATE extension", status ); return; } if (dateobs) *dateobs = smf__find_utc( hdr, 1, status ); if (dateend) *dateend = smf__find_utc( hdr, 0, status ); return; }
double smf_map_getpixsize( const smfData *data, int *status ) { double at[3]={0,0,0}; /* Grid coords. where we check the scale */ int naxes; /* Number of axes */ double pixsize=VAL__BADD; /* The pixel size */ double pixscl[3]; if( *status != SAI__OK ) return pixsize; if( !data ) { *status = SAI__ERROR; errRep( "", FUNC_NAME ": NULL smfData supplied", status ); return pixsize; } if( !data->hdr || !data->hdr->wcs ) { *status = SAI__ERROR; errRep( "", FUNC_NAME ": no header, or missing WCS", status ); return pixsize; } /* Check number of axes in the frameset. It will usually be 3 because we have a frequency axis of length 1 for normal SMURF maps */ naxes = astGetI( data->hdr->wcs, "naxes" ); if( (naxes < 2) || (naxes > 3) ) { *status = SAI__ERROR; errRep( "", FUNC_NAME ": Frameset does not appear to corresond to a 2-d map", status ); return pixsize; } /* Take the average of the x- and y-pixel spacings in radians at the centre of the map, and then convert to arcsec */ at[0] = -(data->lbnd[0]-1); at[1] = -(data->lbnd[1]-1); kpgPixsc( data->hdr->wcs, at, pixscl, NULL, NULL, 0, status ); if( *status == SAI__OK ) { pixsize = (pixscl[0] + pixscl[1])/2.; pixsize *= DR2AS; msgOutiff( MSG__DEBUG, "", FUNC_NAME ": determined pixel size from WCS at map coordinates (%g,%g) " "to be %g arcsec", status, at[0], at[1], pixsize ); } else { *status = SAI__ERROR; errRep( "", FUNC_NAME ": could not determine pixel size from WCS", status ); } return pixsize; }
size_t smf_dtype_sz( const smf_dtype dtype, int *status ) { size_t retval = 0; if (*status != SAI__OK) return retval; /* now switch on data type */ switch( dtype ) { case SMF__INTEGER: retval = sizeof(int); break; case SMF__FLOAT: retval = sizeof(float); break; case SMF__DOUBLE: retval = sizeof(double); break; case SMF__USHORT: retval = sizeof(unsigned short); break; case SMF__UBYTE: retval = sizeof(unsigned char); break; default: retval = 0; *status = SMF__BDTYP; msgSeti( "TC", dtype ); errRep(FUNC_NAME, "Unable to determine size of datatype. Data typecode was ^TC", status ); } return retval; }
void * smf_map_or_malloc (size_t nelem, smf_dtype type, int zero, int indf, const char * comp, int *status ) { void *pntr[3]; /* ndfMap pointers */ int nout = 0; /* number of elements mapped */ if (*status != SAI__OK) return NULL; /* just malloc if we do not have a file */ if ( indf == NDF__NOID) { if( zero ) { return astCalloc( nelem, smf_dtype_sz(type, status) ); } else { return astMalloc( nelem*smf_dtype_sz(type, status) ); } } ndfMap( indf, comp, smf_dtype_str(type, status), (zero ? "WRITE/ZERO" : "WRITE"), pntr, &nout, status); if (nelem != (size_t)nout && *status == SAI__OK) { ndfUnmap( indf, comp, status ); *status = SAI__ERROR; msgSetc( "COMP", comp ); msgSeti( "ORI", nelem ); msgSeti( "NOUT", nout ); errRep(" ", "Mapping ^COMP in NDF but size differs from that listed in smfData attributes (^ORI != ^NOUT)", status); pntr[0] = NULL; } return pntr[0]; }
smfDA * smf_create_smfDA( int * status ) { smfDA * da = NULL; /* File components */ if (*status != SAI__OK) return NULL; da = astMalloc( 1*sizeof(*da) ); if (*status != SAI__OK) { errRep(FUNC_NAME,"Unable to allocate memory for smfDA structure", status ); return NULL; } /* Initialise smfDA */ da->flatcal = NULL; da->flatpar = NULL; da->dksquid = NULL; da->flatmeth = SMF__FLATMETH_NULL; da->nflat = 0; da->refres = VAL__BADD; da->heatval = NULL; da->nheat = 0; return da; }
smf_calcmodelptr smf_model_getptr( smf_modeltype type, int *status) { /* Local Variables */ smf_calcmodelptr retval = NULL; /* Main routine */ if (*status != SAI__OK) return NULL; switch( type ) { case SMF__COM: retval = (smf_calcmodelptr) &smf_calcmodel_com; break; case SMF__EXT: retval = (smf_calcmodelptr) &smf_calcmodel_ext; break; case SMF__NOI: retval = (smf_calcmodelptr) &smf_calcmodel_noi; break; case SMF__DKS: retval = (smf_calcmodelptr) &smf_calcmodel_dks; break; case SMF__GAI: retval = (smf_calcmodelptr) &smf_calcmodel_gai; break; case SMF__FLT: retval = (smf_calcmodelptr) &smf_calcmodel_flt; break; case SMF__PLN: retval = (smf_calcmodelptr) &smf_calcmodel_pln; break; case SMF__SMO: retval = (smf_calcmodelptr) &smf_calcmodel_smo; break; case SMF__TWO: retval = (smf_calcmodelptr) &smf_calcmodel_two; break; case SMF__TMP: retval = (smf_calcmodelptr) &smf_calcmodel_tmp; break; default: msgSetc( "NM", smf_model_getname(type, status) ); *status = SAI__ERROR; errRep( "", FUNC_NAME ": Invalid smf_modeltype given (^NM), or no function available.", status); } return retval; }
void smf_dream_getgrid( const AstKeyMap *keymap, double *gridstep, int *ngrid, int gridminmax[4], int gridpts[DREAM__MXGRID][2], int *status) { /* Local variables */ int k; /* Loop counter */ int tmp; /* General purpose temporary variable */ int xgrid; /* X position in reconstruction grid */ int ygrid; /* Y position in reconstruction grid */ /* Check status */ if (*status != SAI__OK) return; /* Retrieve relevant settings from config file */ if( !astMapGet0D( keymap, "GRIDSTEP", gridstep ) ) { *gridstep = 6.28; /* Define default value */ } /* Get the grid extent, prefill it just in case */ gridminmax[XMIN] = 0; gridminmax[XMAX] = 1; gridminmax[YMIN] = 0; gridminmax[YMAX] = 1; if( !astMapGet1I( keymap, "GRIDMINMAX", 4, &tmp, gridminmax ) ) { *status = SAI__ERROR; errRep(FUNC_NAME, "GRIDXMIN unspecified", status); } if ( *status == SAI__OK ) { /* Check gridxmax > gridxmin etc: swap them round by default? */ if ( gridminmax[XMIN] > gridminmax[XMAX] ) { msgOutif(MSG__VERB," ", "Xmin > Xmax: swapping them round", status ); tmp = gridminmax[XMIN]; gridminmax[XMIN] = gridminmax[XMAX]; gridminmax[XMAX] = tmp; } if ( gridminmax[YMIN] > gridminmax[YMAX] ) { msgOutif(MSG__VERB," ", "Ymin > Ymax: swapping them round", status ); tmp = gridminmax[YMIN]; gridminmax[YMIN] = gridminmax[YMAX]; gridminmax[YMAX] = tmp; } /* Create gridpts array from min/max extent */ *ngrid = ((gridminmax[XMAX] - gridminmax[XMIN] + 1) * (gridminmax[YMAX] - gridminmax[YMIN] + 1)); k = 0; for ( ygrid=gridminmax[YMIN]; ygrid<=gridminmax[YMAX]; ygrid++ ) { for ( xgrid=gridminmax[XMIN]; xgrid<=gridminmax[XMAX]; xgrid++ ) { gridpts[k][0] = xgrid; gridpts[k][1] = ygrid; k++; } } } }
void adamtest ( int * status ) { if (*status != SAI__OK) return; msgOut("MSG1", "This text should not appear for msgOut", status ); msgSeti("TEST", 5); msgOut(" ", " Testing ^^ %% % $ $$ %ET - $TESTOBJ ^TEST",status); msgOut( " ", " Testing $ %ET Again %%ET ^^$", status ); msgOut(" ", "$$DOLLAR ^^CARET %%PERCENT at start of string", status); /* Make up a bad status */ *status = MSG__SYNER; errRep( " ", "This is the error message ^STATUS embedded", status ); errRep( "MSG1", "This text should not appear", status ); errRep( " ", "Should be expanded: %ET as 'EXPOSURE_TIME'", status); errRep( " ", "Object $TESTOBJ %s %XX should be somewhere", status ); errRep( " ", "Multiple %ET and ^STATUS and %TESTOBJ and %BLAH", status ); errRep( " ", "Double up %% escape $$ characters", status ); msgSetc( "X1", STRING ); msgSetc( "X2", STRING); msgSetc( "X3", STRING); msgSetc( "X4", STRING); msgSetc( "X5", STRING); msgSetc( "X6", STRING); errRep( " ","Overflow: ^X1:^X2:^X3:^X4:^X5:^X6", status ); }
AstKeyMap *smf_subinst_keymap( smf_subinst_t subinst, const smfData * indata, const Grp * igrp, size_t idx, int * status ) { const smfHead * hdr = NULL; /* Header of file to be examined */ size_t i; smfData * sub_data = NULL; /* File to be examined */ AstKeyMap * sub_instruments; /* Keymap to be filled */ if (*status != SAI__OK) return NULL; if (subinst == SMF__SUBINST_NONE && !indata && !igrp) { *status = SAI__ERROR; errRep( "", "Must supply either a subinst, a smfData or a Grp" " (possible programming error)", status ); return NULL; } /* Create new keymap */ sub_instruments = astKeyMap( " " ); /* prefill with the list of known sub-instruments. */ for (i = 0; i < SMF__SUBINST_NSUBINST; i++ ) { const char * substr = smf_subinst_str( i, status ); if (substr) astMapPut0I( sub_instruments, substr, 0, NULL ); } /* If the current sub-instrument has not been supplied, get it from the file. Use indata in preference to the group */ if( subinst == SMF__SUBINST_NONE ) { if (indata) { hdr = indata->hdr; } else { smf_open_file( igrp, idx, "READ", SMF__NOCREATE_DATA, &sub_data, status ); if (sub_data) { hdr = sub_data->hdr; } } if (hdr) subinst = smf_calc_subinst( hdr, status ); } /* flag this as being the relevant sub-instrument */ if (subinst != SMF__SUBINST_NSUBINST ) { const char * substr = smf_subinst_str( subinst, status ); if (substr) { astMapPut0I( sub_instruments, substr, 1, NULL ); } } if (sub_data) smf_close_file( &sub_data, status ); /* Free the keymap if we have bad status */ if (*status != SAI__OK && sub_instruments) { sub_instruments = astAnnul( sub_instruments ); } return sub_instruments; }
double smf_raw2current( smfHead *hdr, int *status ) { /* Local Variables */ double raw2current=VAL__BADD; /* Conversion factor */ double dateobs=VAL__BADD; /* UTC MJD at observation start */ double dateconst=VAL__BADD; /* UTC MJD when constant changes */ AstTimeFrame *tf = NULL; /* time frame for date conversion */ /* Main routine */ if( *status != SAI__OK ) return VAL__BADD; /* Get the MJD for start of the observation */ smf_find_dateobs( hdr, &dateobs, NULL, status ); /* Convert ISO dates for when the values changed to MJDs for comparison */ tf = astTimeFrame( " " ); astSet( tf, "TimeScale=UTC" ); astSet( tf, "TimeOrigin=%s", "2011-06-04T00:00:00" ); dateconst = astGetD( tf, "TimeOrigin" ); if( (*status==SAI__OK) && (dateobs!=VAL__BADD) && (dateconst!=VAL__BADD) ) { if( dateobs < dateconst) { /* Prior to 2011-06-04 we use the following value. According to Dan 1.52e-13 was the measured factor for mce mode 1 (unfiltered output) on some old prototype array. The 3.3 multiplier corrected the conversion for mce mode 2 (filtered output). Note that SIMULT is defined in smurf_par.h */ raw2current = SIMULT * 3.3 * 1.52e-13; } else { /* Later the MCE low-pass filter was modified to accomodate a faster sample rate. With the new firmware on s8a the measured factor for mce mode 1 (unfiltered output) is 1.56e-13 and to correct for mce mode 2 (filtered output) requires a 1/1.15 multiplier. */ raw2current = SIMULT * 1.56e-13 / 1.15; } } if( (*status==SAI__OK) && (raw2current==VAL__BADD) ) { *status = SAI__ERROR; errRep( "", FUNC_NAME ": was unable to determine conversion factor", status ); } msgOutiff( MSG__DEBUG, "", FUNC_NAME ": calculated a value of %lf", status, raw2current ); /* Clean up */ tf = astAnnul( tf ); return raw2current; }
void error(int num, char *msg1, char *msg2) { int status; status = SAI__ERROR; msgSetc( "TOK1", msg1 ); msgSetc( "TOK2", msg2 ); errRep( " ", "^TOK1 ^TOK2", &status ); longjmp( env, num ); }
void smf_addmap1( double *map1, double *mapweight1, int *hitsmap1, double *mapvar1, smf_qual_t *mapqual1, double *map2, double *mapweight2, int *hitsmap2, double *mapvar2, smf_qual_t *mapqual2, dim_t msize, int *status ) { /* Local Variables */ dim_t i; /* Loop counter */ /* Main routine */ if (*status != SAI__OK) return; /* Check for NULL inputs */ if( (map1==NULL) || (mapweight1==NULL) || (hitsmap1==NULL) || (mapvar1==NULL) || (map2==NULL) || (mapweight2==NULL) || (hitsmap2==NULL) || (mapvar2==NULL) ) { *status = SAI__ERROR; errRep(FUNC_NAME, "Addmap failed due to NULL inputs.", status); return; } /* Loop over every pixel and store the weighted values in arrays associated with map1 */ for( i=0; i<msize; i++ ) { if( (map1[i] == VAL__BADD) || (mapvar1[i] == VAL__BADD) ) { /* If bad pixel in map1 just copy map2 regardless */ map1[i] = map2[i]; mapweight1[i] = mapweight2[i]; hitsmap1[i] = hitsmap2[i]; mapvar1[i] = mapvar2[i]; mapqual1[i] = mapqual2[i]; } else if( (map2[i] != VAL__BADD) && (mapvar2[i] != VAL__BADD) ) { /* Add together if both maps have good pixels */ if( (mapvar1[i]<=0) || (mapvar2[i]<=0) ) { *status = SAI__ERROR; errRepf("", FUNC_NAME ": invalid variance(s) <=0 detected (%g and %g)", status, mapvar1[i], mapvar2[i]); return; } else { double w = 1./mapvar1[i] + 1./mapvar2[i]; map1[i] = (map1[i]/mapvar1[i] + map2[i]/mapvar2[i])/w; mapweight1[i] += mapweight2[i]; hitsmap1[i] += hitsmap2[i]; mapqual1[i] &= mapqual2[i]; mapvar1[i] = 1. / w; } } } }
double smf_difftime( struct timeval *tv1, struct timeval *tv2, int *status) { if (*status != SAI__OK) return 0; if( !tv1 || !tv2 ) { *status = SAI__ERROR; errRep( "", FUNC_NAME ": NULL pointers to timeval structs supplied.", status ); return 0; } return (double)(tv2->tv_sec-tv1->tv_sec) + (1.0E-6*(double)(tv2->tv_usec-tv1->tv_usec)); }
smfDream *smf_create_smfDream( int * status ) { /* Need to make sure that any memory we malloc will be freed on error so make sure we NULL all pointers first. */ smfDream *dream = NULL; /* smfDream struct to fill */ size_t i; /* Loop counter */ if (*status != SAI__OK) return NULL; /* Create an empty smfDream */ dream = astMalloc( 1*sizeof(smfDream) ); if (*status != SAI__OK) { /* Add our own message to the stack */ errRep(FUNC_NAME, "Unable to allocate memory for smfDream structure", status); goto CLEANUP; } /* Integers */ dream->nvert = 0; dream->ngrid = 0; dream->ncycles = 0; dream->nsampcycle = 0; for ( i = 0; i < DREAM__MXVERT; i++ ) { (dream->jigvert)[i][0] = 0; (dream->jigvert)[i][1] = 0; } for ( i = 0; i < DREAM__MXGRID; i++ ) { (dream->gridpts)[i][0] = 0; (dream->gridpts)[i][1] = 0; } /* Pointers to the grid weights and inverse matrix */ dream->gridwts = NULL; dream->invmatx = NULL; /* Doubles */ dream->jigscal = 0.0; dream->gridstep = 0.0; for ( i = 0; i < DREAM__MXSAM; i++ ) { (dream->jigpath)[i][0] = 0.0; (dream->jigpath)[i][1] = 0.0; } return dream; CLEANUP: dream = astFree( dream ); return NULL; }
static void smf__calc_flatobskey( smfHead *hdr, char * keystr, size_t keylen, int *status ) { int curheat = 0; int detbias = 0; char subarray[10]; double shutter = 0.0; size_t nwrite = 0; int utdate = 0; if (*status != SAI__OK) return; if (!hdr) return; /* get reference heater value, bias, shutter and subarray string */ /* PIXHEAT and DETBIAS are not written by the simulator so we default those to 0 */ smf_getfitsi( hdr, "PIXHEAT", &curheat, status ); if (*status == SMF__NOKWRD) errAnnul(status); /* As of September 1st we heater track after doing the flat ramp. This means that the heater value will have changed slightly between ramp and science. */ smf_getfitsi( hdr, "UTDATE", &utdate, status ); if (utdate >= 20110901 && (hdr->obstype == SMF__TYP_SCIENCE || hdr->obstype == SMF__TYP_POINTING)) { curheat = 0; } smf_getfitsi( hdr, "DETBIAS", &detbias, status ); if (*status == SMF__NOKWRD) errAnnul(status); smf_getfitsd( hdr, "SHUTTER", &shutter, status ); smf_find_subarray( hdr, subarray, sizeof(subarray), NULL, status ); if (*status != SAI__OK) return; nwrite = snprintf(keystr, keylen, "%s_%s_%.1f_%d_%d", hdr->obsidss, subarray, shutter, detbias, curheat ); if (nwrite >= keylen) { /* The string was truncated */ *status = SMF__STRUN; errRep("", "String truncation forming flatfield key (Possible programming error)", status ); } }
static smf_obstype smf__parse_obstype ( char obs_type[], int *status ) { smf_obstype type = SMF__TYP_NULL; if (*status != SAI__OK) return type; if (strcasecmp( obs_type, "SCIENCE" ) == 0) { type = SMF__TYP_SCIENCE; } else if (strcasecmp( obs_type, "POINTING" ) == 0) { type = SMF__TYP_POINTING; } else if (strcasecmp( obs_type, "FOCUS" ) == 0) { type = SMF__TYP_FOCUS; } else if (strcasecmp( obs_type, "SKYDIP" ) == 0) { type = SMF__TYP_SKYDIP; } else if (strcasecmp( obs_type, "FLATFIELD" ) == 0) { type = SMF__TYP_FLATFIELD; } else if (strcasecmp( obs_type, "FASTFLAT" ) == 0) { type = SMF__TYP_FASTFLAT; } else if (strcasecmp( obs_type, "NOISE" ) == 0) { type = SMF__TYP_NOISE; } else if (strcasecmp( obs_type, "HEATRAMP" ) == 0) { type = SMF__TYP_HEATRAMP; } else if (strcasecmp( obs_type, "BIASRAMP" ) == 0) { type = SMF__TYP_BIASRAMP; } else if (strcasecmp( obs_type, "BIASSAW" ) == 0) { type = SMF__TYP_BIASSAW; } else if (strcasecmp( obs_type, "NEP" ) == 0) { type = SMF__TYP_NEP; } else if (strcasecmp( obs_type, "RAMP" ) == 0) { type = SMF__TYP_RAMP; } else if (strcasecmp( obs_type, "IV_CURVES_M" ) == 0) { type = SMF__TYP_IV_CURVES_M; } else if (strcasecmp( obs_type, "IV_CURVES_H" ) == 0) { type = SMF__TYP_IV_CURVES_H; } else if (strcasecmp( obs_type, "OPEN_LOOP_G" ) == 0) { type = SMF__TYP_OPEN_LOOP_G; } else if (strcasecmp( obs_type, "SETUP" ) == 0) { type = SMF__TYP_SETUP; } else { if (*status == SAI__OK) { *status = SAI__ERROR; msgSetc( "TYP", obs_type ); errRep( " ", "Unrecognized observation type '^TYP'", status ); } } return type; }
void gsdac_get0b ( const gsd *gsd, const char *name, char *value, int *status ) { /* Local variables */ char array; /* array flag (should always be false) */ int itemno; /* item number of the GSD header */ char type; /* data type of the item (should always be B) */ char unit[11]; /* unit of the GSD header */ /* Check inherited status */ if ( *status != SAI__OK ) return; /* Get the item number. */ CALLGSD( gsdFind ( gsd->fileDsc, gsd->itemDsc, name, &itemno, unit, &type, &array ), status, msgSetc ( "NAME", name ); errRep ( "gsdac_get0b", "gsdFind : Could not find element ^NAME in file", status ); );
/* private routine for scanning a JCMTSTATE TAI or date FITS header */ static double smf__find_utc( const smfHead *hdr, int first, int *status) { double utc = VAL__BADD; AstTimeFrame *tf = NULL; if (*status != SAI__OK) return VAL__BADD; tf = astTimeFrame( " " ); if (hdr->allState) { dim_t index; if (first) { index = 0; } else { index = hdr->nframes; } astSet( tf, "TimeScale=TAI" ); astSet( tf, "TimeOrigin=MJD %.*g", DBL_DIG, (hdr->allState)[index].rts_end); astSet( tf, "TimeScale=UTC" ); /* we need UTC */ } else if (hdr->fitshdr) { /* look for DATE-OBS */ char iso[81]; const char * fitscard = NULL; astSet( tf, "TimeScale=UTC" ); if (first) { fitscard = "DATE-OBS"; } else { fitscard = "DATE-END"; } smf_fits_getS( hdr, fitscard, iso, sizeof(iso), status ); astSet( tf, "TimeOrigin=%s", iso ); } else { *status = SAI__ERROR; errRep( " ","Can not find date of observation without FITS header " "or JCMTSTATE extension", status ); } /* now read back the TimeOrigin as an MJD */ if (*status == SAI__OK) utc = astGetD( tf, "TimeOrigin" ); /* Clean up */ tf = astAnnul( tf ); return utc; }
void smf_lock_related( smfArray *data, int lock, int *status ){ /* Local Variables */ size_t i; /* Loop counter */ if( *status != SAI__OK ) return; if( !data ) { *status = SAI__ERROR; errRep( "", "smf_lock_related: NULL smfArray provided", status ); return; } for( i=0; i<data->ndat; i++ ) { smf_lock_data( data->sdata[i], lock, status ); } }
static void smf__index_to_tbol( size_t bstride, size_t tstride, size_t bufpos, size_t *bolnum, size_t *tslice, int *status ) { size_t bol = 0; size_t tpos = 0; if (bolnum) *bolnum = 0; if (tslice) *tslice = 0; if (*status != SAI__OK) return; if (tstride == 1) { /* integer arithmetic - truncate the int */ bol = bufpos / bstride; tpos = bufpos - ( bol * bstride ); } else if (bstride == 1) { tpos = bufpos / tstride; bol = bufpos - ( tpos * tstride ); } else { *status = SAI__ERROR; errRep( "", "One of bstride and tstride must be 1", status ); } /* Sanity check */ if (*status == SAI__OK) { size_t ij; ij = bol * bstride + tpos * tstride; if (ij != bufpos) { *status = SAI__ERROR; errRepf("", "Internal error calculating bolometer and time slice from index " " (%zu != %zu from bstride of %zu and tstride of %zu)", status, bufpos, ij, bstride, tstride ); } } if (bolnum) *bolnum = bol; if (tslice) *tslice = tpos; }
int smf_history_check( const smfData* data, const char * appl, int *status) { const char *key; /* History item to check */ int i = 0; /* Loop counter */ int nrec = 0; /* Number of history records */ int retval = 0; /* Return value */ size_t nc; /* Number of characters to compare */ /* Check entry status */ if (*status != SAI__OK) return retval; /* check that we have a smfData */ if ( data == NULL ) { *status = SAI__ERROR; errRep( FUNC_NAME, "Supplied smfData is a NULL pointer. Possible programming error.", status); return retval; } /* Check that history even exists */ if( !data->history ) { return retval; } /* Get the number of characters to compare. */ nc = strlen( appl ); nrec = astMapSize( data->history ); if ( nrec != 0 ) { for ( i=0; i<nrec; i++ ) { msgOutiff(MSG__DEBUG2, " ", "Checking history item '%s' for '%s'", status, astMapKey( data->history, i ), appl); key = astMapKey( data->history, i ); if ( key && strncmp( key, appl, nc ) == 0 ) { retval = 1; break; } } } return retval; }
void smf_model_dataOrder( smfDIMMData *dat, smfArray ** allmodel, int chunk, smf_modeltype toOrder, int isTordered, int * status ) { if (*status != SAI__OK) return; if (!dat) { *status = SAI__ERROR; errRep( "", "smf_model_dataOrder called without data model pointer" " (possible programming error)", status ); return; } if (allmodel) { REORDER( "current", allmodel[chunk] ); } if ( toOrder & SMF__EXT && dat->ext ) REORDER( "ext", dat->ext[chunk] ); if ( toOrder & SMF__GAI && dat->gai ) REORDER( "gai", dat->gai[chunk] ); if ( toOrder & SMF__RES && dat->res ) REORDER( "res", dat->res[chunk] ); if ( toOrder & SMF__NOI && dat->noi ) REORDER( "noi", dat->noi[chunk] ); if ( toOrder & SMF__QUA && dat->qua ) REORDER( "qua", dat->qua[chunk] ); if ( toOrder & SMF__LUT && dat->lut ) REORDER( "lut", dat->lut[chunk] ); }
void smf_history_add( smfData* data, const char * appl, int * status ) { smfFile *file = NULL; /* data->file */ int done; /* Flag to denote whether history entry has been added */ AstKeyMap *history; /* AstKeyMap storing history information */ /* Check entry status */ if (*status != SAI__OK) return; /* Check that we have a smfData */ if ( data == NULL ) { *status = SAI__ERROR; errRep( FUNC_NAME, "Supplied smfData is a NULL pointer. Possible programming error.", status); return; } /* Now add entry to the history AstKeyMap if not already present */ if ( data->history == NULL ) { history = astKeyMap(" " ); data->history = history; astMapPut0I( data->history, appl, 1, " " ); } else if ( !astMapGet0I( data->history, appl, &done ) ) { astMapPut0I( data->history, appl, 1, " " ); } /* If we have a file, write the history entry into the file */ file = data->file; if ( (file !=NULL) && (file->ndfid != NDF__NOID) ) { smf_history_write( data, status); } msgOutiff( MSG__DEBUG2, " ", "Adding history item '%s'", status, appl); }
void gsdac_getSampleMode ( const gsdVars *gsdVars, char *samMode, char *obsType, int *status ) { /* Check inherited status */ if ( *status != SAI__OK ) return; /* Get the observation type (science, pointing, or focus). */ if ( strncmp ( gsdVars->obsType, "FIVEPOINT", 9 ) == 0 ) strcpy ( obsType, "pointing" ); else if ( strncmp ( gsdVars->obsType, "FOCUS", 5 ) == 0 ) strcpy ( obsType, "focus" ); else if ( strncmp ( gsdVars->obsType, "SKYDIP", 6 ) == 0 ) strcpy ( obsType, "skydip" ); else if ( strncmp ( gsdVars->obsType, "SAMPLE", 6 ) == 0 || strncmp ( gsdVars->obsType, "GRID", 4 ) == 0 || strncmp ( gsdVars->obsType, "ON/OFF", 6 ) == 0 || strncmp ( gsdVars->obsType, "PATTERN", 7 ) == 0 || strncmp ( gsdVars->obsType, "RASTER", 6 ) == 0 || strncmp ( gsdVars->obsType, "SPIRAL", 6 ) == 0 ) { strcpy ( obsType, "science" ); } else { *status = SAI__ERROR; errRep ( "gsdac_getSampleMode", "Error getting OBS_TYPE", status ); return; } /* Get the switch mode and sample mode in ACSIS format. */ if ( strncmp ( gsdVars->obsType, "RASTER", 6 ) == 0 ) strcpy ( samMode, "scan" ); else strcpy ( samMode, "grid" ); }
/* Main entry point. */ void smf_calcmodel_smo( ThrWorkForce *wf, smfDIMMData *dat, int chunk, AstKeyMap *keymap, smfArray **allmodel, int flags __attribute__((unused)), int *status) { /* Local Variables */ size_t bstride; /* bolo stride */ dim_t boxcar = 0; /* size of boxcar smooth window */ smf_filt_t filter_type; /* The type of smoothing to perform */ size_t i; /* Loop counter */ dim_t idx=0; /* Index within subgroup */ int iworker; /* Owkrer index */ smfCalcmodelSmoJobData *job_data=NULL; /* Pointer to all job data structures */ AstKeyMap *kmap=NULL; /* Pointer to PLN-specific keys */ smfArray *model=NULL; /* Pointer to model at chunk */ double *model_data=NULL; /* Pointer to DATA component of model */ double *model_data_copy=NULL; /* Copy of model_data for one bolo */ dim_t nbolo=0; /* Number of bolometers */ dim_t ndata=0; /* Total number of data points */ int notfirst=0; /* flag for delaying until after 1st iter */ dim_t ntslice=0; /* Number of time slices */ int nworker; /* No. of worker threads in supplied Workforce */ smfCalcmodelSmoJobData *pdata=NULL; /* Pointer to current data structure */ smfArray *qua=NULL; /* Pointer to QUA at chunk */ smf_qual_t *qua_data=NULL; /* Pointer to quality data */ smfArray *res=NULL; /* Pointer to RES at chunk */ double *res_data=NULL; /* Pointer to DATA component of res */ int step; /* Number of bolometers per thread */ size_t tstride; /* Time slice stride in data array */ const char * typestr = NULL; /* smo.type value */ /* Main routine */ if (*status != SAI__OK) return; /* Obtain pointers to relevant smfArrays for this chunk */ res = dat->res[chunk]; qua = dat->qua[chunk]; /* Obtain pointer to sub-keymap containing PLN parameters. Something will always be available.*/ astMapGet0A( keymap, "SMO", &kmap ); /* Are we skipping the first iteration? */ astMapGet0I(kmap, "NOTFIRST", ¬first); if( notfirst && (flags & SMF__DIMM_FIRSTITER) ) { msgOutif( MSG__VERB, "", FUNC_NAME ": skipping SMO this iteration", status ); return; } /* Get the boxcar size */ if( kmap ) smf_get_nsamp( kmap, "BOXCAR", res->sdata[0], &boxcar, status ); /* Get the type of smoothing filter to use. Anthing that is not "MEDIAN" is mean */ filter_type = SMF__FILT_MEAN; if (astMapGet0C( kmap, "TYPE", &typestr ) ) { if (strncasecmp( typestr, "MED", 3 ) == 0 ) { filter_type = SMF__FILT_MEDIAN; } } /* Assert bolo-ordered data */ smf_model_dataOrder( wf, dat, allmodel, chunk, SMF__RES|SMF__QUA, 0, status ); smf_get_dims( res->sdata[0], NULL, NULL, NULL, &ntslice, &ndata, NULL, NULL, status); model = allmodel[chunk]; msgOutiff(MSG__VERB, "", " Calculating smoothed model using boxcar of width %" DIM_T_FMT " time slices", status, boxcar); /* Create structures used to pass information to the worker threads. */ nworker = wf ? wf->nworker : 1; job_data = astMalloc( nworker*sizeof( *job_data ) ); /* Loop over index in subgrp (subarray) and put the previous iteration of the filtered component back into the residual before calculating and removing the new filtered component */ for( idx=0; (*status==SAI__OK)&&(idx<res->ndat); idx++ ) { /* Obtain dimensions of the data */ smf_get_dims( res->sdata[idx], NULL, NULL, &nbolo, &ntslice, &ndata, &bstride, &tstride, status); /* Get pointers to data/quality/model */ res_data = (res->sdata[idx]->pntr)[0]; qua_data = (qua->sdata[idx]->pntr)[0]; model_data = (model->sdata[idx]->pntr)[0]; if( (res_data == NULL) || (model_data == NULL) || (qua_data == NULL) ) { *status = SAI__ERROR; errRep( "", FUNC_NAME ": Null data in inputs", status); } else { /* Uncomment to aid debugging */ /* smf_write_smfData( res->sdata[idx], NULL, qua_data, "res_in", NULL, 0, 0, MSG__VERB, 0, status ); */ if( *status == SAI__OK ) { /* Place last iteration back into residual if this is a smoothable section of the time series */ for (i=0; i< ndata; i++) { if ( !(qua_data[i]&SMF__Q_FIT) && res_data[i] != VAL__BADD && model_data[i] != VAL__BADD ) { res_data[i] += model_data[i]; } } } /* Uncomment to aid debugging */ /* smf_write_smfData( model->sdata[idx], NULL, qua_data, "model_b4", NULL, 0, 0, MSG__VERB, 0, status ); smf_write_smfData( res->sdata[idx], NULL, qua_data, "res_b4", NULL, 0, 0, MSG__VERB, 0, status ); */ /* Determine which bolometers are to be processed by which threads. */ step = nbolo/nworker; if( step < 1 ) step = 1; for( iworker = 0; iworker < nworker; iworker++ ) { pdata = job_data + iworker; pdata->b1 = iworker*step; pdata->b2 = pdata->b1 + step - 1; } /* Ensure that the last thread picks up any left-over bolometers */ pdata->b2 = nbolo - 1; /* Store all the other info needed by the worker threads, and submit the jobs to apply the smoothing. */ for( iworker = 0; iworker < nworker; iworker++ ) { pdata = job_data + iworker; pdata->boxcar = boxcar; pdata->bstride = bstride; pdata->bstride = bstride; pdata->filter_type = filter_type; pdata->model_data = model_data; pdata->nbolo = nbolo; pdata->nbolo = nbolo; pdata->ntslice = ntslice; pdata->ntslice = ntslice; pdata->qua_data = qua_data; pdata->qua_data = qua_data; pdata->res_data = res_data; pdata->res_data = res_data; pdata->tstride = tstride; pdata->tstride = tstride; thrAddJob( wf, THR__REPORT_JOB, pdata, smf1_calcmodel_smo_job, 0, NULL, status ); } thrWait( wf, status ); /* Uncomment to aid debugging */ /* smf_write_smfData( res->sdata[idx], NULL, qua_data, "res_af", NULL, 0, 0, MSG__VERB, 0, status ); smf_write_smfData( model->sdata[idx], NULL, qua_data, "model_af", NULL, 0, 0, MSG__VERB, 0, status ); */ } } /* Free work space (astFree returns without action if a NULL pointer is supplied). */ model_data_copy = astFree( model_data_copy ); job_data = astFree( job_data ); /* Annul AST Object pointers (astAnnul reports an error if a NULL pointer is supplied). */ if( kmap ) kmap = astAnnul( kmap ); }
void atlKy2hd( AstKeyMap *keymap, HDSLoc *loc, int *status ) { /* * Name: * atlKy2hd * Purpose: * Copies values from an AST KeyMap to a primitive HDS object. * Language: * C. * Invocation: * void atlKy2hd( AstKeyMap *keymap, HDSLoc *loc, int *status ) * Description: * This routine copies the contents of an AST KeyMap into a supplied * HDS structure. * Arguments: * keymap * An AST pointer to the KeyMap. * loc * A locator for the HDS object into which the KeyMap contents * are to be copied. A new component is added to the HDS object for * each entry in the KeyMap. * status * The inherited status. * Copyright: * Copyright (C) 2008, 2010, 2012 Science & Technology Facilities Council. * All Rights Reserved. * Licence: * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be * useful,but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street,Fifth Floor, Boston, MA * 02110-1301, USA * Authors: * DSB: David S. Berry * TIMJ: Tim Jenness (JAC, Hawaii) * {enter_new_authors_here} * History: * 29-APR-2008 (DSB): * Original version. * 2010-09-23 (TIMJ): * Fix arrays of strings. * 2010-09-30 (TIMJ): * Make sure that we are using the correct status pointer in AST. * 2010-10-01 (TIMJ): * Sort the keys when writing to HDS structured. * 2010-10-04 (TIMJ): * Support Short ints in keymap * 14-SEP-2012 (DSB): * Moved from kaplibs to atl. * 17-SEP-2012 (DSB): * Add support for undefined values. * {enter_further_changes_here} * Bugs: * {note_any_bugs_here} */ /* Local Varianles: */ AstObject **objArray = NULL; AstObject *obj = NULL; HDSLoc *cloc = NULL; HDSLoc *dloc = NULL; const char *cval = NULL; const char *key; double dval; float fval; int i; int ival; int j; int lenc; int nval; char *oldsortby; int *oldstat = NULL; int size; int type; int veclen; size_t el; void *pntr = NULL; /* Check inherited status */ if( *status != SAI__OK ) return; /* Make sure that we are checking AST status */ oldstat = astWatch( status ); /* If set, save the old SortBy value and then ensure alphabetical sorting. We need to take a copy of the original string since the buffer in which the string is stored may be re-used by subsequent incocations of astGetC. */ if( astTest( keymap, "SortBy" ) ) { int nc = 0; oldsortby = astAppendString( NULL, &nc, astGetC( keymap, "SortBy" ) ); } else { oldsortby = NULL; } astSet( keymap, "SortBy=KeyUp" ); /* Loop round each entry in the KeyMap. */ size = astMapSize( keymap ); for( i = 0; i < size; i++ ) { if (*status != SAI__OK) break; /* Get the key. the data type and the vector length for the current KeyMap entry. */ key = astMapKey( keymap, i ); type = astMapType( keymap, key ); veclen = astMapLength( keymap, key ); /* If the current entry holds one or more nested KeyMaps, then we call this function recursively to add them into a new HDS component. */ if( type == AST__OBJECTTYPE ) { /* First deal with scalar entries holding a single KeyMap. */ if( veclen == 1 ) { datNew( loc, key, "KEYMAP_ENTRY", 0, NULL, status ); datFind( loc, key, &cloc, status ); (void) astMapGet0A( keymap, key, &obj ); if( astIsAKeyMap( obj ) ) { atlKy2hd( (AstKeyMap *) obj, cloc, status ); } else if( *status == SAI__OK ) { *status = SAI__ERROR; errRep( "", "atlKy2hd: Supplied KeyMap contains unusable AST " "objects (programming error).", status ); } datAnnul( &cloc, status ); /* Now deal with vector entries holding multiple KeyMaps. */ } else { datNew( loc, key, "KEYMAP_ENTRY", 1, &veclen, status ); datFind( loc, key, &cloc, status ); objArray = astMalloc( sizeof( AstObject *) * (size_t)veclen ); if( objArray ) { (void) astMapGet1A( keymap, key, veclen, &nval, objArray ); for( j = 1; j <= veclen; j++ ) { datCell( cloc, 1, &j, &dloc, status ); if( astIsAKeyMap( objArray[ j - 1 ] ) ) { atlKy2hd( (AstKeyMap *) objArray[ j - 1 ], dloc, status ); } else if( *status == SAI__OK ) { *status = SAI__ERROR; errRep( "", "atlKy2hd: Supplied KeyMap contains unusable AST " "objects (programming error).", status ); } datAnnul( &dloc, status ); } objArray = astFree( objArray ); } datAnnul( &cloc, status ); } /* For primitive types... */ } else if( type == AST__INTTYPE ) { if( veclen == 1 ) { datNew0I( loc, key, status ); datFind( loc, key, &cloc, status ); (void) astMapGet0I( keymap, key, &ival ); datPut0I( cloc, ival, status ); datAnnul( &cloc, status ); } else { datNew1I( loc, key, veclen, status ); datFind( loc, key, &cloc, status ); datMapV( cloc, "_INTEGER", "WRITE", &pntr, &el, status ); (void) astMapGet1I( keymap, key, veclen, &nval, (int *) pntr ); datUnmap( cloc, status ); datAnnul( &cloc, status ); } } else if( type == AST__SINTTYPE ) { short sval = 0; if( veclen == 1 ) { datNew0W( loc, key, status ); datFind( loc, key, &cloc, status ); (void) astMapGet0S( keymap, key, &sval ); datPut0W( cloc, sval, status ); datAnnul( &cloc, status ); } else { datNew1W( loc, key, veclen, status ); datFind( loc, key, &cloc, status ); datMapV( cloc, "_WORD", "WRITE", &pntr, &el, status ); (void) astMapGet1S( keymap, key, veclen, &nval, (short *) pntr ); datUnmap( cloc, status ); datAnnul( &cloc, status ); } } else if( type == AST__DOUBLETYPE ) { if( veclen == 1 ) { datNew0D( loc, key, status ); datFind( loc, key, &cloc, status ); (void) astMapGet0D( keymap, key, &dval ); datPut0D( cloc, dval, status ); datAnnul( &cloc, status ); } else { datNew1D( loc, key, veclen, status ); datFind( loc, key, &cloc, status ); datMapV( cloc, "_DOUBLE", "WRITE", &pntr, &el, status ); (void) astMapGet1D( keymap, key, veclen, &nval, (double *) pntr ); datUnmap( cloc, status ); datAnnul( &cloc, status ); } } else if( type == AST__FLOATTYPE ) { if( veclen == 1 ) { datNew0R( loc, key, status ); datFind( loc, key, &cloc, status ); (void) astMapGet0F( keymap, key, &fval ); datPut0R( cloc, fval, status ); datAnnul( &cloc, status ); } else { datNew1R( loc, key, veclen, status ); datFind( loc, key, &cloc, status ); datMapV( cloc, "_REAL", "WRITE", &pntr, &el, status ); (void) astMapGet1F( keymap, key, veclen, &nval, (float *) pntr ); datUnmap( cloc, status ); datAnnul( &cloc, status ); } } else if( type == AST__STRINGTYPE ) { lenc = astMapLenC( keymap, key ); if( veclen == 1 ) { datNew0C( loc, key, lenc, status ); datFind( loc, key, &cloc, status ); (void) astMapGet0C( keymap, key, &cval ); datPut0C( cloc, cval, status ); datAnnul( &cloc, status ); } else { datNew1C( loc, key, lenc, veclen, status ); datFind( loc, key, &cloc, status ); datMapV( cloc, "_CHAR", "WRITE", &pntr, &el, status ); (void) atlMapGet1C( keymap, key, veclen*lenc, lenc, &nval, (char *) pntr, status ); datUnmap( cloc, status ); datAnnul( &cloc, status ); } /* KeyMap "UNDEF" values are always scalar and have no corresponding HDS data type. So arbitrarily use an "_INTEGER" primitive with no defined value to represent a KeyMap UNDEF value. */ } else if( type == AST__UNDEFTYPE ) { datNew0L( loc, key, status ); /* Unknown or unsupported data types. */ } else if( *status == SAI__OK ) { *status = SAI__ERROR; msgSeti( "T", type ); errRep( "", "atlKy2hd: Supplied KeyMap contains entries with " "unusable data type (^T) (programming error).", status ); } } /* If it was originally set, re-instate the old SortBy value in the KeyMap, then free the memory. Otherwise, clear the SortBy attribute. */ if( oldsortby ) { astSetC( keymap, "SortBy", oldsortby ); oldsortby = astFree( oldsortby ); } else { astClear( keymap, "SortBy" ); } /* Reset AST status */ astWatch( oldstat ); }
void smf_filter_fromkeymap( smfFilter *filt, AstKeyMap *keymap, const smfHead *hdr, int *dofilt, int *whiten, int *status ) { int dofft=0; /* Set if freq. domain filtering the data */ double f_edgelow; /* Freq. cutoff for low-pass edge filter */ double f_edgehigh; /* Freq. cutoff for high-pass edge filter */ double f_edgesmall; /* Select low-pass based on spatial scale */ double f_edgelarge; /* Select high-pass based on spatial scale */ double f_low; /* Lowest edge frequency */ double f_notchlow[SMF__MXNOTCH]; /* Array low-freq. edges of notch filters */ double f_notchhigh[SMF__MXNOTCH];/* Array high-freq. edges of notch filters */ int f_nnotch=0; /* Number of notch filters in array */ int i; /* Loop count */ int ival = 0; /* Dummy integer argument */ int whitening; /* Will we apply a whitening filter? */ /* Main routine */ if( *status != SAI__OK ) return; if( !filt ) { *status = SAI__ERROR; errRep( "", FUNC_NAME ": NULL smfFilter pointer", status ); return; } if( filt->ndims != 1 ) { *status = SAI__ERROR; errRep( "", FUNC_NAME ": can only create time-series filters at present", status ); return; } /* Search for filtering parameters in the keymap. None of these parameters represent a number of time clies, so we can set the smfData (the 2nd argument) to NULL. */ smf_get_cleanpar( keymap, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &f_edgelow, &f_edgehigh, &f_edgesmall, &f_edgelarge, f_notchlow, f_notchhigh, &f_nnotch, &dofft, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &whitening, NULL, NULL, NULL, NULL, NULL, NULL, NULL, status ); /* Modify edge filters if spacial scales were requested */ smf_scale2freq( f_edgesmall, f_edgelarge, hdr, &f_edgelow, &f_edgehigh, status ); /* Return dofilt if requested */ if( dofilt ) { *dofilt = dofft; } if( f_edgelarge ) { } /* If filtering parameters given, create filter */ if( dofft ) { if( f_edgelow ) { smf_filter_edge( filt, f_edgelow, 1, status ); } if( f_edgehigh ) { smf_filter_edge( filt, f_edgehigh, 0, status ); } if( f_nnotch ) { smf_filter_notch( filt, f_notchlow, f_notchhigh, f_nnotch, status ); } if( ! astMapGet0D( keymap, "FILT_WLIM", &(filt->wlim) ) ) { filt->wlim = VAL__BADD; } /* If no apodisation length has been given, use a default of 1/(steptime*freq) where freq is the lowest edge or notch frequency. We only apodise if we are padding data with zeros. */ if( astMapGet0I( keymap, "ZEROPAD", &ival ) && ival ) { if( astMapGet0I( keymap, "APOD", &ival ) ) { filt->apod_length = ival; } else { f_low = ( f_edgehigh > 0.0 ) ? f_edgehigh : VAL__MAXD; if( f_edgelow > 0.0 && f_edgelow < f_low ) f_low = f_edgelow; for( i = 0; i < f_nnotch; i++ ) { if( f_notchlow[ i ] > 0.0 && f_notchlow[ i ] < f_low ) f_low = f_notchlow[ i ]; } if( f_low != VAL__MAXD ) { filt->apod_length = 0.5*filt->df[0]*filt->rdims[0]/f_low; } else { filt->apod_length = 0; } msgSeti( "P", (int) filt->apod_length ); msgOutif( MSG__VERB, "", "Apodising ^P samples at start and end of " "each time stream.", status ); } } else { filt->apod_length = SMF__BADSZT; msgOutif( MSG__VERB, "", " Data will not be apodised since time streams " "are being padded with artificial data rather than zeros.", status ); } } /* Return whiten if requested */ if( whiten ) *whiten = whitening; }