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;

}
Exemple #2
0
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;
}
Exemple #6
0
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;
}
Exemple #9
0
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++;
      }
    }

  }

}
Exemple #11
0
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;
}
Exemple #13
0
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;
}
Exemple #14
0
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 );
}
Exemple #15
0
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;
      }
    }
  }

}
Exemple #16
0
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;
}
Exemple #18
0
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 );
  }

}
Exemple #19
0
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;
}
Exemple #20
0
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 ); );
Exemple #21
0
/* 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;
}
Exemple #22
0
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;
}
Exemple #25
0
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] );

}
Exemple #26
0
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" );

}
Exemple #28
0
/* 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", &notfirst);

  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 );
}
Exemple #29
0
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;
}