Пример #1
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 );
}
Пример #2
0
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];
}
Пример #3
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;
}
Пример #4
0
int smf_apply_dark( smfData *indata, const smfArray *darks,
                     int *status) {

  size_t dark1;
  size_t dark2;
  smfData * dkdata1 = NULL;
  smfData * dkdata2 = NULL;
  int retval = 0;

  if (*status != SAI__OK) return retval;
  if (!darks) return retval;

  /* work out which darks are suitable */
  smf_choose_darks( darks, indata, &dark1, &dark2, status );

  /* get the file struct and create a token */
  smf_smfFile_msg( indata->file, "FILE", 1, "<no file>" );

  /* and correct for dark */
  if (dark1 != SMF__BADIDX) dkdata1 = darks->sdata[dark1];
  if (dark2 != SMF__BADIDX) dkdata2 = darks->sdata[dark2];
  if (dkdata1 || dkdata2) {

    if (dkdata1) {
      msgSetc("PRIOR", "yes");
    } else {
      msgSetc("PRIOR", "no");
    }
    if (dkdata2) {
      msgSetc("POST", "yes");
    } else {
      msgSetc("POST", "no");
    }
    msgOutif(MSG__VERB," ", "Dark subtracting ^FILE."
             " Prior dark: ^PRIOR  Following dark: ^POST", status);
    smf_subtract_dark( indata, dkdata1, dkdata2, SMF__DKSUB_CHOOSE, status );
    retval = 1;
  } else {
    msgOutif(MSG__QUIET, " ",
             "Warning: File ^FILE has no suitable dark frame",
             status);
  }

  return retval;
}
Пример #5
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 );

}
Пример #6
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 ); );
Пример #7
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;
}
Пример #8
0
void smf_find_science(const Grp * ingrp, Grp **outgrp, int reverttodark,
                      Grp **darkgrp, Grp **flatgrp, int reducedark,
                      int calcflat, smf_dtype darktype, smfArray ** darks,
                      smfArray **fflats, AstKeyMap ** heateffmap,
                      double * meanstep, int * status ) {

  smfSortInfo *alldarks; /* array of sort structs for darks */
  smfSortInfo *allfflats; /* array of fast flat info */
  Grp * dgrp = NULL;  /* Internal dark group */
  double duration_darks = 0.0; /* total duration of all darks */
  double duration_sci = 0.0;  /* Duration of all science observations */
  size_t dkcount = 0; /* Dark counter */
  size_t ffcount = 0; /* Fast flat counter */
  Grp * fgrp = NULL;  /* Fast flat group */
  size_t i;           /* loop counter */
  smfData *infile = NULL; /* input file */
  size_t insize;     /* number of input files */
  size_t nsteps_dark = 0;    /* Total number of steps for darks */
  size_t nsteps_sci = 0;     /* Total number of steps for science */
  AstKeyMap * heatermap = NULL; /* Heater efficiency map */
  AstKeyMap * obsmap = NULL; /* Info from all observations */
  AstKeyMap * objmap = NULL; /* All the object names used */
  AstKeyMap * scimap = NULL; /* All non-flat obs indexed by unique key */
  Grp *ogrp = NULL;   /* local copy of output group */
  size_t sccount = 0; /* Number of accepted science files */
  struct timeval tv1;  /* Timer */
  struct timeval tv2;  /* Timer */

  if (meanstep) *meanstep = VAL__BADD;
  if (outgrp) *outgrp = NULL;
  if (darkgrp) *darkgrp = NULL;
  if (darks) *darks = NULL;
  if (fflats) *fflats = NULL;
  if (heateffmap) *heateffmap = NULL;

  if (*status != SAI__OK) return;

  /* Sanity check to make sure we return some information */
  if ( outgrp == NULL && darkgrp == NULL && darks == NULL && fflats == NULL) {
    *status = SAI__ERROR;
    errRep( " ", FUNC_NAME ": Must have some non-NULL arguments"
            " (possible programming error)", status);
    return;
  }

  /* Start a timer to see how long this takes */
  smf_timerinit( &tv1, &tv2, status );

  /* Create new group for output files */
  ogrp = smf_grp_new( ingrp, "Science", status );

  /* and a new group for darks */
  dgrp =  smf_grp_new( ingrp, "DarkFiles", status );

  /* and for fast flats */
  fgrp =  smf_grp_new( ingrp, "FastFlats", status );

  /* and also create a keymap for the observation description */
  obsmap = astKeyMap( "KeyError=1" );

  /* and an object map */
  objmap = astKeyMap( "KeyError=1" );

  /* This keymap contains the sequence counters for each related
     subarray/obsidss/heater/shutter combination and is used to decide
     if a bad flat is relevant */
  scimap = astKeyMap( "KeyError=1,KeyCase=0" );

  /* This keymap is used to contain relevant heater efficiency data */
  heatermap = astKeyMap( "KeyError=1,KeyCase=0" );

  /* Work out how many input files we have and allocate sufficient sorting
     space */
  insize = grpGrpsz( ingrp, status );
  alldarks = astCalloc( insize, sizeof(*alldarks) );
  allfflats = astCalloc( insize, sizeof(*allfflats) );

  /* check each file in turn */
  for (i = 1; i <= insize; i++) {
    int seqcount = 0;
    char keystr[100];  /* Key for scimap entry */

    /* open the file but just to get the header */
    smf_open_file( ingrp, i, "READ", SMF__NOCREATE_DATA, &infile, status );
    if (*status != SAI__OK) break;

    /* Fill in the keymap with observation details */
    smf_obsmap_fill( infile, obsmap, objmap, status );

    /* Find the heater efficiency map if required */
    if (*status == SAI__OK && heateffmap) {
      char arrayidstr[32];
      smf_fits_getS( infile->hdr, "ARRAYID", arrayidstr, sizeof(arrayidstr),
                     status );
      if (!astMapHasKey( heatermap, arrayidstr ) ) {
        smfData * heateff = NULL;
        dim_t nbolos = 0;
        smf_flat_params( infile, "RESIST", NULL, NULL, NULL, NULL, NULL,
                         NULL, NULL, NULL, NULL, NULL, &heateff, status );
        smf_get_dims( heateff, NULL, NULL, &nbolos, NULL, NULL, NULL, NULL,
                      status );
        if (heateff) astMapPut0P( heatermap, arrayidstr, heateff, NULL );
      }
    }

    /* Get the sequence counter for the file. We do not worry about
       duplicate sequence counters (at the moment) */
    smf_find_seqcount( infile->hdr, &seqcount, status );

    /* The key identifying this subarray/obsidss/heater/shutter combo */
    smf__calc_flatobskey( infile->hdr, keystr, sizeof(keystr), status );

    if (smf_isdark( infile, status )) {
      /* Store the sorting information */
      dkcount = smf__addto_sortinfo( infile, alldarks, i, dkcount, "Dark", status );
      smf__addto_durations( infile, &duration_darks, &nsteps_dark, status );
      astMapPutElemI( scimap, keystr, -1, seqcount );
    } else {
      /* compare sequence type with observation type and drop it (for now)
         if they differ */
      if ( infile->hdr->obstype == infile->hdr->seqtype ) {
        /* Sanity check the header for corruption. Compare RTS_NUM with SEQSTART
           and SEQEND. The first RTS_NUM must either be SEQSTART or else between
           SEQSTART and SEQEND (if someone has giving us a section) */
        int seqstart = 0;
        int seqend = 0;
        int firstnum = 0;
        JCMTState *tmpState = NULL;
        smf_getfitsi( infile->hdr, "SEQSTART", &seqstart, status );
        smf_getfitsi( infile->hdr, "SEQEND", &seqend, status );
        tmpState = infile->hdr->allState;

        if( tmpState ) {
          firstnum = (tmpState[0]).rts_num;
          smf_smfFile_msg( infile->file, "F", 1, "<unknown file>");
          if ( firstnum >= seqstart && firstnum <= seqend ) {
            /* store the file in the output group */
            ndgCpsup( ingrp, i, ogrp, status );
            msgOutif(MSG__DEBUG, " ", "Non-dark file: ^F",status);
            smf__addto_durations( infile, &duration_sci, &nsteps_sci, status );
            astMapPutElemI( scimap, keystr, -1, seqcount );
            sccount++;
          } else {
            msgOutif( MSG__QUIET, "",
                      "File ^F has a corrupt FITS header. Ignoring it.",
                      status );
          }
        } else {
          smf_smfFile_msg( infile->file, "F", 1, "<unknown file>");
          /* store the file in the output group */
          ndgCpsup( ingrp, i, ogrp, status );
          msgOutif( MSG__DEBUG, " ",
                    "File ^F lacks JCMTState: assuming it is non-dark",status);
          smf__addto_durations( infile, &duration_sci, &nsteps_sci, status );
          astMapPutElemI( scimap, keystr, -1, seqcount );
          sccount++;
        }

      } else if (infile->hdr->seqtype == SMF__TYP_FASTFLAT ) {
        ffcount = smf__addto_sortinfo( infile, allfflats, i, ffcount, "Fast flat", status );
      } else {
        smf_smfFile_msg( infile->file, "F", 1, "<unknown file>");
        msgOutif(MSG__DEBUG, " ", "Sequence type mismatch with observation type: ^F",status);
      }
    }

    /* close the file */
    smf_close_file( &infile, status );
  }

  /* Store output group in return variable or else free it */
  if (outgrp) {
    *outgrp = ogrp;
  } else {
    grpDelet( &ogrp, status );
  }

  /* process flatfields if necessary */
  if (ffcount > 0 && fflats ) {
    smfArray * array = NULL;

    /* sort flats into order */
    qsort( allfflats, ffcount, sizeof(*allfflats), smf_sort_bydouble);

    if (fflats) array = smf_create_smfArray( status );

    /* now open the flats and store them if requested */
    if (*status == SAI__OK && array && ffcount) {
      size_t start_ffcount = ffcount;
      AstKeyMap * flatmap = NULL;

      if (calcflat) {
        /* Use AgeUp so that we get the keys out in the sorted order
           that allfflats used */
        flatmap = astKeyMap( "KeyCase=0,KeyError=1,SortBy=AgeDown" );
      }

      /* Read each flatfield. Calculate a responsivity image and a flatfield
         solution. Store these in a keymap along with related information
         which is itself stored in a keymap indexed by a string made of
         OBSIDSS, reference heater value, shutter and subarray.
      */

      for (i = 0; i < start_ffcount; i++ ) {
        size_t ori_index =  (allfflats[i]).index;
        smfData * outfile = NULL;
        char keystr[100];
        AstKeyMap * infomap = astKeyMap( "KeyError=1" );
        int oplen = 0;
        char thisfile[MSG__SZMSG];
        int seqcount = 0;

        /* read filename from group */
        infile = NULL;
        smf_open_file( ingrp, ori_index, "READ", 0, &infile, status );
        if ( *status != SAI__OK ) {
          /* This should not happen because we have already opened
             the file. If it does happen we abort with error. */
          if (infile) smf_close_file( &infile, status );
          break;
        }

        /* Calculate the key for this observation */
        smf__calc_flatobskey( infile->hdr, keystr, sizeof(keystr), status );

        /* Get the file name for error messages */
        smf_smfFile_msg( infile->file, "F", 1, "<unknown file>" );
        msgLoad( "", "^F", thisfile, sizeof(thisfile), &oplen, status );

        /* And the sequence counter to link against science observations */
        smf_find_seqcount( infile->hdr, &seqcount, status );

        /* Prefill infomap */
        astMapPut0C( infomap, "FILENAME", thisfile, "");
        astMapPut0I( infomap, "SEQCOUNT", seqcount, "");

        /* Collapse it */
        if (*status == SAI__OK) {
          smf_flat_fastflat( infile, &outfile, status );
          if (*status == SMF__BADFLAT) {
            errFlush( status );

            if (calcflat) {
              /* Need to generate an outfile like smf_flat_fastflat
                 and one heater setting will force smf_flat_calcflat to fail */
              smf_flat_malloc( 1, infile, NULL, &outfile, status );
            } else {
              if (outfile) smf_close_file( &outfile, status );
              if (infile) smf_close_file( &infile, status );
              infomap = astAnnul( infomap );
              ffcount--;
              continue;
            }
          }
        }

        if (outfile && *status == SAI__OK) {
          smf_close_file( &infile, status );
          infile = outfile;

          if (calcflat) {
            size_t ngood = 0;
            smfData * curresp = NULL;
            int utdate;

            if (*status == SAI__OK) {
              ngood = smf_flat_calcflat( MSG__VERB, NULL, "RESIST",
                                         "FLATMETH", "FLATORDER", NULL, "RESPMASK",
                                         "FLATSNR", NULL, infile, &curresp, status );
              if (*status != SAI__OK) {
                /* if we failed to calculate a flatfield we continue but force the
                   flatfield to be completely bad. This will force the science data associated
                   with the flatfield to be correctly blanked. We do not annul though
                   if we have a SUBPAR error telling us that we have failed to define
                   our parameters properly. */
                if (*status != SUBPAR__NOPAR) errAnnul(status);

                /* parameters of flatfield */
                ngood = 0;

                /* Generate a blank flatfield and blank responsivity image */
                smf_flat_badflat( infile, &curresp, status );
              }

              /* Retrieve the UT date so we can decide whether to compare
                 flatfields */
              smf_getfitsi( infile->hdr, "UTDATE", &utdate, status );

              /* Store the responsivity data for later on and the processed
                 flatfield until we have vetted it */
              astMapPut0P( infomap, "CALCFLAT", infile, "" );
              astMapPut0P( infomap, "RESP", curresp, "" );
              astMapPut0I( infomap, "UTDATE", utdate, "" );
              astMapPut0I( infomap, "ISGOOD", 1, "" );
              astMapPut0I( infomap, "NGOOD", ngood, "" );
              astMapPut0I( infomap, "GRPINDEX", ori_index, "" );
              astMapPut0I( infomap, "SMFTYP", infile->hdr->obstype, "" );
              astMapPutElemA( flatmap, keystr, -1, infomap );

            }

          } else { /* if (calcflat) */
            /* Store the collapsed flatfield  - the processed flat is not stored here yet */
            smf_addto_smfArray( array, infile, status );

            /* Copy the group info */
            ndgCpsup( ingrp, ori_index, fgrp, status );

          }

        } /* if (outfile) */

        /* Annul the keymap (will be fine if it is has been stored in another keymap) */
        infomap = astAnnul( infomap );

      } /* End loop over flatfields */

      /* Now we have to loop over the related flatfields to disable
         bolometers that are not good and also decide whether we
         need to set status to bad. */
      if (*status == SAI__OK && calcflat ) {
        size_t nkeys = astMapSize( flatmap );
        for (i = 0; i < nkeys; i++ ) {
          const char *key = astMapKey( flatmap, i );
          int nf = 0;
          AstKeyMap ** kmaps = NULL;
          int nelem = astMapLength( flatmap, key );
          kmaps = astMalloc( sizeof(*kmaps) * nelem );
          astMapGet1A( flatmap, key, nelem, &nelem, kmaps );

          for ( nf = 0; nf < nelem && *status == SAI__OK; nf++ ) {
            AstKeyMap * infomap = kmaps[nf];
            int isgood = 0;

            astMapGet0I( infomap, "ISGOOD", &isgood );

            if (isgood) {
              /* The flatfield worked */
              size_t ngood = 0;
              int itemp;
              int utdate = 0;
              int ratioFlats = 0;

              /* Get the UT date - we do not compare flatfields after
                 the time we enabled heater tracking at each sequence. */
              astMapGet0I( infomap, "UTDATE", &utdate );

              /* Get the number of good bolometers at this point */
              astMapGet0I( infomap, "NGOOD", &itemp );
              ngood = itemp;

              /* Decide if we want to do the ratio test. We default to
                 not doing it between 20110901 and 20120827 which is
                 the period when we did mini-heater tracks before each
                 flat. ! indicates that we choose based on date. */
              if (*status == SAI__OK) {
                parGet0l( "FLATUSENEXT", &ratioFlats, status );
                if ( *status == PAR__NULL ) {
                  errAnnul( status );
                  if (utdate >= 20110901 || utdate <= 20120827 ) {
                    ratioFlats = 0;
                  } else {
                    ratioFlats = 1;
                  }
                }
              }

              /* Can we compare with the next flatfield? */
              if (ngood < SMF__MINSTATSAMP || !ratioFlats ) {
                /* no point doing all the ratio checking for this */
              } else if ( nelem - nf >= 2 ) {
                AstKeyMap * nextmap = kmaps[nf+1];
                const char *nextfname = NULL;
                const char *fname = NULL;
                smfData * curresp = NULL;
                smfData * nextresp = NULL;
                smfData * curflat = NULL;
                void *tmpvar = NULL;
                size_t bol = 0;
                smfData * ratio = NULL;
                double *in1 = NULL;
                double *in2 = NULL;
                double mean = VAL__BADD;
                size_t nbolo;
                double *out = NULL;
                double sigma = VAL__BADD;
                float clips[] = { 5.0, 5.0 }; /* 5.0 sigma iterative clip */
                size_t ngoodz = 0;

                astMapGet0C( nextmap, "FILENAME", &nextfname );
                astMapGet0C( infomap, "FILENAME", &fname );

                /* Retrieve the responsivity images from the keymap */
                astMapGet0P( infomap, "RESP", &tmpvar );
                curresp = tmpvar;
                astMapGet0P( nextmap, "RESP", &tmpvar );
                nextresp = tmpvar;
                astMapGet0P( infomap, "CALCFLAT", &tmpvar );
                curflat = tmpvar;

                nbolo = (curresp->dims)[0] * (curresp->dims)[1];

                /* get some memory for the ratio if we have not already.
                   We could get some memory once assuming each flat has the
                   same number of bolometers... */
                ratio = smf_deepcopy_smfData( curresp, 0, 0, 0, 0, status );
                if( *status == SAI__OK ) {

                  /* divide: smf_divide_smfData ? */
                  in1 = (curresp->pntr)[0];
                  in2 = (nextresp->pntr)[0];
                  out = (ratio->pntr)[0];

                  for (bol=0; bol<nbolo;bol++) {
                    if ( in1[bol] != VAL__BADD && in1[bol] != 0.0 &&
                         in2[bol] != VAL__BADD && in2[bol] != 0.0 ) {
                      out[bol] = in1[bol] / in2[bol];
                    } else {
                      out[bol] = VAL__BADD;
                    }
                  }
                }

                /* find some statistics */
                smf_clipped_stats1D( out, 2, clips, 1, nbolo, NULL, 0, 0, &mean,
                                     &sigma, NULL, 0, &ngoodz, status );

                if (*status == SMF__INSMP) {
                  errAnnul(status);
                  msgOutiff( MSG__QUIET, "",
                            "Flatfield ramp ratio of %s with %s had too few bolometers (%zu < %d).",
                             status, fname, nextfname, ngoodz, SMF__MINSTATSAMP );
                  ngood = ngoodz; /* Must be lower or equal to original ngood */

                } else if (*status == SAI__OK && mean != VAL__BADD && sigma != VAL__BADD && curflat->da) {
                  /* Now flag the flatfield as bad for bolometers that have changed
                     more than n%. We expect the variation to be 1+/-a small bit */
                  const double pmrange = 0.10;
                  double thrlo = 1.0 - pmrange;
                  double thrhi = 1.0 + pmrange;
                  size_t nmasked = 0;
                  double *flatcal = curflat->da->flatcal;

                  msgOutiff( MSG__DEBUG, "", "Flatfield fast ramp ratio mean = %g +/- %g (%zu bolometers)",
                             status, mean, sigma, ngood);

                  /* we can just set the first slice of the flatcal to bad. That should
                     be enough to disable the entire bolometer. We have just read these
                     data so they should be in ICD order. */
                  for (bol=0; bol<nbolo;bol++) {
                    if ( out[bol] != VAL__BADD &&
                         (out[bol] < thrlo || out[bol] > thrhi ) ) {
                      flatcal[bol] = VAL__BADD;
                      nmasked++;
                    } else if ( in1[bol] != VAL__BADD && in2[bol] == VAL__BADD ) {
                      /* A bolometer is bad next time but good now so we must set it bad now */
                      flatcal[bol] = VAL__BADD;
                      nmasked++;
                    }
                  }

                  if ( nmasked > 0 ) {
                    msgOutiff( MSG__NORM, "", "Masked %zu bolometers in %s from unstable flatfield",
                               status, nmasked, fname );

                    /* update ngood to take into account the masking */
                    ngood -= nmasked;
                  }

                }

                smf_close_file( &ratio, status );

              } /* End of flatfield responsivity comparison */

              /* if we only have a few bolometers left we now consider this
                 a bad flat unless it is actually an engineering measurement
                 where expect some configurations to give zero bolometers */
              if (ngood < SMF__MINSTATSAMP) {
                const char *fname = NULL;
                void * tmpvar = NULL;
                int smftyp = 0;
                smfData * curflat = NULL;
                astMapGet0I( infomap, "SMFTYP", &smftyp );
                astMapGet0C( infomap, "FILENAME", &fname );
                if (smftyp != SMF__TYP_NEP) {
                  msgOutiff( MSG__QUIET, "",
                            "Flatfield %s has %zu good bolometer%s.%s",
                             status, fname, ngood, (ngood == 1 ? "" : "s"),
                             ( ngood == 0 ? "" : " Keeping none.") );
                  isgood = 0;

                  /* Make sure that everything is blanked. */
                  if (ngood > 0) {
                    astMapGet0P( infomap, "CALCFLAT", &tmpvar );
                    curflat = tmpvar;
                    if (curflat && curflat->da) {
                      size_t bol;
                      size_t nbolo = (curflat->dims)[0] * (curflat->dims)[1];
                      double *flatcal = curflat->da->flatcal;
                      for (bol=0; bol<nbolo; bol++) {
                        /* Just need to set the first element to bad */
                        flatcal[bol] = VAL__BADD;
                      }
                    }
                  }

                } else {
                  msgOutiff( MSG__NORM, "",
                            "Flatfield ramp file %s has %zu good bolometer%s. Eng mode.",
                             status, fname, ngood, (ngood == 1 ? "" : "s") );
                }
              }

              /* We do not need the responsivity image again */
              {
                void *tmpvar = NULL;
                smfData * resp = NULL;
                astMapGet0P( infomap, "RESP", &tmpvar );
                resp = tmpvar;
                if (resp) smf_close_file( &resp, status );
                astMapRemove( infomap, "RESP" );
              }

            } /* End of isgood comparison */

            /* We are storing flats even if they failed. Let the downstream
               software worry about it */
            {
              int ori_index;
              smfData * flatfile = NULL;
              void *tmpvar = NULL;

              /* Store in the output group */
              astMapGet0I( infomap, "GRPINDEX", &ori_index );
              ndgCpsup( ingrp, ori_index, fgrp, status );

              /* And store in the smfArray */
              astMapGet0P( infomap, "CALCFLAT", &tmpvar );
              astMapRemove( infomap, "CALCFLAT" );
              flatfile = tmpvar;
              smf_addto_smfArray( array, flatfile, status );
            }

            /* Free the object as we go */
            kmaps[nf] = astAnnul( kmaps[nf] );
          } /* End of loop over this obsidss/subarray/heater */

          kmaps = astFree( kmaps );

        }
      }

      if (array->ndat) {
        if (fflats) *fflats = array;
      } else {
        smf_close_related(&array, status );
        if (fflats) *fflats = NULL;
      }
    }
  }

  /* no need to do any more if neither darks nor darkgrp are defined or we might
     be wanting to revert to darks. */
  if (dkcount > 0 && (darks || darkgrp || reverttodark ) ) {
    smfArray * array = NULL;

    /* sort darks into order */
    qsort( alldarks, dkcount, sizeof(*alldarks), smf_sort_bydouble);

    if (darks) array = smf_create_smfArray( status );

    /* now open the darks and store them if requested */
    if (*status == SAI__OK) {
      for (i = 0; i < dkcount; i++ ) {
        size_t ori_index =  (alldarks[i]).index;

         /* Store the entry in the output group */
        ndgCpsup( ingrp, ori_index, dgrp, status );

        if (darks) {

          /* read the value from the new group */
          smf_open_file( dgrp, i+1, "READ", 0, &infile, status );

          /* do we have to process these darks? */
          if (reducedark) {
            smfData *outfile = NULL;
            smf_reduce_dark( infile, darktype, &outfile, status );
            if (outfile) {
              smf_close_file( &infile, status );
              infile = outfile;
            }
          }

          smf_addto_smfArray( array, infile, status );
        }
      }
      if (darks) *darks = array;
    }
  }

  /* free memory */
  alldarks = astFree( alldarks );
  allfflats = astFree( allfflats );

  if( reverttodark && outgrp && (grpGrpsz(*outgrp,status)==0) &&
      (grpGrpsz(dgrp,status)>0) ) {
    /* If outgrp requested but no science observations were found, and
       dark observations were found, return darks in outgrp and set
       flatgrp and darkgrp to NULL. This is to handle cases where we
       want to process data taken in the dark like normal science
       data. To activate this behaviour set reverttodark */

    msgOutiff( MSG__NORM, "", "Treating the dark%s as science data",
               status, ( dkcount > 1 ? "s" : "" ) );

    *outgrp = dgrp;

    if( darkgrp ){
      *darkgrp = NULL;
    }

    if( flatgrp ) {
      *flatgrp = NULL;
    }

    grpDelet( &ogrp, status);
    grpDelet( &fgrp, status);

    if (meanstep && nsteps_dark > 0) *meanstep = duration_darks / nsteps_dark;

    /* Have to clear the darks smfArray as well */
    if (darks) smf_close_related( darks, status );

  } else {
    /* Store the output groups in the return variable or free it */
    if (darkgrp) {
      *darkgrp = dgrp;
    } else {
      grpDelet( &dgrp, status);
    }
    if (flatgrp) {
      *flatgrp = fgrp;
    } else {
      grpDelet( &fgrp, status);
    }

    if (meanstep && nsteps_sci > 0) *meanstep = duration_sci / nsteps_sci;
  }

  msgSeti( "ND", sccount );
  msgSeti( "DK", dkcount );
  msgSeti( "FF", ffcount );
  msgSeti( "TOT", insize );
  if ( insize == 1 ) {
    if (dkcount == 1) {
      msgOutif( MSG__VERB, " ", "Single input file was a dark",
                status);
    } else if (ffcount == 1) {
      msgOutif( MSG__VERB, " ", "Single input file was a fast flatfield",
                status);
    } else if (sccount == 1) {
      msgOutif( MSG__VERB, " ", "Single input file was accepted (observation type same as sequence type)",
                status);
    } else {
      msgOutif( MSG__VERB, " ", "Single input file was not accepted.",
                status);
    }

  } else {
    if (dkcount == 1) {
      msgSetc( "DKTXT", "was a dark");
    } else {
      msgSetc( "DKTXT", "were darks");
    }
    if (ffcount == 1) {
      msgSetc( "FFTXT", "was a fast flat");
    } else {
      msgSetc( "FFTXT", "were fast flats");
    }
    if (sccount == 1) {
      msgSetc( "NDTXT", "was science");
    } else {
      msgSetc( "NDTXT", "were science");
    }

    /* This might be a useful message */
    msgOutif( MSG__NORM, " ", "Out of ^TOT input files, ^DK ^DKTXT, ^FF ^FFTXT "
              "and ^ND ^NDTXT", status );
  }

  if (meanstep && *meanstep != VAL__BADD) {
    msgOutiff( MSG__VERB, "", "Mean step time for input files = %g sec",
             status, *meanstep );
  }

  /* Store the heater efficiency map */
  if (*status != SAI__OK) heatermap = smf_free_effmap( heatermap, status );
  if (heateffmap) *heateffmap = heatermap;

  /* Now report the details of the observation */
  smf_obsmap_report( MSG__NORM, obsmap, objmap, status );

  obsmap = astAnnul( obsmap );
  objmap = astAnnul( objmap );
  scimap = astAnnul( scimap );

  msgOutiff( SMF__TIMER_MSG, "",
             "Took %.3f s to find science observations",
             status, smf_timerupdate( &tv1, &tv2, status ) );

  return;
}
Пример #9
0
void smurf_unmakecube( int *status ) {

/* Local Variables */
   AstFrame *tfrm = NULL;       /* Current Frame from input WCS */
   AstFrameSet *wcsin = NULL;   /* WCS Frameset for input cube */
   AstMapping *tmap = NULL;     /* Base->current Mapping from input WCS */
   AstSkyFrame *iskyfrm = NULL; /* SkyFrame from the input WCS Frameset */
   Grp *detgrp = NULL;        /* Group of detector names */
   Grp *igrp1 = NULL;         /* Group of input sky cube files */
   Grp *igrp2 = NULL;         /* Group of input template files */
   Grp *ogrp = NULL;          /* Group containing output file */
   NdgProvenance *oprov = NULL;/* Provenance for the output NDF */
   SkyCube *sky_cubes = NULL; /* Pointer to array of sky cube descriptions */
   SkyCube *skycube = NULL;   /* Pointer to next sky cube description */
   char pabuf[ 10 ];          /* Text buffer for parameter value */
   double params[ 4 ];        /* astResample parameters */
   int axes[ 2 ];             /* Indices of selected axes */
   int blank;                 /* Was a blank line just output? */
   int flag;                  /* Was the group expression flagged? */
   int ifile;                 /* Input file index */
   int interp = 0;            /* Pixel interpolation method */
   int iskycube;              /* Index of current sky cube */
   int nel;                   /* Number of elements in 3D array */
   int nparam = 0;            /* No. of parameters required for interpolation scheme */
   int ondf;                  /* Output time series NDF identifier */
   int outax[ 2 ];            /* Indices of corresponding output axes */
   int overlap;               /* Does time series overlap sky cube? */
   int sdim[3];               /* Array of significant pixel axes */
   int usedetpos;             /* Should the detpos array be used? */
   size_t ndet;               /* Number of detectors supplied for "DETECTORS" */
   size_t nskycube;           /* Number of supplied sky cubes */
   size_t outsize;            /* Number of files in output group */
   size_t size;               /* Number of files in input group */
   smfData *data = NULL;      /* Pointer to data struct */
   void *in_data = NULL;      /* Pointer to the input cube data array */
   void *out_data = NULL;     /* Pointer to the output cube data array */

#if defined(FPTRAP)
   feenableexcept(FE_DIVBYZERO|FE_INVALID|FE_OVERFLOW);
#endif

/* Check inherited status */
   if( *status != SAI__OK ) return;

/* We have not yet displayed a blank line on stdout. */
   blank = 0;

/* Begin an AST context */
   astBegin;

/* Begin an NDF context. */
   ndfBegin();

/* Get a group holding the input sky cubes. */
   kpg1Rgndf( "IN", 0, 1, "", &igrp1, &nskycube, status );

/* Create an array of structures to hold information about each input sky
   cube. */
   sky_cubes = astMalloc( sizeof( SkyCube )*(size_t) nskycube );

/* Store a description of each sky cube. */
   if( sky_cubes ) {
      for( iskycube = 0; iskycube < nskycube; iskycube++ ) {
         skycube = sky_cubes + iskycube;

/* Get an NDF identifier for the next sky cube. */
         ndgNdfas( igrp1, iskycube + 1, "READ", &(skycube->indf), status );

/* Get the WCS FrameSet from the sky cube, together with its pixel index
   bounds. */
         kpg1Asget( skycube->indf, 3, 0, 1, 1, sdim, skycube->slbnd,
                    skycube->subnd, &wcsin, status );

/* Get the base->current Mapping from the input WCS FrameSet, and split it
   into two Mappings; one (iskymap) that maps the first 2 GRID axes into
   celestial sky coordinates, and one (ispecmap) that maps the third GRID
   axis into a spectral coordinate. Also extract the SpecFrame and
   SkyFrame from the current Frame. */
         tmap = astGetMapping( wcsin, AST__BASE, AST__CURRENT );
         tfrm = astGetFrame( wcsin, AST__CURRENT );

         axes[ 0 ] = 1;
         axes[ 1 ] = 2;
         astMapSplit( tmap, 2, axes, outax, &(skycube->iskymap) );
         iskyfrm = astPickAxes( tfrm, 2, outax, NULL );

         axes[ 0 ] = 3;
         astMapSplit( tmap, 1, axes, outax, &(skycube->ispecmap) );
         skycube->ispecfrm = astPickAxes( tfrm, 1, outax, NULL );

/* Create a copy of "iskyfrm" representing absolute coords rather than
   offsets. We assume the target is moving if the cube represents offsets. */
         skycube->abskyfrm = astCopy( iskyfrm );
         astClear( skycube->abskyfrm, "SkyRefIs" );
         skycube->moving = ( *status == SAI__OK &&
                             !strcmp( astGetC( iskyfrm, "SkyRefIs" ),
                                      "Origin" ) ) ? 1 : 0;

/* Invert the Mappings (for the convenience of smf_resamplecube), so
   that they go from current Frame to grid axis. */
         astInvert( skycube->ispecmap );
         astInvert( skycube->iskymap );

/* For efficiency, annul manually the unneeded AST objects created in
   this loop. */
         wcsin = astAnnul( wcsin );
         tmap = astAnnul( tmap );
         tfrm = astAnnul( tfrm );
         iskyfrm = astAnnul( iskyfrm );
      }
   }

/* See if the detector positions are to be read from the RECEPPOS array
   in the template NDFs. Otherwise, they are calculated on the basis of
   the FPLANEX/Y arrays. */
   parGet0l( "USEDETPOS", &usedetpos, status );

/* Get the detectors to use. If a null value is supplied, annull the
   error. Otherwise, make the group case insensitive. */
   detgrp = NULL;
   if( *status == SAI__OK ) {
      kpg1Gtgrp( "DETECTORS", &detgrp, &ndet, status );
      if( *status == PAR__NULL ) {
         errAnnul( status );
	 if (detgrp) {
	   grpDelet( &detgrp, status );
	 }
      } else {
         grpSetcs( detgrp, 0, status );
      }
   }

/* Get the pixel interpolation scheme to use. */
   parChoic( "INTERP", "NEAREST", "NEAREST,LINEAR,SINC,"
             "SINCSINC,SINCCOS,SINCGAUSS,SOMB,SOMBCOS",
             1, pabuf, 10, status );

   if( !strcmp( pabuf, "NEAREST" ) ) {
      interp = AST__NEAREST;
      nparam = 0;

   } else if( !strcmp( pabuf, "LINEAR" ) ) {
      interp = AST__LINEAR;
      nparam = 0;

   } else if( !strcmp( pabuf, "SINC" ) ) {
      interp = AST__SINC;
      nparam = 1;

   } else if( !strcmp( pabuf, "SINCSINC" ) ) {
      interp = AST__SINCSINC;
      nparam = 2;

   } else if( !strcmp( pabuf, "SINCCOS" ) ) {
      interp = AST__SINCCOS;
      nparam = 2;

   } else if( !strcmp( pabuf, "SINCGAUSS" ) ) {
      interp = AST__SINCGAUSS;
      nparam = 2;

   } else if( !strcmp( pabuf, "SOMB" ) ) {
      interp = AST__SOMB;
      nparam = 1;

   } else if( !strcmp( pabuf, "SOMBCOS" ) ) {
      interp = AST__SOMBCOS;
      nparam = 2;

   } else if( *status == SAI__OK ) {
      nparam = 0;
      *status = SAI__ERROR;
      msgSetc( "V", pabuf );
      errRep( "", "Support not available for INTERP = ^V (programming "
              "error)", status );
   }

/* Get an additional parameter vector if required. */
   if( nparam > 0 ) parExacd( "PARAMS", nparam, params, status );

/* Get a group of reference time series files to use as templates for
   the output time series files.*/
   ndgAssoc( "REF", 1, &igrp2, &size, &flag, status );

/* Create a group holding the names of the corresponding output NDFs. */
   ndgCreat ( "OUT", igrp2, &ogrp, &outsize, &flag, status );
   if( outsize != size && *status == SAI__OK ) {
      *status = SAI__ERROR;
      msgSeti( "O", outsize );
      msgSeti( "I", size );
      errRep( "", "Numbers of input reference cubes (^I) and output "
              "cubes (^O) differ.", status );
   }

/* Loop round all the template time series files. */
   for( ifile = 1; ifile <= size && *status == SAI__OK; ifile++ ) {

/* Start a new NDF context. */
      ndfBegin();

/* Obtain information about the current template NDF, but do not map the
   arrays. */
      smf_open_file( igrp2, ifile, "READ", SMF__NOCREATE_DATA, &data, status );

/* Issue a suitable message and abort if anything went wrong. */
      if( *status != SAI__OK ) {
         errRep( FUNC_NAME, "Could not open input template file.", status );
         break;

      } else {
         if( data->file == NULL ) {
            *status = SAI__ERROR;
            errRep( FUNC_NAME, "No smfFile associated with smfData.",
                    status );
            break;

         } else if( data->hdr == NULL ) {
            *status = SAI__ERROR;
            errRep( FUNC_NAME, "No smfHead associated with smfData.",
                    status );
            break;

         }
      }

/* Report the name of the input template. */
      smf_smfFile_msg( data->file, "FILE", 1, "<unknown>" );
      msgSeti( "THISFILE", ifile );
      msgSeti( "NUMFILES", size );
      msgOutif( MSG__NORM, " ", "Simulating ^THISFILE/^NUMFILES ^FILE",
                status );

/* Create the output NDF by propagation from the input template NDF.
   Everything is copied except for the array components and any PROVENANCE
   extension. */
      ndgNdfpr( data->file->ndfid, "TITLE,LABEL,UNITS,AXIS,WCS,HISTORY,"
                "NOEXTENSION(PROVENANCE)", ogrp, ifile, &ondf, status );

/* Ensure the output NDF has a history component. */
      ndfHcre( ondf, status );

/* Get a pointer to the mapped output data array. Set all values bad. */
      ndfMap( ondf, "DATA", "_REAL", "WRITE/BAD", &out_data, &nel, status );

/* If the detector positions are to calculated on the basis of FPLANEX/Y
   rather than detpos, then free the detpos array in the templates smfHead
   structure. This will cause smf_tslice_ast to use the fplanex/y values. */
      if( !usedetpos && data->hdr->detpos ) {
         astFree( (double *) data->hdr->detpos );
         data->hdr->detpos = NULL;
      }

/* Get a pointer to a structure holding provenance information for the
   output time series. */
      oprov = ndgReadProv( ondf, "SMURF:UNMAKECUBE", status );

/* Record details of the template in the provenance structure for the
   output time series. */
      ndgPutProv( oprov, data->file->ndfid, NULL, 0, status );

/* Loop round all input sky cubes. */
      for( iskycube = 0; iskycube < nskycube; iskycube++ ) {
         skycube = sky_cubes + iskycube;

/* Record details of the input cube in the provenance extension of the
   output time series. */
         ndgPutProv( oprov, skycube->indf, NULL, 0, status );

/* See if the current time series overlaps the current sky cube. */
         smf_resampcube( data, skycube->abskyfrm,
                         skycube->iskymap, skycube->ispecfrm,
                         skycube->ispecmap, detgrp, skycube->moving,
                         skycube->slbnd, skycube->subnd, interp,
                         params, NULL, NULL, &overlap, status );

/* If not, pass on to the next sky cube. */
         if( overlap ) {

/* Report the name of the sky cube. */
            ndfMsg( "NDF", skycube->indf );
            msgOutif( MSG__NORM, " ", "   Re-sampling ^NDF", status );

/* Map the data array in the current sky cube. */
            ndfMap( skycube->indf, "DATA", "_REAL", "READ", &in_data, &nel,
                    status );

/* Resample the cube data into the output time series. */
            smf_resampcube( data, skycube->abskyfrm,
                            skycube->iskymap, skycube->ispecfrm,
                            skycube->ispecmap, detgrp, skycube->moving,
                            skycube->slbnd, skycube->subnd, interp,
                            params, in_data, out_data, &overlap, status );

/* Unmap the data array. */
            ndfUnmap( skycube->indf, "DATA", status );
         }
      }

/* Write the provenance structure to the output NDF, and then free it. */
      ndgWriteProv( oprov, ondf, 1, status );
      oprov =ndgFreeProv( oprov, status );

/* Close the input time series file. */
      if( data != NULL ) {
         smf_close_file( &data, status );
         data = NULL;
      }

/* End the NDF context. */
      ndfEnd( status );
   }

/* Close any input data file that is still open due to an early exit from
   the above loop. */
   if( data != NULL ) {
      smf_close_file( &data, status );
      data = NULL;
   }

/* Free remaining resources. */
   if( detgrp != NULL) grpDelet( &detgrp, status);
   if( igrp1 != NULL) grpDelet( &igrp1, status);
   if( igrp2 != NULL) grpDelet( &igrp2, status);
   if( ogrp != NULL) grpDelet( &ogrp, status);
   sky_cubes = astFree( sky_cubes );

/* End the NDF context. */
   ndfEnd( status );

/* End the tile's AST context. */
   astEnd;

/* Issue a status indication.*/
   if( *status == SAI__OK ) {
      msgOutif(MSG__VERB," ",TASK_NAME " succeeded, time series written.", status);
   } else {
      msgOutif(MSG__VERB," ",TASK_NAME " failed.", status);
   }
}
Пример #10
0
void smf_check_pol2( Grp *igrp,  int size, int raw, int *status ) {

/* Local Variables */
   smfData *data = NULL;        /* pointer to  SCUBA2 data struct */
   int i;                       /* Loop counter */

/* Check inherited status */
   if( *status != SAI__OK ) return;

/* Loop over all files in the Grp */
   for( i = 1; i <= size && *status == SAI__OK; i++ ) {

/* Read header info  from the ith input file in the group */
      smf_open_file( NULL, igrp, i, "READ", SMF__NOCREATE_DATA, &data,
                     status );

/* Check there is a file. */
      if(  *status == SAI__OK && data->file == NULL ) {
          *status = SAI__ERROR;
          errRep( FUNC_NAME, "No smfFile associated with smfData.",
                  status );

/* Check there is a header. */
      } else if( *status == SAI__OK && data->hdr == NULL ) {
          smf_smfFile_msg( data->file, "FILE", 1, "<unknown>" );
          *status = SAI__ERROR;
          errRep( FUNC_NAME, "No smfHead associated with ^FILE.",
                  status );
      }

/* Check that there are 3 pixel axes. */
      if(  *status == SAI__OK && data->ndims != 3) {
         smf_smfFile_msg( data->file, "FILE", 1, "<unknown>" );
         msgSeti( "NDIMS", data->ndims );
         *status = SAI__ERROR;
         errRep( FUNC_NAME, "^FILE has ^NDIMS pixel axes, should be 3.",
                 status );
      }

/* Check that POL2 is in the beam. */
      if( *status == SAI__OK && !(data->hdr->inbeam & SMF__INBEAM_POL) ) {
          smf_smfFile_msg( data->file, "FILE", 1, "<unknown>" );
          *status = SAI__ERROR;
          errRep( FUNC_NAME, "^FILE does not contain POL2 data.",
                  status );
      }

/* For raw data check that the NDF Label component is "Q" or "U". */
      if( *status == SAI__OK ) {
         if( raw  ) {
            if( strcmp( data->hdr->dlabel, "Signal" ) ) {
               smf_smfFile_msg( data->file, "FILE", 1, "<unknown>" );
               msgSetc( "L", data->hdr->dlabel );
               *status = SAI__ERROR;
               errRep( FUNC_NAME, "File ^FILE does not contain POL2 "
                       "analysed intensity data (NDF label is '^L' "
                       "but should be 'Signal').", status );
            }

/* For Q/U data check that the NDF Label component is "Q" or "U". */
         } else {
            if( strcmp( data->hdr->dlabel, "Q" ) &&
                strcmp( data->hdr->dlabel, "U" ) ) {
               smf_smfFile_msg( data->file, "FILE", 1, "<unknown>" );
               msgSetc( "L", data->hdr->dlabel );
               *status = SAI__ERROR;
               errRep( FUNC_NAME, "File ^FILE does not contain POL2 "
                       "Q or U data (NDF label is '^L' but should be "
                       "'Q' or 'U').", status );
            }
         }
      }

/* Close the data file */
      smf_close_file( NULL, &data, status);
   }
}
Пример #11
0
void smf_ext2km( int indf, const char *xname, AstKeyMap *keymap,
                 int mode, int *status ){

/* Local Variables */
   HDSLoc *cloc = NULL;
   HDSLoc *sloc = NULL;
   HDSLoc *xloc = NULL;
   const char *key = NULL;
   hdsdim diml[NDF__MXDIM];
   hdsdim dimu[NDF__MXDIM];
   int dim[ NDF__MXDIM ];
   int i;
   int idim;
   int lbnd[ NDF__MXDIM ];
   int ncomp;
   int ndim;
   int nentry;
   int ntime = 0;
   int prim;
   int there;
   int ubnd[ NDF__MXDIM ];

/* Check the inherited status */
   if( *status != SAI__OK ) return;

/* Get the shape of the NDF. */
   ndfBound( indf, 3, lbnd, ubnd, &ndim, status );

/* Get a locator to the named extension. */
   ndfXloc( indf, xname, "READ", &xloc, status );

/* Select the name of the prototype component that determines the length
   of the arrays to be copied. */
   if( !strcmp( xname, "JCMTSTATE" ) ) {
      key = "RTS_NUM";
   } else if( !strcmp( xname, "ACSIS" ) ) {
      key = "TSYS";
   } else {
      cloc = NULL;
      msgSetc( "X", xname );
      errRep( "", "smf_ext2km: Unknown extension specified - '^X'. "
              "Must be 'JCMTSTATE' or 'ACSIS'.", status );
   }

/* Check the prorotype component is present in the extension. Report an
   error if not. */
   datThere( xloc, key, &there, status );
   if( !there && *status == SAI__OK ) {
      msgSetc( "C", key );
      msgSetc( "X", xname );
      errRep( "", "smf_ext2km: Component '^C' not found in extension "
              "^X", status );

/* If it is present, get the length of its last pixel axis. This is the
   length of the arrays to be copied. */
   } else {
      datFind( xloc, key, &cloc, status );
      datShape( cloc, NDF__MXDIM, dim, &ndim, status );
      ntime = dim[ ndim - 1 ];
      datAnnul( &cloc, status );
   }

/* First deal with mode 1... */
/* ========================= */
   if( mode == 1 ) {

/* Loop round every component in the extension. */
      datNcomp( xloc, &ncomp, status );
      for( i = 1; i <= ncomp; i++ ) {
         datIndex( xloc, i, &cloc, status );

/* Check the component has primitive values. */
         datPrim( cloc, &prim, status );
         if( prim ) {

/* Get the shape of the component. */
            datShape( cloc, NDF__MXDIM, dim, &ndim, status );

/* Skip over this component if the length of its final axis is not equal
   to the expected number of time slices. */
            if( ndim > 0 && dim[ ndim - 1 ] == ntime ) {

/* Also skip if we are dealing with the ACSIS extension and the array has
   only 1 (or zero) axes. */
               if( ndim > 1 || strcmp( xname, "ACSIS" ) ) {

/* Cut a section from the HDS array so that it matches the pixel bounds of
   the NDF . */
                  for( idim = 0; idim < ndim - 1; idim++ ) {
                     diml[ idim ] = 1;
                     dimu[ idim ] = dim[ idim ];
                  }
                  diml[ idim ] = lbnd[ 2 ];
                  dimu[ idim ] = ubnd[ 2 ];
                  datSlice( cloc, ndim, diml, dimu, &sloc, status );

/* Store the values as a new entry in "keymap". */
                  kpg1Hdsky( sloc, keymap, 2, 1, status );

/* Annul the locator for the slice. */
                  datAnnul( &sloc, status );
               }
            }
         }
         datAnnul( &cloc, status );
      }

/* Now deal with mode 2... */
/* ========================= */
   } else if( mode == 2 ) {

/* Loop round every entry in the KeyMap. */
      nentry = astMapSize( keymap );
      for( i = 0; i < nentry; i++ ) {
         key = astMapKey( keymap, i );

/* See if the supplied extension has a component with the same name. */
         datThere( xloc, key, &there, status );

/* If it did, check the component is primitive. */
         if( there && *status == SAI__OK ) {
            datFind( xloc, key, &cloc, status );
            datPrim( cloc, &prim, status );
            if( prim ) {

/* Check the final axis of the primitive array has a length equal to the
   expected number of time slices. */
               datShape( cloc, NDF__MXDIM, dim, &ndim, status );
               if( ndim > 0 && dim[ ndim - 1 ] == ntime ) {

/* Also skip if we are dealing with the ACSIS extension and the array has
   only 1 (or zero) axes. */
                  if( ndim > 1 || strcmp( xname, "ACSIS" ) ) {

/* Cut a section from the HDS array so that it matches the pixel bounds of
   the NDF . */
                     for( idim = 0; idim < ndim - 1; idim++ ) {
                        diml[ idim ] = 1;
                        dimu[ idim ] = dim[ idim ];
                     }
                     diml[ idim ] = lbnd[ 2 ];
                     dimu[ idim ] = ubnd[ 2 ];
                     datSlice( cloc, ndim, diml, dimu, &sloc, status );

/* Append the values to the end of the existing KeyMap entry. */
                     kpg1Hdsky( sloc, keymap, 1, 3, status );

/* Annul the locator for the slice. */
                     datAnnul( &sloc, status );

                  }

               } else if( *status == SAI__OK ) {
                  *status = SAI__ERROR;
                  msgSetc( "X", xname );
                  msgSetc( "K", key );
                  ndfMsg( "F", indf );
                  errRep( "", "The ^X.^K array has an unexpected shape in "
                          "\"^F\".", status );
               }

            } else if( *status == SAI__OK ) {
               *status = SAI__ERROR;
               msgSetc( "X", xname );
               msgSetc( "K", key );
               ndfMsg( "F", indf );
               errRep( "", "The ^X.^K array has an unexpected data type in "
                       "\"^F\".", status );
            }

            datAnnul( &cloc, status );

         } else if( *status == SAI__OK ) {
            *status = SAI__ERROR;
            msgSetc( "X", xname );
            msgSetc( "K", key );
            ndfMsg( "F", indf );
            errRep( "", "The ^X.^K array is missing in \"^F\".", status );
         }

      }

/* Now tidy up. */
/* ============ */

/* Report an error if the "mode" value was illegal. */
   } else if( *status == SAI__OK ) {
      *status = SAI__ERROR;
      msgSeti( "MODE", mode );
      errRep( "", "smf_ext2km: Illegal value (^MODE) supplied for "
              "argument MODE (programming error).", status );
   }

/* Free resources. */
   datAnnul( &xloc, status );
}
Пример #12
0
unsigned char *smf_get_mask( ThrWorkForce *wf, smf_modeltype mtype,
                             AstKeyMap *config, smfDIMMData *dat, int flags,
                             int *status ) {

/* Local Variables: */
   AstCircle *circle;         /* AST Region used to mask a circular area */
   AstKeyMap *akm;            /* KeyMap holding AST config values */
   AstKeyMap *subkm;          /* KeyMap holding model config values */
   char refparam[ DAT__SZNAM ];/* Name for reference NDF parameter */
   char words[100];           /* Buffer for variable message words */
   const char *cval;          /* The ZERO_MASK string value */
   const char *modname;       /* The name of the model  being masked */
   const char *skyrefis;      /* Pointer to SkyRefIs attribute value */
   dim_t i;                   /* Pixel index */
   double *pd;                /* Pointer to next element of map data */
   double *predef;            /* Pointer to mask defined by previous run */
   double *ptr;               /* Pointer to NDF  Data array */
   double *pv;                /* Pointer to next element of map variance */
   double centre[ 2 ];        /* Coords of circle centre in radians */
   double meanhits;           /* Mean hits in the map */
   double radius[ 1 ];        /* Radius of circle in radians */
   double zero_circle[ 3 ];   /* LON/LAT/Radius of circular mask */
   double zero_lowhits;       /* Fraction of mean hits at which to threshold */
   double zero_snr;           /* Higher SNR at which to threshold */
   double zero_snrlo;         /* Lower SNR at which to threshold */
   int *ph;                   /* Pointer to next hits value */
   int have_mask;             /* Did a mask already exist on entry? */
   int imask;                 /* Index of next mask type */
   int indf1;                 /* Id. for supplied reference NDF */
   int indf2;                 /* Id. for used section of reference NDF */
   int isstatic;              /* Are all used masks static? */
   int lbnd_grid[ 2 ];        /* Lower bounds of map in GRID coords */
   int mask_types[ NTYPE ];   /* Identifier for the types of mask to use */
   int munion;                /* Use union of supplied masks */
   int nel;                   /* Number of mapped NDF pixels */
   int nmask;                 /* The number of masks to be combined */
   int nsource;               /* No. of source pixels in final mask */
   int skip;                  /* No. of iters for which AST is not subtracted */
   int thresh;                /* Absolute threshold on hits */
   int ubnd_grid[ 2 ];        /* Upper bounds of map in GRID coords */
   int zero_c_n;              /* Number of zero circle parameters read */
   int zero_mask;             /* Use the reference NDF as a mask? */
   int zero_niter;            /* Only mask for the first "niter" iterations. */
   int zero_notlast;          /* Don't zero on last iteration? */
   size_t ngood;              /* Number good samples for stats */
   smf_qual_t *pq;            /* Pinter to map quality */
   unsigned char **mask;      /* Address of model's mask pointer */
   unsigned char *newmask;    /* Individual mask work space */
   unsigned char *pm;         /* Pointer to next returned mask pixel */
   unsigned char *pn;         /* Pointer to next new mask pixel */
   unsigned char *result;     /* Returned mask pointer */

/* Initialise returned values */
   result = NULL;

/* Check inherited status. Also check that a map is being created.  */
   if( *status != SAI__OK || !dat || !dat->map ) return result;

/* Begin an AST context. */
   astBegin;

/* Get the sub-keymap containing the configuration parameters for the
   requested model. Also get a pointer to the mask array to use (there is
   one for each maskable model)*/
   if( mtype == SMF__COM ) {
      modname = "COM";
      mask = &(dat->com_mask);
   } else if( mtype == SMF__AST ) {
      modname = "AST";
      mask = &(dat->ast_mask);
   } else if( mtype == SMF__FLT ) {
      modname = "FLT";
      mask = &(dat->flt_mask);
   } else {
      modname = NULL;
      mask = NULL;
      *status = SAI__ERROR;
      errRepf( " ", "smf_get_mask: Unsupported model type %d supplied - "
               "must be COM, FLT or AST.", status, mtype );
   }
   subkm = NULL;
   astMapGet0A( config, modname, &subkm );

/* Get the "ast.skip" value - when considering "zero_niter" and
   "zero_freeze", we only count iterations for which the AST model
   is subtracted (i.e. the ones following the initial "ast.skip"
   iterations). */
   astMapGet0A( config, "AST", &akm );
   astMapGet0I( akm, "SKIP", &skip );
   akm = astAnnul( akm );

/* Get the number of iterations over which the mask is to be applied. Zero
   means all. Return with no mask if this number of iterations has
   already been performed. */
   zero_niter = 0;
   astMapGet0I( subkm, "ZERO_NITER", &zero_niter );
   if( zero_niter == 0 || dat->iter < zero_niter + skip ) {

/* Only return a mask if this is not the last iteration, or if ZERO_NOTLAST
   is unset. */
      zero_notlast = 0;
      astMapGet0I( subkm, "ZERO_NOTLAST", &zero_notlast );
      if( !( flags & SMF__DIMM_LASTITER ) || !zero_notlast ) {

/* Create a list of the mask types to be combined to get the final mask by
   looking for non-default values for the corresponding configuration
   parameters in the supplied KeyMap. Static masks (predefined, circles
   or external NDFs) may be used on any iteration, but dynamic masks
   (lowhits, snr) will only be avialable once the map has been determined
   at the end of the first iteration. This means that when masking anything
   but the AST model (which is determined after the map), the dynamic masks
   cannot be used on the first iteration. Make a note if all masks being
   used are static. */

         isstatic = 1;
         nmask = 0;

         zero_lowhits = 0.0;
         astMapGet0D( subkm, "ZERO_LOWHITS", &zero_lowhits );
         if( zero_lowhits > 0.0 ) {
            if( mtype == SMF__AST || !( flags & SMF__DIMM_FIRSTITER ) ) {
               mask_types[ nmask++] = LOWHITS;
               isstatic = 0;
            }
         } else if( zero_lowhits <  0.0 && *status == SAI__OK ) {
            *status = SAI__ERROR;
            errRepf( " ", "Bad value for config parameter %s.ZERO_LOWHITS (%g) - "
                     "it must not be negative.", status, modname, zero_lowhits );
         }

         if( astMapGet1D( subkm, "ZERO_CIRCLE", 3, &zero_c_n, zero_circle ) ) {
            if( zero_c_n == 1 || zero_c_n == 3 ) {
               mask_types[ nmask++] = CIRCLE;
            } else if( *status == SAI__OK ) {
               *status = SAI__ERROR;
               errRepf( " ", "Bad number of values (%d) for config parameter "
                        "%s.ZERO_CIRCLE - must be 1 or 3.", status, zero_c_n,
                        modname );
            }
         }

         cval = NULL;
         astMapGet0C( subkm, "ZERO_MASK", &cval );
         if( cval ) {
            if( !astChrMatch( cval, "REF" ) &&
                !astChrMatch( cval, "MASK2" ) &&
                !astChrMatch( cval, "MASK3" ) ) {
               astMapGet0I( subkm, "ZERO_MASK", &zero_mask );
               cval = ( zero_mask > 0 ) ? "REF" : NULL;
            }
            if( cval ) {
               strcpy( refparam, cval );
               astChrCase( NULL, refparam, 1, 0 );
               mask_types[ nmask++] = REFNDF;
            }
         }

         zero_snr = 0.0;
         astMapGet0D( subkm, "ZERO_SNR", &zero_snr );
         if( zero_snr > 0.0 ) {
            if( mtype == SMF__AST || !( flags & SMF__DIMM_FIRSTITER ) ) {
               mask_types[ nmask++] = SNR;
               isstatic = 0;
            }
         } else if( zero_snr <  0.0 && *status == SAI__OK ) {
            *status = SAI__ERROR;
            errRepf( " ", "Bad value for config parameter %s.ZERO_SNR (%g) - "
                     "it must not be negative.", status, modname, zero_snr );
         }

         if( astMapHasKey( subkm, "ZERO_MASK_POINTER" ) ) {
            astMapGet0P( subkm, "ZERO_MASK_POINTER", (void **) &predef );
            if( predef ) mask_types[ nmask++] = PREDEFINED;
         }

/* No need to create a mask if no masking was requested or possible. */
         if( nmask > 0 ) {

/* Decide if we are using the union or intersection of the masks. */
            astMapGet0I( subkm, "ZERO_UNION", &munion );

/* Note if a mask existed on entry. If not, create a mask now, and
   initialise it to hold the mask defined by the initial sky map. */
            if( *mask == NULL ) {
               have_mask = 0;
               if( dat->initqual ) {
                  *mask = astMalloc( dat->msize*sizeof( **mask ) );
                  if( *mask ) {
                     pm = *mask;
                     pq = dat->initqual;
                     for( i = 0; i < dat->msize; i++ ) {
                        *(pm++) = ( *(pq++) != 0 );
                     }
                  }
               } else{
                  *mask = astCalloc( dat->msize, sizeof( **mask ) );
               }
            } else {
               have_mask = 1;
            }

/* If we are combining more than one mask, we need work space to hold
   an individual mask independently of the total mask. If we are using
   only one mask, then just use the main mask array. */
            if( nmask > 1 ) {
               newmask = astMalloc( dat->msize*sizeof( *newmask ) );
            } else {
               newmask = *mask;
            }

/* Get the number of iterations after which the mask is to be frozen.
   Zero means "never freeze the mask". */
            int zero_freeze = 0;
            astMapGet0I( subkm, "ZERO_FREEZE", &zero_freeze );

/* Loop round each type of mask to be used. */
            for( imask = 0; imask < nmask && *status == SAI__OK; imask++ ){

/* If the mask is now frozen, we just return the existing mask. So leave the
   loop. */
               if( zero_freeze != 0 && dat->iter > zero_freeze + skip ) {
                  break;

/* Low hits masking... */
               } else if( mask_types[ imask ] == LOWHITS ) {

/* Set hits pixels with 0 hits to VAL__BADI so that stats1 ignores them */
                  ph = dat->hitsmap;
                  for( i = 0; i < dat->msize; i++,ph++ ) {
                     if( *ph == 0 ) *ph = VAL__BADI;
                  }

/* Find the mean hits in the map */
                  smf_stats1I( dat->hitsmap, 1, dat->msize, NULL, 0, 0, &meanhits,
                               NULL, NULL, &ngood, status );
                  msgOutiff( MSG__DEBUG, " ", "smf_get_mask: mean hits = %lf, ngood "
                             "= %zd", status, meanhits, ngood );

/* Create the mask */
                  thresh = meanhits*zero_lowhits;
                  ph = dat->hitsmap;
                  pn = newmask;
                  for( i = 0; i < dat->msize; i++,ph++ ) {
                     *(pn++) = ( *ph != VAL__BADI && *ph < thresh ) ? 1 : 0;
                  }

/* Report masking info. */
                  msgOutiff( MSG__DEBUG, " ", "smf_get_mask: masking %s "
                             "model at hits = %d.", status, modname, thresh );

/* Circle masking... */
               } else if( mask_types[ imask ] == CIRCLE ) {

/* If we had a mask on entry, then there is no need to create a new one
   since it will not have changed. But we need to recalculate the circle
   mask if are combining it with any non-static masks. */
                  if( ! have_mask || ! isstatic ) {

/* If only one parameter supplied it is radius, assume reference
   LON/LAT from the frameset to get the centre. If the SkyFrame
   represents offsets from the reference position (i.e. the source is
   moving), assume the circle is to be centred on the origin.  */
                     if( zero_c_n == 1 ) {
                        zero_circle[ 2 ] = zero_circle[ 0 ];

                        skyrefis = astGetC( dat->outfset, "SkyRefIs" );
                        if( skyrefis && !strcmp( skyrefis, "Origin" ) ) {
                           zero_circle[ 0 ] = 0.0;
                           zero_circle[ 1 ] = 0.0;
                        } else {
                           zero_circle[ 0 ] = astGetD( dat->outfset, "SkyRef(1)" );
                           zero_circle[ 1 ] = astGetD( dat->outfset, "SkyRef(2)" );
                        }

                        zero_circle[ 0 ] *= AST__DR2D;
                        zero_circle[ 1 ] *= AST__DR2D;
                     }

/* The supplied bounds are for pixel coordinates... we need bounds for grid
    coordinates which have an offset */
                     lbnd_grid[ 0 ] = 1;
                     lbnd_grid[ 1 ] = 1;
                     ubnd_grid[ 0 ] = dat->ubnd_out[ 0 ] - dat->lbnd_out[ 0 ] + 1;
                     ubnd_grid[ 1 ] = dat->ubnd_out[ 1 ] - dat->lbnd_out[ 1 ] + 1;

/* Coordinates & radius of the circular region converted from degrees
   to radians */
                     centre[ 0 ] = zero_circle[ 0 ]*AST__DD2R;
                     centre[ 1 ] = zero_circle[ 1 ]*AST__DD2R;
                     radius[ 0 ] = zero_circle[ 2 ]*AST__DD2R;

/* Create the Circle, defined in the current Frame of the FrameSet (i.e.
   the sky frame). */
                     circle = astCircle( astGetFrame( dat->outfset, AST__CURRENT), 1,
                                         centre, radius, NULL, " " );

/* Fill the mask with zeros. */
                     memset( newmask, 0, sizeof( *newmask )*dat->msize );

/* Get the mapping from the sky frame (current) to the grid frame (base),
   and then set the mask to 1 for all of the values outside this circle */
                     astMaskUB( circle, astGetMapping( dat->outfset, AST__CURRENT,
                                                       AST__BASE ),
                                0, 2, lbnd_grid, ubnd_grid, newmask, 1 );

/* Report masking info. */
                     if( zero_niter == 0 ) {
                        sprintf( words, "on each iteration" );
                     } else {
                        sprintf( words, "for %d iterations", zero_niter );
                     }

                     msgOutiff( MSG__DEBUG, " ", "smf_get_mask: The %s model will"
                                " be masked %s using a circle of "
                                "radius %g arc-secs, centred at %s=%s, %s=%s.",
                                status, modname, words, radius[0]*AST__DR2D*3600,
                                astGetC( dat->outfset, "Symbol(1)" ),
                                astFormat( dat->outfset, 1, centre[ 0 ] ),
                                astGetC( dat->outfset, "Symbol(2)" ),
                                astFormat( dat->outfset, 2, centre[ 1 ] ) );
                  }

/* Reference NDF masking... */
               } else if( mask_types[ imask ] == REFNDF ) {

/* If we had a mask on entry, then there is no need to create a new one
   since it will not have changed. But we need to recalculate the NDF
   mask if are combining it with any non-static masks. */
                  if( ! have_mask || ! isstatic ) {

/* Begin an NDF context. */
                     ndfBegin();

/* Get an identifier for the NDF using the associated ADAM parameter. */
                     ndfAssoc( refparam, "READ", &indf1, status );

/* Get a section from this NDF that matches the bounds of the map. */
                     ndfSect( indf1, 2, dat->lbnd_out, dat->ubnd_out, &indf2,
                              status );

/* Map the section. */
                     ndfMap( indf2, "DATA", "_DOUBLE", "READ", (void **) &ptr,
                             &nel, status );

/* Check we can use the pointer safely. */
                     if( *status == SAI__OK ) {

/* Find bad pixels in the NDF and set those pixels to 1 in the mask. */
                        pn = newmask;
                        for( i = 0; i < dat->msize; i++ ) {
                           *(pn++) = ( *(ptr++) == VAL__BADD ) ? 1 : 0;
                        }

/* Report masking info. */
                        ndfMsg( "N", indf2 );
                        msgSetc( "M", modname );
                        if( zero_niter == 0 ) {
                           msgOutiff( MSG__DEBUG, " ", "smf_get_mask: The ^M "
                                      "model will be masked on each iteration "
                                      "using the bad pixels in NDF '^N'.",
                                      status );
                        } else {
                           msgSeti( "I", zero_niter );
                           msgOutiff( MSG__DEBUG, " ", "smf_get_mask: The ^M "
                                      "model will be masked for ^I iterations "
                                      "using the bad pixels in NDF '^N'.",
                                      status );
                        }
                     }

/* End the NDF context. */
                     ndfEnd( status );
                  }

/* SNR masking... */
               } else if( mask_types[ imask ] == SNR ) {

/* Get the lower SNR limit. */
                  zero_snrlo = 0.0;
                  astMapGet0D( subkm, "ZERO_SNRLO", &zero_snrlo );
                  if( zero_snrlo <= 0.0 ) {
                     zero_snrlo = zero_snr;
                  } else if( zero_snrlo > zero_snr && *status == SAI__OK ) {
                     *status = SAI__ERROR;
                     errRepf( " ", "Bad value for config parameter "
                              "%s.ZERO_SNRLO (%g) - it must not be higher "
                              "than %s.ZERO_SNR (%g).", status, modname,
                              zero_snrlo, modname, zero_snr );
                  }

/* If the higher and lower SNR limits are equal, just do a simple
   threshold on the SNR values to get the mask. */
                  if( zero_snr == zero_snrlo ) {
                     pd = dat->map;
                     pv = dat->mapvar;
                     pn = newmask;
                     for( i = 0; i < dat->msize; i++,pd++,pv++ ) {
                        *(pn++) = ( *pd != VAL__BADD && *pv != VAL__BADD &&
                                    *pv >= 0.0 && *pd < zero_snr*sqrt( *pv ) ) ? 1 : 0;
                     }

/* Report masking info. */
                     if( !have_mask ) {
                        if( zero_niter == 0 ) {
                           sprintf( words, "on each iteration" );
                        } else {
                           sprintf( words, "for %d iterations", zero_niter );
                        }
                        msgOutiff( MSG__DEBUG, " ", "smf_get_mask: The %s model "
                                   "will be masked %s using an SNR limit of %g.",
                                   status, modname, words, zero_snr );
                     }

/* If the higher and lower SNR limits are different, create an initial
   mask by thresholding at the ZERO_SNR value, and then extend the source
   areas within the mask down to an SNR limit of ZERO_SNRLO. */
                  } else {
                     smf_snrmask( wf, dat->map, dat->mapvar, dat->mdims,
                                  zero_snr, zero_snrlo, newmask, status );

/* Report masking info. */
                     if( !have_mask ) {
                        if( zero_niter == 0 ) {
                           sprintf( words, "on each iteration" );
                        } else {
                           sprintf( words, "for %d iterations", zero_niter );
                        }
                        msgOutiff( MSG__DEBUG, " ", "smf_get_mask: The %s model "
                                   "will be masked %s using an SNR limit of %g "
                                   "extended down to %g.", status, modname,
                                   words, zero_snr, zero_snrlo );
                     }
                  }

/* Predefined masking... */
               } else if( mask_types[ imask ] == PREDEFINED ) {

/* If we had a mask on entry, then there is no need to create a new one
   since it will not have changed. But we need to recalculate the
   mask if are combining it with any non-static masks. */
                  if( ! have_mask || ! isstatic ) {

/* Find bad pixels in the predefined array and set those pixels to 1 in
   the mask. */
                     pn = newmask;
                     for( i = 0; i < dat->msize; i++ ) {
                        *(pn++) = ( *(predef++) == VAL__BADD ) ? 1 : 0;
                     }

/* Report masking info. */
                     if( zero_niter == 0 ) {
                        sprintf( words, "on each iteration" );
                     } else {
                        sprintf( words, "for %d iterations", zero_niter );
                     }
                     msgOutiff( MSG__DEBUG, " ", "smf_get_mask: The %s model "
                                "will be masked %s using a smoothed form of "
                                "the final mask created with the previous map.",
                                status, modname, words );
                  }
               }

/* If required, add the new mask into the returned mask. If this is the
   first mask, we just copy the new mask to form the returned mask.
   Otherwise, we combine it with the existing returned mask. */
               if( ! have_mask || ! isstatic ) {
                  if( nmask > 1 ) {
                     if( imask == 0 ) {
                        memcpy( *mask, newmask, dat->msize*sizeof(*newmask));
                     } else {
                        pm = *mask;
                        pn = newmask;
                        if( munion ) {
                           for( i = 0; i < dat->msize; i++,pm++ ) {
                              if( *(pn++) == 0 ) *pm = 0;
                           }
                        } else {
                           for( i = 0; i < dat->msize; i++,pm++ ) {
                              if( *(pn++) == 1 ) *pm = 1;
                           }
                        }
                     }
                  }
               }
            }

/* Free the individual mask work array if it was used. */
            if( nmask > 1 ) newmask = astFree( newmask );

/* Check that the mask has some source pixels (i.e. pixels that have non-bad data values -
   we do not also check variance values since they are not available until the second
   iteration). */
            if( *status == SAI__OK ) {
               nsource = 0;
               pm = *mask;
               pd = dat->map;
               for( i = 0; i < dat->msize; i++,pd++,pv++,pm++ ) {
                  if( *pd != VAL__BADD && *pm == 0 ) nsource++;
               }
               if( nsource < 5 && *status == SAI__OK ) {
                  *status = SAI__ERROR;
                  errRepf( "", "The %s mask being used has fewer than 5 "
                           "source pixels.", status, modname );
                  if( zero_snr > 0.0 ) {
                     errRepf( "", "Maybe your zero_snr value (%g) is too high?",
                              status, zero_snr );
                  }
               }
            }

/* Return the mask pointer if all has gone well. */
            if( *status == SAI__OK ) result = *mask;
         }
      }
   }

/* End the AST context, annulling all AST Objects created in the context. */
   astEnd;

/* Return the pointer to the boolean mask. */
   return result;
}
Пример #13
0
void sc2sim_instap_calc
(
 struct sc2sim_obs_struct *inx, /* Pointer to observation struct */
 int mstp,              /* current microstep */
 double instap[2],      /* Returned focal plane offsets (radians) */
 int *status            /* global status (given and returned) */
 )

{

  /* Local variables */
  double halfx;
  double halfy;
  double instap_arr[2]={0,0};
  double instap_ms[2]={0,0};

  /* Check status */
  if ( *status != SAI__OK ) return;

  /* Calculate midpoint of subarray - include offset from boresight */
  halfx = 0.5 * (inx->colsize + 4) * inx->bol_distx;
  halfy = 0.5 * (inx->rowsize + 4) * inx->bol_disty;

  if  ( strncmp( inx->instap, " ", 1 ) != 0 ) {
    /* Check for valid subarray */
    if ( (strncmp( inx->instap, "s8a", 3 ) == 0 ) ||
         (strncmp( inx->instap, "s4d", 3 ) == 0 ) ){
      instap_arr[0] = halfx;
      instap_arr[1] = -halfy;
    } else if ( (strncmp( inx->instap, "s8b", 3 ) == 0 ) ||
                (strncmp( inx->instap, "s4c", 3 ) == 0 ) ) {
      instap_arr[0] = -halfy;
      instap_arr[1] = -halfx;
    } else if ( (strncmp( inx->instap, "s8c", 3 ) == 0 ) ||
                (strncmp( inx->instap, "s4b", 3 ) == 0 ) ) {
      instap_arr[0] = -halfx;
      instap_arr[1] = halfy;
    } else if ( (strncmp( inx->instap, "s8d", 3 ) == 0 ) ||
                (strncmp( inx->instap, "s4a", 3 ) == 0 ) ) {
      instap_arr[0] = halfy;
      instap_arr[1] = halfx;
    } else {
      if ( strncmp( inx->instap, " ", 1 ) == 0 ) {
        msgSetc("S", inx->instap);
        msgOutif( MSG__VERB, " ",
                  "Unrecognized subarray name, ^S, assuming zero offsets",
                  status );
      }
      instap_arr[0] = 0.0;
      instap_arr[1] = 0.0;
    }
  }

  if ( inx->nmicstep > 1 ) {
    instap_ms[0] = inx->mspat_x[mstp] * inx->bol_distx;
    instap_ms[1] = inx->mspat_y[mstp] * inx->bol_disty;
  }

  inx->instap_x = instap_arr[0] + instap_ms[0];
  inx->instap_y = instap_arr[1] + instap_ms[1];

  instap[0] = DAS2R * inx->instap_x;
  instap[1] = DAS2R * inx->instap_y;

}
Пример #14
0
void smf_calc_mode ( smfHead * hdr, int * status ) {

  char sam_mode[SZFITSTR];   /* Value of SAM_MODE header */
  char obs_type[SZFITSTR];   /* value of OBS_TYPE header */
  char sw_mode[SZFITSTR];    /* value of SW_MODE header */
  char seq_type[SZFITSTR];   /* value of SEQ_TYPE header */
  char inbeamstr[SZFITSTR];  /* value of INBEAM header */

  smf_obstype type = SMF__TYP_NULL;   /* temporary type */
  smf_obstype stype = SMF__TYP_NULL;   /* temporary seq type */
  smf_obsmode mode = SMF__OBS_NULL;   /* temporary mode */
  smf_swmode  swmode = SMF__SWM_NULL; /* Switching mode */
  smf_inbeam_t inbeam = SMF__INBEAM_NOTHING; /* what is in beam? */

  if (*status != SAI__OK) return;

  if (hdr == NULL) {
    *status = SAI__ERROR;
    errRep( " ", "Null pointer supplied to " FUNC_NAME, status );
    return;
  }

  /* Proceed if we're using a valid instrument */
  if( hdr->instrument != INST__NONE ) {

    /* Read the relevant headers */
    smf_fits_getS( hdr, "SAM_MODE", sam_mode, sizeof(sam_mode), status );
    smf_fits_getS( hdr, "SW_MODE", sw_mode, sizeof(sw_mode), status );
    smf_fits_getS( hdr, "OBS_TYPE", obs_type, sizeof(obs_type), status );

    /* INBEAM can be undef */
    inbeamstr[0] = '\0';
    smf_getfitss( hdr, "INBEAM", inbeamstr, sizeof(inbeamstr), status );

    /* SEQ_TYPE is "new" */
    if ( *status == SAI__OK ) {
      smf_fits_getS( hdr, "SEQ_TYPE", seq_type, sizeof(seq_type), status );
      if (*status == SMF__NOKWRD ) {
        errAnnul( status );
        one_strlcpy( seq_type, obs_type, sizeof(seq_type), status );
      }
    }

    /* start with sample type */
    if (strcasecmp( sam_mode, "SCAN" ) == 0 ||
        strcasecmp( sam_mode, "RASTER") == 0 ) {
      mode = SMF__OBS_SCAN;
    } else if (strcasecmp( sam_mode, "STARE" ) == 0) {
      mode = SMF__OBS_STARE;
    } else if (strcasecmp( sam_mode, "DREAM" ) == 0) {
      mode = SMF__OBS_DREAM;
    } else if (strcasecmp( sam_mode, "JIGGLE" ) == 0) {
      mode = SMF__OBS_JIGGLE;
    } else if (strcasecmp( sam_mode, "GRID" ) == 0) {
      mode = SMF__OBS_GRID;
    } else {
      if (*status != SAI__OK) {
        *status = SAI__ERROR;
        msgSetc( "MOD", sam_mode );
        errRep( " ", "Unrecognized observing mode '^MOD'", status );
      }
    }

    /* switching mode: options are "none", "pssw", "chop", "freqsw", "self" */
    if (strcasecmp( sw_mode, "NONE" ) == 0 ) {
      swmode = SMF__SWM_NULL;
    } else if (strcasecmp( sw_mode, "PSSW" ) == 0) {
      swmode = SMF__SWM_PSSW;
    } else if (strcasecmp( sw_mode, "CHOP" ) == 0) {
      swmode = SMF__SWM_CHOP;
    } else if (strcasecmp( sw_mode, "SELF" ) == 0) {
      swmode = SMF__SWM_SELF;
    } else if (strcasecmp( sw_mode, "FREQSW" ) == 0) {
      swmode = SMF__SWM_FREQSW;
    } else {
      if (*status != SAI__OK) {
        *status = SAI__ERROR;
        msgSetc( "MOD", sw_mode );
        errRep( " ", "Unrecognized switching mode '^MOD'", status );
      }
    }

    /* obs type */
    type = smf__parse_obstype( obs_type, status );
    stype = smf__parse_obstype( seq_type, status );

    /* in beam (convert to upper case to make it case insensitive) */
    astChrCase( NULL, inbeamstr, 1, 0 );
    if ( smf_pattern_extract( inbeamstr, "(POL)", NULL, NULL, 0, status ) ) {
      inbeam |= SMF__INBEAM_POL;
    }
    if ( smf_pattern_extract( inbeamstr, "(FTS)", NULL, NULL, 0, status ) ) {
      inbeam |= SMF__INBEAM_FTS;
    }
    if ( smf_pattern_extract( inbeamstr, "(BODY)", NULL, NULL, 0, status ) ) {
      inbeam |= SMF__INBEAM_BLACKBODY;
      /* We could consider ensuring FTS is not set in this case */
    }
  }

  hdr->obstype = type;
  hdr->seqtype = stype;
  hdr->obsmode = mode;
  hdr->swmode = swmode;
  hdr->inbeam = inbeam;

}
Пример #15
0
void smurf_calcqu( int *status ) {

    /* Local Variables: */
    AstFitsChan *fc;           /* Holds FITS headers for output NDFs */
    AstKeyMap *config;         /* Holds all cleaning parameters */
    AstKeyMap *dkpars;         /* Holds dark squid cleaning parameters */
    AstKeyMap *heateffmap = NULL; /* Heater efficiency data */
    AstKeyMap *sub_instruments;/* Indicates which instrument is being used */
    Grp *bgrp = NULL;          /* Group of base names for each chunk */
    Grp *igrp = NULL;          /* Group of input files */
    Grp *ogrp = NULL;          /* Group of output files  */
    Grp *sgrp = NULL;          /* Group of science files */
    HDSLoc *loci = NULL;       /* Locator for output I container file */
    HDSLoc *locq = NULL;       /* Locator for output Q container file */
    HDSLoc *locu = NULL;       /* Locator for output U container file */
    NdgProvenance *oprov;      /* Provenance to store in each output NDF */
    ThrWorkForce *wf;          /* Pointer to a pool of worker threads */
    char headval[ 81 ];        /* FITS header value */
    char ndfname[ 30 ];        /* Name of output Q or U NDF */
    char polcrd[ 81 ];         /* FITS 'POL_CRD' header value */
    char subarray[ 10 ];       /* Subarray name (e.g. "s4a", etc) */
    double angrot;             /* Angle from focal plane X axis to fixed analyser */
    double paoff;              /* WPLATE value corresponding to POL_ANG=0.0 */
    float arcerror;            /* Max acceptable error (arcsec) in one block */
    int block_end;             /* Index of last time slice in block */
    int block_start;           /* Index of first time slice in block */
    int dkclean;               /* Clean dark squids? */
    int fix;                   /* Fix the POL-2 triggering issue? */
    int iblock;                /* Index of current block */
    int iplace;                /* NDF placeholder for current block's I image */
    int ipolcrd;               /* Reference direction for waveplate angles */
    int maxsize;               /* Max no. of time slices in a block */
    int minsize;               /* Min no. of time slices in a block */
    int nc;                    /* Number of characters written to a string */
    int pasign;                /* +1 or -1 indicating sense of POL_ANG value */
    int qplace;                /* NDF placeholder for current block's Q image */
    int submean;               /* Subtract mean value from each time slice? */
    int uplace;                /* NDF placeholder for current block's U image */
    size_t ichunk;             /* Continuous chunk counter */
    size_t idx;                /* Subarray counter */
    size_t igroup;             /* Index for group of related input NDFs */
    size_t inidx;              /* Index into group of science input NDFs */
    size_t nchunk;             /* Number continuous chunks outside iter loop */
    size_t ssize;              /* Number of science files in input group */
    smfArray *concat = NULL;   /* Pointer to smfArray holding bolometer data */
    smfArray *darks = NULL;    /* dark frames */
    smfArray *dkarray = NULL;  /* Pointer to smfArray holding dark squid data */
    smfArray *flatramps = NULL;/* Flatfield ramps */
    smfData *data = NULL;      /* Concatenated data for one subarray */
    smfData *dkdata = NULL;    /* Concatenated dark squid data for one subarray */
    smfGroup *sgroup = NULL;   /* smfGroup corresponding to sgrp */

    /* Check inhereited status */
    if( *status != SAI__OK ) return;

    /* Start new AST and NDF contexts. */
    astBegin;
    ndfBegin();

    /* Find the number of cores/processors available and create a work force
       holding the same number of threads. */
    wf = thrGetWorkforce( thrGetNThread( SMF__THREADS, status ), status );

    /* Get a group of input files */
    kpg1Rgndf( "IN", 0, 1, "  Give more NDFs...", &igrp, &ssize, status );

    /* Get a group containing just the files holding science data. */
    smf_find_science( igrp, &sgrp, 0, NULL, NULL, 1, 1, SMF__NULL, &darks,
                      &flatramps, &heateffmap, NULL, status );

    /* Check we have at least once science file. */
    ssize = grpGrpsz( sgrp, status );
    if( ssize == 0 ) {
        msgOutif( MSG__NORM, " ", "All supplied input frames were DARK.",
                  status );
    } else {

        /* See if a correction should be made for the POL2 triggering issue. */
        parGet0l( "FIX", &fix, status );

        /* Create HDS container files to hold the output NDFs. */
        datCreat( "OUTQ", "CALCQU", 0, 0, status );
        datCreat( "OUTU", "CALCQU", 0, 0, status );

        /* Associate the locators with the structures. */
        datAssoc( "OUTQ", "WRITE", &locq, status );
        datAssoc( "OUTU", "WRITE", &locu, status );

        /* The I images are optional. */
        if( *status == SAI__OK ) {
            datCreat( "OUTI", "CALCQU", 0, 0, status );
            datAssoc( "OUTI", "WRITE", &loci, status );
            if( *status == PAR__NULL ) {
                errAnnul( status );
                loci = NULL;
            }
        }

        /* Group the input files so that all files within a single group have the
           same wavelength and belong to the same subscan of the same observation.
           Also identify chunks of data that are contiguous in time, and
           determine to which such chunk each group belongs. All this information
           is returned in a smfGroup structure ("*sgroup"). */
        smf_grp_related( sgrp, ssize, 1, 1, 0, NULL, NULL, NULL,
                         NULL, &sgroup, &bgrp, NULL, status );

        /* Obtain the number of contiguous chunks. */
        if( *status == SAI__OK ) {
            nchunk = sgroup->chunk[ sgroup->ngroups - 1 ] + 1;
        } else {
            nchunk = 0;
        }

        /* Indicate we have not yet found a value for the ARCERROR parameter. */
        arcerror = 0.0;

        /* Loop over all contiguous chunks */
        for( ichunk = 0; ichunk < nchunk && *status == SAI__OK; ichunk++ ) {

            /* Display the chunk number. */
            if( nchunk > 1 ) {
                msgOutiff( MSG__VERB, "", "   Doing chunk %d of %d.",
                           status, (int) ichunk + 1, (int) nchunk );
            }

            /* Concatenate the data within this contiguous chunk. This produces a
               smfArray ("concat") containing a smfData for each subarray present in
               the chunk. Each smfData holds the concatenated data for a single
               subarray. */
            smf_concat_smfGroup( wf, NULL, sgroup, darks, NULL, flatramps,
                                 heateffmap, ichunk, 1, 1, NULL, 0, NULL, NULL,
                                 0, 0, 0, &concat, NULL, status );

            /* Get a KeyMap holding values for the configuration parameters. Since we
               sorted by wavelength when calling smf_grp_related, we know that all
               smfDatas in the current smfArray (i.e. chunk) will relate to the same
               wavelength. Therefore we can use the same parameters for all smfDatas in
               the current smfArray. */
            sub_instruments = smf_subinst_keymap( SMF__SUBINST_NONE,
                                                  concat->sdata[ 0 ], NULL,
                                                  0, status );
            config = kpg1Config( "CONFIG", "$SMURF_DIR/smurf_calcqu.def",
                                 sub_instruments, status );
            sub_instruments = astAnnul( sub_instruments );


            /* Get the CALCQU specific parameters. */
            if( !astMapGet0I( config, "PASIGN", &pasign ) ) pasign = 1;
            msgOutiff( MSG__VERB, "", "PASIGN=%d", status, pasign );
            if( !astMapGet0D( config, "PAOFF", &paoff ) ) paoff = 0.0;
            msgOutiff( MSG__VERB, "", "PAOFF=%g", status, paoff );
            if( !astMapGet0D( config, "ANGROT", &angrot ) ) angrot = 90.0;
            msgOutiff( MSG__VERB, "", "ANGROT=%g", status, angrot );
            if( !astMapGet0I( config, "SUBMEAN", &submean ) ) submean = 0;
            msgOutiff( MSG__VERB, "", "SUBMEAN=%d", status, submean );

            /* See if the dark squids should be cleaned. */
            if( !astMapGet0I( config, "DKCLEAN", &dkclean ) ) dkclean = 0;

            /* If required, clean the dark squids now since we might need to use them to
               clean the bolometer data. */
            if( dkclean ) {

                /* Create a smfArray containing the dark squid data. For each one, store
                   a pointer to the main header so that smf_clean_smfArray can get at the
                   JCMTState information. */
                dkarray = smf_create_smfArray( status );
                for( idx = 0; idx < concat->ndat && *status == SAI__OK; idx++ ) {
                    data = concat->sdata[ idx ];
                    if( data && data->da && data->da->dksquid ) {
                        dkdata = data->da->dksquid;
                        dkdata->hdr = data->hdr;
                        smf_addto_smfArray( dkarray, dkdata, status );
                    }
                }

                /* Clean the smfArray containing the dark squid data. Use the "CLEANDK.*"
                   parameters. */
                (void) astMapGet0A( config, "CLEANDK", &dkpars );
                smf_clean_smfArray( wf, dkarray, NULL, NULL, NULL, dkpars, status );
                dkpars = astAnnul( dkpars );

                /* Nullify the header pointers so that we don't accidentally close any. */
                if( dkarray ) {
                    for( idx = 0; idx < dkarray->ndat; idx++ ) {
                        dkdata = dkarray->sdata[ idx ];
                        dkdata->hdr = NULL;
                    }

                    /* Free the smfArray holding the dark squid data, but do not free the
                       individual smfDatas within it. */
                    dkarray->owndata = 0;
                    smf_close_related( &dkarray, status );
                }
            }

            /* Now clean the bolometer data */
            smf_clean_smfArray( wf, concat, NULL, NULL, NULL, config, status );

            /* If required correct for the POL2 triggering issue. */
            if( fix ) smf_fix_pol2( wf, concat, status );

            /* Loop round each sub-array in the current contiguous chunk of data. */
            for( idx = 0; idx < concat->ndat && *status == SAI__OK; idx++ ) {
                data = concat->sdata[ idx ];

                /* Find the name of the subarray that generated the data. */
                smf_find_subarray( data->hdr, subarray, sizeof(subarray), NULL,
                                   status );

                /* Display the sub-array. */
                if( concat->ndat > 1 ) {
                    msgOutiff( MSG__VERB, "", "   Doing sub-array %s.",
                               status, subarray );
                }

                /* Create an empty provenance structure. Each input NDF that contributes
                   to the current chunk and array will be added as an ancestor to this
                   structure, which will later be stored in each output NDF created for
                   this chunk and array. */
                oprov = ndgReadProv( NDF__NOID, "SMURF:CALCQU", status );

                /* Indicate we do not yet have any FITS headers for the output NDFs */
                fc = NULL;

                /* Indicate we do not yet know the coordinate reference frame for the
                   half-waveplate angle. */
                polcrd[ 0 ] = 0;
                ipolcrd = 0;

                /* Go through the smfGroup looking for groups of related input NDFs that
                   contribute to the current chunk. */
                for( igroup = 0; igroup < sgroup->ngroups; igroup++ ) {
                    if( sgroup->chunk[ igroup ] == ichunk ) {

                        /* Get the integer index into the GRP group (sgrp) that holds the input NDFs.
                           This index identifies the input NDF that provides the data for the current
                           chunk and subarray. This assumes that the order in which smf_concat_smfGroup
                           stores arrays in the "concat" smfArray matches the order in which
                           smf_grp_related stores arrays within the sgroup->subgroups. */
                        inidx = sgroup->subgroups[ igroup ][ idx ];

                        /* Add this input NDF as an ancestor into the output provenance structure. */
                        smf_accumulate_prov( NULL, sgrp, inidx, NDF__NOID,
                                             "SMURF:CALCQU", &oprov, status );

                        /* Merge the FITS headers from the current input NDF into the FitsChan
                           that holds headers for the output NDFs. The merging retains only those
                           headers which have the same value in all input NDFs. */
                        smf_fits_outhdr( data->hdr->fitshdr, &fc, status );

                        /* Get the polarimetry related FITS headers and check that all input NDFs
                           have usabie values. */
                        headval[ 0 ] = 0;
                        smf_getfitss( data->hdr, "POL_MODE", headval,
                                      sizeof(headval), status );
                        if( strcmp( headval, "CONSTANT" ) && *status == SAI__OK ) {
                            *status = SAI__ERROR;
                            grpMsg( "N", sgrp, inidx );
                            errRep( " ", "Input NDF ^N does not contain "
                                    "polarimetry data obtained with a spinning "
                                    "half-waveplate.", status );
                        }

                        headval[ 0 ] = 0;
                        smf_getfitss( data->hdr, "POLWAVIN", headval,
                                      sizeof(headval), status );
                        if( strcmp( headval, "Y" ) && *status == SAI__OK ) {
                            *status = SAI__ERROR;
                            grpMsg( "N", sgrp, inidx );
                            errRep( " ", "Half-waveplate was not in the beam for "
                                    "input NDF ^N.", status );
                        }

                        headval[ 0 ] = 0;
                        smf_getfitss( data->hdr, "POLANLIN", headval,
                                      sizeof(headval), status );
                        if( strcmp( headval, "Y" ) && *status == SAI__OK ) {
                            *status = SAI__ERROR;
                            grpMsg( "N", sgrp, inidx );
                            errRep( " ", "Analyser was not in the beam for input "
                                    "NDF ^N.", status );
                        }

                        if( polcrd[ 0 ] ) {
                            headval[ 0 ] = 0;
                            smf_getfitss( data->hdr, "POL_CRD", headval,
                                          sizeof(headval), status );
                            if( strcmp( headval, polcrd ) && *status == SAI__OK ) {
                                *status = SAI__ERROR;
                                errRep( " ", "Input NDFs have differing values for "
                                        "FITS header 'POL_CRD'.", status );
                            }

                        } else {
                            smf_getfitss( data->hdr, "POL_CRD", polcrd,
                                          sizeof(polcrd), status );
                            if( !strcmp( polcrd, "FPLANE" ) ) {
                                ipolcrd = 0;
                            } else if( !strcmp( polcrd, "AZEL" ) ) {
                                ipolcrd = 1;
                            } else if( !strcmp( polcrd, "TRACKING" ) ) {
                                ipolcrd = 2;
                            } else if( *status == SAI__OK ) {
                                *status = SAI__ERROR;
                                msgSetc( "N", data->file->name );
                                msgSetc( "V", polcrd );
                                errRep( " ", "Input NDF ^N contains unknown value "
                                        "'^V' for FITS header 'POL_CRD'.", status );
                            }
                        }
                    }
                }

                /* If not already done, get the maximum spatial drift (in arc-seconds) that
                   can be tolerated whilst creating a single I/Q/U image. The default value is
                   half the makemap default pixel size. Also get limits on the number of
                   time slices in any block. */
                if( arcerror == 0.0 ) {
                    parDef0d( "ARCERROR", 0.5*smf_calc_telres( data->hdr->fitshdr,
                              status ), status );
                    parGet0r( "ARCERROR", &arcerror, status );

                    parGet0i( "MAXSIZE", &maxsize, status );
                    parGet0i( "MINSIZE", &minsize, status );
                    if( maxsize > 0 && maxsize < minsize && *status == SAI__OK ) {
                        *status = SAI__ERROR;
                        errRepf( "", "Value of parameter MAXSIZE (%d) is less "
                                 "than value of parameter MINSIZE (%d)", status,
                                 maxsize, minsize );
                    }
                }

                /* The algorithm that calculates I, Q and U assumes that all samples for a
                   single bolometer measure flux from the same point on the sky. Due to
                   sky rotation, this will not be the case - each bolometer will drift
                   slowly across the sky. However, since the drift is (or should be)
                   slow we can apply the I/Q/U algorithm to blocks of contiguous data over
                   which the bolometers do not move significantly. We produce a separate
                   I, Q and U image for each such block. The first block starts at the first
                   time slice in the smfData. */
                block_start = 0;

                /* Find the time slice at which the corner bolometers have moved
                   a critical distance (given by parameter ARCERROR) from their
                   positions at the start of the block. Then back off some time slices
                   to ensure that the block holds an integral number of half-waveplate
                   rotations. */
                block_end = smf_block_end( data, block_start, ipolcrd, arcerror,
                                           maxsize, status );

                /* Loop round creating I/Q/U images for each block. Count them. */
                iblock = 0;
                while( block_end >= 0 && *status == SAI__OK ) {

                    /* Skip very short blocks. */
                    if( block_end - block_start > minsize ) {

                        /* Display the start and end of the block. */
                        msgOutiff( MSG__VERB, "", "   Doing time slice block %d "
                                   "-> %d", status, (int) block_start,
                                   (int) block_end );

                        /* Get the name for the Q NDF for this block. Start of with "Q" followed by
                           the block index. */
                        iblock++;
                        nc = sprintf( ndfname, "Q%d", iblock );

                        /* Append the subarray name to the NDF name. */
                        nc += sprintf( ndfname + nc, "_%s", subarray );

                        /* Append the chunk index to the NDF name. */
                        nc += sprintf( ndfname + nc, "_%d", (int) ichunk );

                        /* Get NDF placeholder for the Q NDF. The NDFs are created inside the
                           output container file. */
                        ndfPlace( locq, ndfname, &qplace, status );

                        /* The name of the U NDF is the same except the initial "Q" is changed to
                           "U". */
                        ndfname[ 0 ] = 'U';
                        ndfPlace( locu, ndfname, &uplace, status );

                        /* The name of the I NDF is the same except the initial "Q" is changed to
                           "I". */
                        if( loci ) {
                            ndfname[ 0 ] = 'I';
                            ndfPlace( loci, ndfname, &iplace, status );
                        } else {
                            iplace = NDF__NOPL;
                        }

                        /* Store the chunk and block numbers as FITS headers. */
                        atlPtfti( fc, "POLCHUNK", (int) ichunk, "Chunk index used by CALCQU", status );
                        atlPtfti( fc, "POLBLOCK", iblock, "Block index used by CALCQU", status );

                        /* Create the Q and U images for the current block of time slices from
                           the subarray given by "idx", storing them in the output container
                           file. */
                        smf_calc_iqu( wf, data, block_start, block_end, ipolcrd,
                                      qplace, uplace, iplace, oprov, fc,
                                      pasign, AST__DD2R*paoff, AST__DD2R*angrot,
                                      submean, status );

                        /* Warn about short blocks. */
                    } else {
                        msgOutiff( MSG__VERB, "", "   Skipping short block of %d "
                                   "time slices (parameter MINSIZE=%d).", status,
                                   block_end - block_start - 1, minsize );
                    }

                    /* The next block starts at the first time slice following the previous
                       block. */
                    block_start = block_end + 1;

                    /* Find the time slice at which the corner bolometers have moved
                       a critical distance (given by parameter ARCERROR) from their
                       positions at the start of the block. Then back off some time slices
                       to ensure that the block holds an integral number of half-waveplate
                       rotations. This returns -1 if all time slices have been used. */
                    block_end = smf_block_end( data, block_start, ipolcrd,
                                               arcerror, maxsize, status );
                }

                /* Free resources */
                oprov = ndgFreeProv( oprov, status );
                fc = astAnnul( fc );
            }
            config = astAnnul( config );

            /* Close the smfArray. */
            smf_close_related( &concat, status );
        }

        /* Annul the locators for the output container files. */
        datAnnul( &locq, status );
        datAnnul( &locu, status );
        if( loci ) datAnnul( &loci, status );

        /* The parameter system hangs onto a primary locator for each container
           file, so cancel the parameters to annul these locators. */
        datCancl( "OUTQ", status );
        datCancl( "OUTU", status );
        datCancl( "OUTI", status );
    }

    /* Free resources. */
    smf_close_related( &darks, status );
    smf_close_related( &flatramps, status );

    if( igrp ) grpDelet( &igrp, status);
    if( sgrp ) grpDelet( &sgrp, status);
    if( bgrp ) grpDelet( &bgrp, status );
    if( ogrp ) grpDelet( &ogrp, status );
    if( sgroup ) smf_close_smfGroup( &sgroup, status );
    if (heateffmap) heateffmap = smf_free_effmap( heateffmap, status );

    /* End the NDF and AST contexts. */
    ndfEnd( status );
    astEnd;

    /* Issue a status indication.*/
    if( *status == SAI__OK ) {
        msgOutif( MSG__VERB, " ", "CALCQU succeeded.", status);
    } else {
        msgOutif( MSG__VERB, " ", "CALCQU failed.", status);
    }
}
Пример #16
0
static int smf1_check_steps( const char *param, int first, dim_t nx,
                             double sizetol, int nold, int nnew,
                             smfStepFix *oldsteps, smfStepFix *newsteps,
                             int *status ){
/*
*  Name:
*     smf1_check_steps

*  Purpose:
*     Compare two sets of steps, issuing a warning for each step that
*     has changed significantly.

*  Invocation:
*     int smf1_check_steps( const char *param, int first, dim_t nx,
*                           double sizetol, int nold, int nnew,
*                           smfStepFix *oldsteps, smfStepFix *newsteps,
*                           int *status )

*  Arguments:
*     param = const char * (Given)
*        Name of parameter to use when asking the user whether to
*        continue to look for further changes.
*     first = int (Given)
*        The index of the first change to report.
*     nx = dim_t (Given)
*        The length of the first axis of the bolometer array.
*     sizetol = double (Given)
*        The minimum significant relative error in step size.
*     nold = int (Given)
*        The number of steps in the "oldsteps" array.
*     nnew = int (Given)
*        The number of steps in the "newsteps" array.
*     oldsteps = smfStepFix * (Given and Returned)
*        A pointer to the first element of an array of smfStepFix structures
*        describing the steps fixed in a previous invocation of this program.
*        The array is sorted on exit.
*     newsteps = smfStepFix * (Given and Returned)
*        A pointer to the first element of an array of smfStepFix structures
*        describing the steps fixed in the current invocation of this program.
*        The array is sorted on exit.
*     status = int * (Given and Returned)
*        Pointer to global status.

*  Description:
*     Firstly, an attempt it made to associated each old step with a
*     corresponding new step (i.e. a new step that occurs at the same
*     time and in the same bolometer as the old step). Warning messages
*     are issued about each old step for which no corresponding new step
*     can be found, or for which the corresponding new step has a
*     significantly different height to the old step. Finally, warnings
*     messages are also issued for each new step that has not been
*     associated with an old step.

*  Returned Value:
*     Zero if no significant differences were found. Non-zero otherwise.

*/

/* Local Variables: */
   double abslim;
   double dsize;
   double dsize_min;
   int *fnew;
   int *new_flags;
   int cont;
   int inew;
   int iold;
   int jnew;
   int match;
   int result;
   smfStepFix *pnew;
   smfStepFix *pold;

/* Initialise the returned value. */
   result = 0;

/* Check the inherited status. */
   if( *status != SAI__OK ) return result;

/* Find the absolute minimum significant difference between step sizes.
   This is "sizetol" times the clipped RMS step size in the new steps. */
   abslim = sizetol*smf1_get_rmssize( nnew, newsteps, status );
   msgSetd( "T", abslim );
   msgOut( "", "Ignoring differences in step size smaller than ^T",
           status );
   msgBlank( status );

/* Allocate memory to hold an array with one element for each new step.
   Each element holds zero if the new step has not yet been associated
   with any old step. Otherwise, it holds the one-based index of the
   associated old step. Initialise it to hold zero at every element. */
   new_flags = astCalloc( nnew, sizeof( *new_flags ) );
   if( *status == SAI__OK ) {

/* Loop round each old step. */
      pold = oldsteps;
      for( iold = 0; iold < nold; iold++,pold++ ) {

/* Ignore old steps with bolometer indicies greater than 5000 */
         if( pold->ibolo > 5000 ) continue;

/* Indicate no new step has yet been associated with the old step. */
         jnew = -1;
         dsize_min = VAL__MAXD;
         match = 0;

/* Loop round all new steps. */
         pnew = newsteps;
         fnew = new_flags;
         for( inew = 0; inew < nnew; inew++,pnew++,fnew++ ) {

/* Ignore this new step if it has already been associated with a previous
   old step. */
            if( ! *fnew ) {

/* See if the current new and old steps occur in the same bolometer and
   have overlapping time spans. If so they are considered to be at the
   same time. */
               if( pold->ibolo == pnew->ibolo &&
                   pold->start <= pnew->end &&
                   pold->end >= pnew->start ) {

/* Get the difference in step size between the old and new steps. */
                  dsize = fabs( pold->size - pnew->size );

/* Note the index of the matching new step that is most similar in height
   to the old step. */
                  if( dsize < dsize_min ) {
                     jnew = inew;
                     dsize_min = dsize;
                  }

/* If the old and new step heights are about the same then we associate
   the new step with the old step. Store the (one based) index of the
   corresponding old step. We do not need to check any more new steps,
   so break out of the new step loop. */
                  if( dsize < abslim ||
                      dsize < sizetol*fabs( 0.5*( pold->size + pnew->size ) ) ) {
                     match = 1;
                     *fnew = iold + 1;
                     break;
                  }
               }
            }
         }

/* If a new step was found at the same time and place as the old step, and
   with the same height, pass on to the next old step. */
         if( ! match ) {

/* If no new step was found at the same time and place as the old step, an old
   step has dissappeared. */
            if( jnew == -1 ) {

/* If the old step was of significant height, tell the user. */
               if( fabs( pold->size ) > abslim ){
                  result++;

                  if( result >= first ) {
                     msgSeti( "N", result );
                     msgSeti( "I", pold->id );
                     msgSetc( "W", pold->corr ? "secondary" : "primary" );
                     msgOut( "", "^N: An old ^W step (index ^I) is no longer found:", status );

                     msgSeti( "B", pold->ibolo );
                     msgSeti( "X", pold->ibolo % nx );
                     msgSeti( "Y", pold->ibolo / nx );
                     msgOut( "", "   Bolometer = ^B (^X,^Y)", status );

                     msgSeti( "S", pold->start );
                     msgSeti( "E", pold->end );
                     msgOut( "", "   Time slice range = ^S:^E", status );

                     msgSetd( "H", pold->size );
                     msgOut( "", "   Height = ^H", status );


                     parGet0l( param, &cont, status );
                     parCancl( param, status );
                     if( !cont || *status != SAI__OK ) break;
                     msgBlank( status );
                  }
               }

/* If one or more new step were found at the same time and place as the
   old step (but with a significantly different height), tell the user
   about the change in height. */
            } else {
               pnew = newsteps + jnew;
               result++;

               if( result >= first ) {
                  msgSeti( "I", result );
                  msgSetd( "O", pold->size );
                  msgSetd( "N", pnew->size );
                  msgOut( "", "^I: Step size changed from ^O to ^N:", status );

                  msgSeti( "I", pnew->id );
                  msgSetc( "W", pnew->corr ? "secondary" : "primary" );
                  msgOut( "", "   New index = ^I (^W)", status );

                  msgSeti( "I", pold->id );
                  msgSetc( "W", pold->corr ? "secondary" : "primary" );
                  msgOut( "", "   Old index = ^I (^W)", status );

                  msgSeti( "B", pold->ibolo );
                  msgSeti( "X", pold->ibolo % nx );
                  msgSeti( "Y", pold->ibolo / nx );
                  msgOut( "", "   Bolometer = ^B (^X,^Y)", status );

                  msgSeti( "S", pold->start );
                  msgSeti( "E", pold->end );
                  msgOut( "", "   Old time slice range = ^S:^E", status );

                  msgSeti( "S", pnew->start );
                  msgSeti( "E", pnew->end );
                  msgOut( "", "   New time slice range = ^S:^E", status );

                  parGet0l( param, &cont, status );
                  parCancl( param, status );
                  if( !cont || *status != SAI__OK ) break;
                  msgBlank( status );
               }
            }
         }
      }

/* We have now checked all old steps for matching new steps. If no
   significant change has yet been found, look for new steps that
   have not been associated with an old step. */
      pnew = newsteps;
      fnew = new_flags;
      for( inew = 0; inew < nnew && cont; inew++,pnew++,fnew++ ) {
         if( ! *fnew ) {

/* If the new step is off significant height, tell the user. */
            if( fabs( pnew->size ) > abslim ){
               result++;

               if( result >= first ) {
                  msgSeti( "N", result );
                  msgSeti( "I", pnew->id );
                  msgSetc( "W", pnew->corr ? "secondary" : "primary" );
                  msgOut( "", "^N: A new ^W step (index ^I) was found:", status );

                  msgSeti( "B", pnew->ibolo );
                  msgSeti( "X", pnew->ibolo % nx );
                  msgSeti( "Y", pnew->ibolo / nx );
                  msgOut( "", "   Bolometer = ^B (^X,^Y)", status );

                  msgSeti( "S", pnew->start );
                  msgSeti( "E", pnew->end );
                  msgOut( "", "   Time slice range = ^S:^E", status );

                  msgSetd( "H", pnew->size );
                  msgOut( "", "   Height = ^H", status );

                  parGet0l( param, &cont, status );
                  parCancl( param, status );
                  if( !cont || *status != SAI__OK ) break;
                  msgBlank( status );
               }
            }
         }
      }
   }

/* Free resources. */
   new_flags = astFree( new_flags );

/* Return the result. */
   return result;
}
Пример #17
0
static smfStepFix *smf1_read_steps( FILE *fd, double dcthresh0,
                                    dim_t dcsmooth0, dim_t dcfitbox0,
                                    int dcmaxsteps0, int dclimcorr0,
                                    size_t nrej0, int nstep0, int *nstep,
                                    int *status ) {
/*
*  Name:
*     smf1_read_steps

*  Purpose:
*     Read step descriptions from a file, and check global values.

*  Invocation:
*     smfStepFix *smf1_read_steps( FILE *fd, double dcthresh0,
*                                  dim_t dcsmooth0, dim_t dcfitbox0,
*                                  int dcmaxsteps0, int dclimcorr0,
*                                  size_t nrej0, int nstep0, int *nstep,
*                                  int *status )

*  Arguments:
*     fd = FILE * (Given)
*        A file descriptor from which to read the details of a set of
*        steps.
*     dcthresh0 = double (Given)
*        Expected value of DCTHRESH.
*     dcsmooth0 = dim_t (Given)
*        Expected value of DCSMOOTH.
*     dcfitbox0 = dim_t (Given)
*        Expected value of DCFITBOX.
*     dcmaxsteps0 = int (Given)
*        Expected value of DCMAXSTEPS.
*     dclimcorr = int (Given)
*        Expected value of DCLIMCORR.
*     nrej0 = size_t (Given)
*        The expected number of bolometers rejected.
*     nstep0 = int (Given)
*        The expected number of step fixes.
*     nstep = int * (Returned)
*        The number of steps fixes read from the file.
*     status = int* (Given and Returned)
*        Pointer to global status.

*  Description:
*     Reads information from the supplied file, returning an array of
*     step fixes. It also issues warnings if any of the global values
*     read from the file are not equal to the supplied expected values.

*  Returned Value:
*     A pointer to an array of smfStepFix structures describing the
*     steps fixes read form the file. The length of this array is equal
*     to "*nstep". The array should be freed using astFree when no longer
*     needed.

*/

/* Local Variables: */
   smfStepFix *result;
   char buf[ 256 ];
   char *c;
   double dval;
   double size;
   int bad;
   int corr;
   int end;
   int ibolo;
   int iline;
   int istep;
   int ival;
   int nc;
   int nold;
   int stage;
   int start;

/* Initialise */
   result = NULL;
   *nstep = 0;

/* Check the inherited status. */
   if( *status != SAI__OK ) return result;

/* Indicate we have not yet reached the tabular data. */
   stage = 0;

/* Initialise the index of the next step */
   istep = 0;

/* Indicate we do not yet know how many steps are described in the text
   file. */
   nold = -1;

/* Indicate no bad lines found yet. */
   bad = 0;

/* Loop round reading lines of text from the supplied file until an
   illegal line is read or the end of file is reached. */
   iline = 0;
   while( !bad && fgets( buf, sizeof(buf), fd ) && *status == SAI__OK ) {
      iline++;

/* Remove trailing white space. */
      c = buf + strlen( buf ) - 1;
      while( isspace( *c ) && c > buf ) c--;
      c[ 1 ] = 0;

/* scanf indicates success if the strings do not fail to match before the
   end of the shorter of the two. So we need to check that sufficient
   characters are compared. Initialise the number of characters compared. */
      nc = 0;

/* If we are not yet in the tabular data, look for header lines, and
   issue a message if the old value is different to the new value. */
      if( stage == 0 ) {

         if( sscanf( buf, "# Number of steps fixed = %d%n", &ival, &nc )
                     && nc > 26 ) {
            if( ival != nstep0 ) {
               msgSeti( "O", ival );
               msgSeti( "N", nstep0 );
               msgOut( "", "No. of steps fixed changed from ^O to ^N",
                       status );
            }

            nold = ival;

         } else if( sscanf( buf, "# Number of bolometers rejected = %d%n",
                            &ival, &nc ) && nc > 34 ) {
            if( ival != (int) nrej0 ) {
               msgSeti( "O", ival );
               msgSeti( "N", nrej0 );
               msgOut( "", "No. of bolometers rejected changed from ^O to ^N",
                       status );
            }

         } else if( sscanf( buf, "# DCFITBOX = %d%n", &ival, &nc ) && nc > 13 ) {
            if( ival != (int) dcfitbox0 ) {
               msgSeti( "O", ival );
               msgSeti( "N", dcfitbox0 );
               msgOut( "", "Warning: DCFITBOX changed from ^O to ^N", status );
            }

         } else if( sscanf( buf, "# DCMAXSTEPS = %d%n", &ival, &nc ) && nc > 14 ) {
            if( ival != dcmaxsteps0 ) {
               msgSeti( "O", ival );
               msgSeti( "N", dcmaxsteps0 );
               msgOut( "", "Warning: DCMAXSTEPS changed from ^O to ^N", status );
            }

         } else if( sscanf( buf, "# DCLIMCORR = %d%n", &ival, &nc ) && nc > 14 ) {
            if( ival != dclimcorr0 ) {
               msgSeti( "O", ival );
               msgSeti( "N", dclimcorr0 );
               msgOut( "", "Warning: DCLIMCORR changed from ^O to ^N", status );
            }

         } else if( sscanf( buf, "# DCSMOOTH = %d%n", &ival, &nc )
                    && nc > 18 ) {
            if( ival != (int) dcsmooth0 ) {
               msgSeti( "O", ival );
               msgSeti( "N", dcsmooth0 );
               msgOut( "", "Warning: DCSMOOTH changed from ^O to ^N", status );
            }

         } else if( sscanf( buf, "# DCTHRESH = %lg%n", &dval, &nc ) && nc > 13 ) {
            if( fabs( dval - dcthresh0 ) > 1.0E-10 ) {
               msgSetd( "O", dval );
               msgSetd( "N", dcthresh0 );
               msgOut( "", "Warning: DCTHRESH changed from ^O to ^N", status );
            }

/* Look for the line that marks the start of the tabular data. */
         } else if( !strcmp( buf, "# istep start end ibolo size corr" ) ) {
            stage = 1;
            msgBlank( status );

/* Allocate the returned array. */
            result = astMalloc( nold*sizeof( *result ) );
            *nstep = nold;

/* Abort if an illegal header line is read. */
         } else if( strcmp( buf, "#" ) &&
                    strncmp( buf, "# Steps fixed in '", 18 ) ) {
            bad = 1;
         }

/* If we are now reading tabular data... */
      } else {

/* Extract the numerical values from the line of text. */
         if( sscanf( buf, "%d %d %d %d %lg %d%n", &ival, &start, &end, &ibolo,
                     &size, &corr, &nc ) == 6 && nc > 14 ) {

/* Report an error if there is a jump in the step index (indicates lines
   missing from the supplied file). */
            if( ival != istep ) {
               *status = SAI__ERROR;
               msgSeti( "I", istep );
               errRep( "", "Step ^I data not found in old steps file:", status );
               bad = 1;

/* Otherwise, store the numerical values in the next element of the
   returned array. */
            } else if( istep < nold ){
               result[ istep ].id = ival;
               result[ istep ].ibolo = ibolo;
               result[ istep ].start = start;
               result[ istep ].end = end;
               result[ istep ].size = size;
               result[ istep ].corr = corr;
            }

/* Increment the index of the next step to check. */
            istep++;

/* Abort if the numerical values cannot be read from the line of text. */
         } else {
            bad = 1;
         }
      }
   }

/* Report an error if the last line read was illegal. */
   if( bad ) {
      *status = SAI__ERROR;
      msgSeti( "I", iline );
      errRep( "", "Illegal line found in old steps file (line ^I):", status );
      msgSetc( "L", buf );
      errRep( "", "'^L'", status );

/* Report an error if the number of steps in the old file is still unknown */
   } else if( nold == -1 ) {
      *status = SAI__ERROR;
      errRep( "", "Required line not found in old steps file:", status );
      errRep( "", "'# Number of steps fixed = ...'", status );

/* Report an error if the number of lines of tabular data was wrong. */
   } else if( istep != nold ) {
      *status = SAI__ERROR;
      errRep( "", "Incorrect number of step descriptions in old steps file.",
              status );
      msgSeti( "I", istep );
      msgSeti( "N", nold );
      errRep( "", "Header says file contains ^N steps but data for ^I "
              "steps was found.", status );
   }

   return result;
}
Пример #18
0
static AstTable *ReadNextTable( FILE *fd, const char *fname, int *iline,
                                int *status ) {
    /*
    *  Name:
    *     ReadOneTable

    *  Purpose:
    *     Reads a single Table from a text file.

    *  Description:
    *     This function reads text from the supplied file descriptor until it
    *     reaches the end of file or encounters an end-of-table marker (a line
    *     consisting just of two or more minus signs with no leading spaces).
    *     It creates an AstTable from the text and returns a pointer to it.

    *  Arguments:
    *     fd
    *        The file descriptor.
    *     fname
    *        The file name - used for error messages.
    *     iline
    *        Pointer to an int holding the number of lines read from the
    *        file so far. Updated on exit to include the lines read by the
    *        invocation of this function.
    *     status
    *        Pointer to the global status variable.

    *  Returned Value:
    *     A pointer to the Table read from the file, or NULL if an error occurs.

    */

    /* Local Variables: */
    AstTable *result;
    AstTable *subtable;
    char **cols;
    char **words;
    char *last_com;
    char *line;
    char *p;
    char *tname;
    char key[ 200 ];
    const char *cval;
    const char *oldname;
    const char *newname;
    double dval;
    int *types;
    int blank;
    int c;
    int com;
    int eot;
    int first;
    int icol;
    int irow;
    int ival;
    int iword;
    int line_len;
    int max_line_len;
    int more;
    int nc;
    int ncol;
    int nrow;
    int nword;
    int skip;
    size_t len;

    /* Initialise */
    result = NULL;

    /* Check the inherited status. */
    if( *status != SAI__OK ) return result;

    /* Create an empty Table. */
    result = astTable( " " );

    /* Allocate a buffer for one one line of text. This will be increased in
       size as required. */
    max_line_len = 80;
    line = astMalloc( max_line_len*sizeof( *line ) );

    /* Read each line of text from the file. */
    eot = 0;
    skip = 1;
    line_len = 0;
    more = 1;
    last_com = NULL;
    cols = NULL;
    first = 1;
    irow = 0;
    types = NULL;

    while( more && *status == SAI__OK ) {
        (*iline)++;
        line_len = 0;

        /* Loop reading characters from the file until a newline or the end of file is
           reached. */
        while( ( c = fgetc( fd ) ) != EOF && c != '\n' ) {

            /* Increment the current line length, and double the size of the line buffer
               if it is full. */
            if( ++line_len >= max_line_len ) {
                max_line_len *= 2;
                line = astRealloc( line, max_line_len*sizeof( *line ) );
                if( *status != SAI__OK ) break;
            }

            /* Store the character. Ignore leading white space. */
            if( skip ) {
                if( ! isspace( c ) ) {
                    line[ line_len - 1 ] = c;
                    skip = 0;
                } else {
                    line_len--;
                }
            } else {
                line[ line_len - 1 ] = c;
            }

        }

        /* If the end-of-file was reached indicate that we should leave the main
           loop after processing the current line. */
        if( c == EOF ) more = 0;

        /* Terminate the line. */
        line[ line_len ] = 0;

        /* Terminate it again to exclude trailing white space. */
        line[ astChrLen( line ) ] = 0;

        /* Assume the line is a blank non-comment, and store a pointer to the first
           character to use. */
        blank = 1;
        com = 0;
        p = line;

        /* Skip blank lines. */
        if( line[ 0 ] ) {

            /* If the line starts with a comment character... */
            if( line[ 0 ] == '#' || line[ 0 ] == '!' ) {
                com = 1;

                /* Get a pointer to the first non-space/tab character after the comment
                   character. */
                p = line + 1;
                while( *p == ' ' || *p == '\t' ) p++;

                /* Note if it is blank. */
                if( *p ) blank = 0;

                /* If it is not a comment line, then the line is not blank. */
            } else {
                blank = 0;

                /* See if it is the end-of-table marker - a line containing just two or
                   more minus signs with no leading spaces. */
                eot = ( strspn( line, "-" ) > 1 );
            }
        }

        /* Skip blank lines, whether comment or not. */
        if( ! blank ) {

            /* First handle comment lines. */
            if( com ) {

                /* Does it look like a  parameter assignment... */
                words = astChrSplitRE( p, "^\\s*(\\w+)\\s*=\\s*(.*)$", &nword, NULL );
                if( words ) {

                    /* Add a parameter declaration to the Table. */
                    astAddParameter( result, words[ 0 ] );

                    /* Store the parameter value, using an appropriate data type. */
                    len = strlen( words[ 1 ] );
                    if( nc = 0, ( 1 == astSscanf( words[ 1 ], "%d%n", &ival, &nc ) )
                            && ( nc >= len ) ) {
                        astMapPut0I( result, words[ 0 ], ival, NULL );

                    } else if( nc = 0, ( 1 == astSscanf( words[ 1 ], "%lg%n", &dval, &nc ) )
                               && ( nc >= len ) ) {
                        astMapPut0D( result, words[ 0 ], dval, NULL );

                    } else {
                        astMapPut0C( result, words[ 0 ], words[ 1 ], NULL );

                    }

                    /* Free the words returned by astChrSplitRE. */
                    for( iword = 0; iword < nword; iword++ ) {
                        words[ iword ] = astFree( words[ iword ] );
                    }
                    words = astFree( words );

                    /* If it does not look like a parameter assignment... */
                } else {

                    /* Save a copy of it in case it turns out to be the last non-blank comment
                       line before the first row of data values (in which case it should
                       contain the column names). */
                    last_com = astStore( last_com, p, strlen( p ) + 1 );
                }

                /* If the line is not a comment see if it is an end of table marker. If so
                   indicate that we should leave the loop. */
            } else if( eot ) {
                more = 0;

                /* If the line is not a comment or an end of table marker ... */
            } else {

                /* Get the words from the row. */
                words = astChrSplit( p, &nword );

                /* If this is the first non-blank non-comment line, get the column names from
                   the previous non-blank comment line. */
                if( first ) {
                    if( last_com ) {
                        first = 0;
                        cols = astChrSplit( last_com, &ncol );

                        /* Create an array to hold the data type for each colum, and initialise
                           them to "integer". */
                        types = astMalloc( ncol*sizeof( int ) ) ;
                        for( iword = 0; iword < nword && astOK; iword++ ) {
                            if( iword < ncol ) {
                                types[ iword ] = AST__INTTYPE;

                                /* The columns are stored initially using interim names which have "T_"
                                   prepended to the names given in the file. */
                                tname = NULL;
                                nc = 0;
                                tname = astAppendString( tname, &nc, "T_" );
                                tname = astAppendString( tname, &nc, cols[ iword ] );
                                astFree( cols[ iword ] );
                                cols[ iword ] = tname;

                                /* Create the column definition within the returned Table. We store them
                                   initially as strings and then convert to the appropriate column data type
                                   later (once all rows have been read and the the data types are known). */
                                astAddColumn( result, cols[ iword ], AST__STRINGTYPE,
                                              0, NULL, " " );
                            }
                        }

                    } else if( *status == SAI__OK ) {
                        *status = SAI__ERROR;
                        msgSetc( "F", fname );
                        errRep( " ", "No column headers found in file ^F.", status );
                    }
                }

                /* Report an error if the line has the wrong number of values. */
                if( nword != ncol ) {
                    if( *status == SAI__OK ) {
                        *status = SAI__ERROR;
                        msgSeti( "N", nword );
                        msgSeti( "I", (*iline) );
                        msgSeti( "M", ncol );
                        msgSetc( "F", fname );
                        errRep( " ", "Wrong number of values (^N) at line ^I in "
                                "file ^F (should be ^M).", status );
                    }

                    /* Otherwise increment the number of rows read. */
                } else {
                    irow++;

                    /* Store each string value in the table, excluding "null" strings. Also check
                       the data type of each string an dupdate the column data types if necessary. */
                    for( iword = 0; iword < nword && *status == SAI__OK; iword++ ) {
                        if( strcmp( words[ iword ], "null" ) ) {
                            sprintf( key, "%s(%d)", cols[ iword ], irow );
                            astMapPut0C( result, key, words[ iword ], NULL );

                            /* If the column is currently thought to hold integers, check that the
                               current word looks like an integer. If not, down-grade the column type
                               to double. */
                            len = strlen( words[ iword ] );
                            if( types[ iword ] == AST__INTTYPE ) {
                                if( nc = 0, ( 1 != astSscanf( words[ iword ], "%d%n",
                                                              &ival, &nc ) ) ||
                                        ( nc < len ) ) {
                                    types[ iword ] = AST__DOUBLETYPE;
                                }
                            }

                            /* If the column is currently thought to hold doubles, check that the
                               current word looks like an doubler. If not, down-grade the column type
                               to string. */
                            if( types[ iword ] == AST__DOUBLETYPE ) {
                                if( nc = 0, ( 1 != astSscanf( words[ iword ], "%lg%n",
                                                              &dval, &nc ) ) ||
                                        ( nc < len ) ) {
                                    types[ iword ] = AST__STRINGTYPE;
                                }
                            }
                        }
                    }
                }

                /* Free the words returned by astChrSplit. */
                for( iword = 0; iword < nword; iword++ ) {
                    words[ iword ] = astFree( words[ iword ] );
                }
                words = astFree( words );

            }
        }
    }

    /* The entire file has now been read, and a Table created in which every
       column holds strings. We also have flags indicating whether the values
       in each column are all integers or doubles. Modify the type of the
       column within the Table to match these flags. */
    nrow = astGetI( result, "Nrow" );
    for( icol = 0; icol < ncol && *status == SAI__OK; icol++ ) {

        /* The column will be re-named from "T_<name>" to "<name>". */
        oldname = cols[ icol ];
        newname = oldname + 2;

        /* First convert string columns to integer columns if all the values in
           the column look like integers. */
        if( types[ icol ] == AST__INTTYPE ) {

            /* Create the new column */
            astAddColumn( result, newname, AST__INTTYPE, 0, NULL, " " );

            /* Copy each cell of the current column, converting from string to integer. */
            for( irow = 1; irow <= nrow; irow++ ) {
                sprintf( key, "%s(%d)", oldname, irow );
                if( astMapGet0I( result, key, &ival ) ) {
                    sprintf( key, "%s(%d)", newname, irow );
                    astMapPut0I( result, key, ival, NULL );
                }
            }

            /* Now do double columns in the same way. */
        } else if( types[ icol ] == AST__DOUBLETYPE ) {
            astAddColumn( result, newname, AST__DOUBLETYPE, 0, NULL, " " );
            for( irow = 1; irow <= nrow; irow++ ) {
                sprintf( key, "%s(%d)", oldname, irow );
                if( astMapGet0D( result, key, &dval ) ) {
                    sprintf( key, "%s(%d)", newname, irow );
                    astMapPut0D( result, key, dval, NULL );
                }
            }

            /* Copy string values without change. */
        } else {
            astAddColumn( result, newname, AST__STRINGTYPE, 0, NULL, " " );
            for( irow = 1; irow <= nrow; irow++ ) {
                sprintf( key, "%s(%d)", oldname, irow );
                if( astMapGet0C( result, key, &cval ) ) {
                    sprintf( key, "%s(%d)", newname, irow );
                    astMapPut0C( result, key, cval, NULL );
                }
            }
        }

        /* Remove the old column. */
        astRemoveColumn( result, oldname );

    }

    /* Free resources. */
    line = astFree( line );
    last_com = astFree( last_com );
    types = astFree( types );
    if( cols ) {
        for( icol = 0; icol < ncol; icol++ ) {
            cols[ icol ] = astFree( cols[ icol ] );
        }
        cols = astFree( cols );
    }

    /* If the table ended with an end-of-table marker, there may be another
       Table in the file. Call this function recursively to read it. */
    if( eot ) {
        subtable = ReadNextTable( fd, fname, iline, status );

        /* Store the subtable as a table parameter in the returned table. */
        if( subtable ) {
            astAddParameter( result, "SubTable" );
            astMapPut0A( result, "SubTable", subtable, NULL );

            /* The Table clones the pointer, so we must annull our local copy of it. */
            subtable = astAnnul( subtable );
        }
    }

    /* Return the Table pointer. */
    return result;
}
Пример #19
0
AstTable *atlReadTable( const char *fname, int *status ) {
    /*
    *+
    *  Name:
    *     atlReadTable

    *  Purpose:
    *     Create an AST Table from a text file.

    *  Language:
    *     C.

    *  Invocation:
    *     AstTable *atlReadTable( const char *fname, int *status )

    *  Description:
    *     This function creates an AST Table by reading the contents of a
    *     given text file. The text file format matches that of TOPCAT's
    *     "ASCII" format, except that any comment lines before the first row
    *     of column values that are of the form "# name = value" or
    *     "! name = value" are used to create Table parameters. Here "name"
    *     is a contiguous block of alphanumeric characters, and "value"
    *     represents all characters following the equals sign, up to the end
    *     of the line, excluding leading and trailing white space. If value
    *     is a scalar integer or double, it is stored as such in the Table.
    *     Otherwise, it is stored as a string.
    *
    *     In addition, any row that consists just of two or more minus signs,
    *     with no leading spaces, is taken to mark the end of the catalogue.
    *     Any subsequent lines in the file are assumed to form a whole new
    *     table that is read in exactly the same way as the first. This
    *     second Table is stored as a parameter of the first Table using the
    *     key "SubTable".

    *  Arguments:
    *     fname
    *        The file name.
    *     status
    *        Pointer to the global status variable.

    *  Returned Value:
    *     A pointer to the Table read from the file, or NULL if an error occurs.

    *  Notes:
    *     - All columns in the returned Table will hold scalar values.

    *  Copyright:
    *     Copyright (C) 2016 East Asian Observatory.
    *     Copyright (C) 2011 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
    *     {enter_new_authors_here}

    *  History:
    *     13-MAY-2011 (DSB):
    *        Original version.
    *     16-MAR-2016 (DSB):
    *        Added the SubTable facility.
    *     22-NOV-2016 (DSB):
    *        Report error if file has no column headers. Previously this
    *        caused a seg fault.
    *     {enter_further_changes_here}

    *  Bugs:
    *     {note_any_bugs_here}

    *+
    */

    /* Local Variables: */
    AstTable *result;
    FILE *fd;
    int iline;
    int *old_status;

    /* Initialise */
    result = NULL;

    /* Check the inherited status. */
    if( *status != SAI__OK ) return result;

    /* Make AST use the Fortran status variable. */
    old_status = astWatch( status );

    /* Open the file */
    fd = fopen( fname, "r" );

    /* Report an error if the file could not be opened. */
    if( !fd ) {
        *status = SAI__ERROR;
        msgSetc( "F", fname );
        errRep( "", "atlReadTable: Failed to open input text file: \"^F\".",
                status );

        /* Otherwise... */
    } else {

        /* Create the Table by reading text from the start of the file. */
        iline = 0;
        result = ReadNextTable( fd, fname, &iline, status );

        /* Close the output file. */
        fclose( fd );
    }

    /* Make AST use its original status variable. */
    astWatch( old_status );

    /* Return the Table pointer. */
    return result;
}
double cupidConfigD( AstKeyMap *config, const char *name, double def,
                     int *status ){
/*
*+
*  Name:
*     cupidConfigD

*  Purpose:
*     Get the value of a configuration parameter.

*  Language:
*     Starlink C

*  Synopsis:
*     double cupidConfigD( AstKeyMap *config, const char *name, double def,
*        int *status )

*  Description:
*     This function returns a named value from the supplied KeyMap. If
*     the KeyMap does not contain the named value, an attempt is made to
*     obtain a value from a secondary KeyMap which should be stored
*     within the supplied KeyMap, using a key equal to the constant
*     string CUPID__CONFIG. If the secondary KeyMap does not contain a
*     value, then the supplied default value is returned. In either case,
*     the returned value is stored in the KeyMap.

*  Parameters:
*     config
*        An AST KeyMap holding the configuration parameters. If NULL is
*        supplied, the default value is returned without error.
*     name
*        The name of the value to extract from the KeyMap.
*     def
*        The default value to use.
*     status
*        Pointer to the inherited status value.

*  Returned Value:
*     The required value. The supplied default value is returned if an
*     error occurs.

*  Copyright:
*     Copyright (C) 2005 Particle Physics & Astronomy Research Council.
*     Copyright (C) 2008 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
*     {enter_new_authors_here}

*  History:
*     5-OCT-2005 (DSB):
*        Original version.
*     26-MAR-2008 (DSB):
*        Re-report a more friendly message iof the supplied text could
*        not be interpreted as a numerical value.
*     {enter_further_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*-
*/

/* Local Variables: */
   AstObject *sconfig; /* Object pointer obtained from KeyMap */
   const char *text;   /* Pointer to uninterprted text value */
   double ret;         /* The returned value */

/* Initialise */
   ret = def;

/* Abort if an error has already occurred, or if no KeyMap was supplied. */
   if( *status != SAI__OK || !config ) return ret;

/* Attempt to extract the named value from the supplied KeyMap. */
   if( !astMapGet0D( config, name, &ret ) ) {

/* If the value was not found in the KeyMap, see if the KeyMap contains a
   secondary KeyMap. */
      if( astMapGet0A( config, CUPID__CONFIG, &sconfig ) ) {

/* If it does, see if the secondary KayMap contains a value for the named
   entry. If it does, remove the value from the KeyMap so it does not
   appear in the CUPID NDF extension. */
         if( astMapGet0D( (AstKeyMap *) sconfig, name, &ret ) ) {
            astMapRemove(  (AstKeyMap *) sconfig, name );

/* If the text supplied by the user could not be interpreted as a
   floating point value, re-report the error. */
         } else if( *status == AST__MPGER ) {
            ret = def;
            errAnnul( status );
            if( astMapGet0C( config, name, &text ) ) {
               *status = SAI__ERROR;
               msgSetc( "T", text );
               msgSetc( "N", name );
               errRep( "", "Illegal value \"^T\" supplied for configuration "
                       "parameter ^N.", status );
            }

/* If the value was not found in either KeyMap, return the default value. */
         } else {
            ret = def;
         }

/* Free the pointer to the secondary KeyMap. */
         sconfig = astAnnul( sconfig );

/* If no secondary KeyMap was found, return the default value. */
      } else {
         ret = def;
      }

/* Store the returned value in the supplied KeyMap if it is good. */
      if( ret != VAL__BADD ) astMapPut0D( config, name, ret, NULL );

/* If the text supplied by the user could not be interpreted as a
   floating point value, re-report the error. */
   } else if( *status == AST__MPGER ) {
      ret = def;
      errAnnul( status );
      if( astMapGet0C( config, name, &text ) ) {
         *status = SAI__ERROR;
         msgSetc( "T", text );
         msgSetc( "N", name );
         errRep( "", "Illegal value \"^T\" supplied for configuration "
                 "parameter ^N.", status );
      }
   }

/* Return the result. */
   return ret;
}
Пример #21
0
void smf_uncalc_iqu( ThrWorkForce *wf, smfData *data,
                     double *idata, double *qdata, double *udata,
                     int *status ){

/* Local Variables: */
   const JCMTState *state;    /* JCMTState info for current time slice */
   dim_t nbolo;               /* No. of bolometers */
   dim_t ntslice;             /* Number of time-slices in data */
   int bstep;                 /* Bolometer step between threads */
   int itime;                 /* Time slice index */
   int iworker;               /* Index of a worker thread */
   int ntime;                 /* Time slices to check */
   int nworker;               /* No. of worker threads */
   int old;                   /* Data has old-style POL_ANG values? */
   size_t bstride;            /* Stride between adjacent bolometer values */
   size_t tstride;            /* Stride between adjacent time slice values */
   smfHead *hdr;              /* Pointer to data header this time slice */
   smfUncalcIQUJobData *job_data = NULL; /* Pointer to all job data */
   smfUncalcIQUJobData *pdata = NULL;/* Pointer to next job data */
   char headval[ 81 ];        /* FITS header value */
   int ipolcrd;               /* Reference direction for waveplate angles */

/* Check the inherited status. */
   if( *status != SAI__OK ) return;

/* Convenience pointer. */
   hdr = data->hdr;

/* Check the half-waveplate and analyser were in the beam. */
   headval[ 0 ] = 0;
   smf_getfitss( hdr, "POLWAVIN", headval, sizeof(headval), status );
   if( strcmp( headval, "Y" ) && *status == SAI__OK ) {
      smf_smfFile_msg( data->file, "N", 0, "" );
      *status = SAI__ERROR;
      errRep( " ", "Half-waveplate was not in the beam for "
              "input NDF ^N.", status );
   }

   headval[ 0 ] = 0;
   smf_getfitss( hdr, "POLANLIN", headval, sizeof(headval), status );
   if( strcmp( headval, "Y" ) && *status == SAI__OK ) {
      smf_smfFile_msg( data->file, "N", 0, "" );
      *status = SAI__ERROR;
      errRep( " ", "Analyser was not in the beam for input "
              "NDF ^N.", status );
   }

/* Get the reference direction for JCMTSTATE:POL_ANG values. */
   smf_getfitss( hdr, "POL_CRD", headval, sizeof(headval), status );
   if( !strcmp( headval, "FPLANE" ) ) {
      ipolcrd = 0;
   } else if( !strcmp( headval, "AZEL" ) ) {
      ipolcrd = 1;
   } else if( !strcmp( headval, "TRACKING" ) ) {
      ipolcrd = 2;
   } else if( *status == SAI__OK ) {
      *status = SAI__ERROR;
      smf_smfFile_msg( data->file, "N", 0, "" );
      msgSetc( "V", headval );
      errRep( " ", "Input NDF ^N contains unknown value "
              "'^V' for FITS header 'POL_CRD'.", status );
   }

/* Obtain number of time slices - will also check for 3d-ness. Also get
   the dimensions of the bolometer array and the strides between adjacent
   bolometer values. */
   smf_get_dims( data, NULL, NULL, &nbolo, &ntslice, NULL, &bstride,
                 &tstride, status );

/* Create structures used to pass information to the worker threads. */
   nworker = wf ? wf->nworker : 1;
   job_data = astMalloc( nworker*sizeof( *job_data ) );

/* Check the above pointers can be used safely. */
   if( *status == SAI__OK ) {

/* Go through the first thousand POL_ANG values to see if they are in
   units of radians (new data) or arbitrary encoder units (old data).
   They are assumed to be in radians if no POL_ANG value is larger than
   20. */
      old = 0;
      state = hdr->allState;
      ntime = ( ntslice > 1000 ) ? 1000 : ntslice;
      for( itime = 0; itime < ntime; itime++,state++ ) {
         if( state->pol_ang > 20 ) {
            old = 1;
            msgOutif( MSG__VERB, "","   POL2 data contains POL_ANG values "
                      "in encoder units - converting to radians.", status );
            break;
         }
      }

/* Determine which bolometers are to be processed by which threads. */
      bstep = nbolo/nworker;
      if( bstep < 1 ) bstep = 1;

      for( iworker = 0; iworker < nworker; iworker++ ) {
         pdata = job_data + iworker;
         pdata->b1 = iworker*bstep;
         pdata->b2 = pdata->b1 + bstep - 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 calculate the analysed intensity values in each bolo, and then
   wait for them to complete. */
      for( iworker = 0; iworker < nworker; iworker++ ) {
         pdata = job_data + iworker;

         pdata->bstride = bstride;
         pdata->nbolo = nbolo;
         pdata->tstride = tstride;
         pdata->allstates = hdr->allState;
         pdata->ipi = idata;
         pdata->ipq = qdata;
         pdata->ipu = udata;
         pdata->ipolcrd = ipolcrd;
         pdata->old = old;
         pdata->ntslice = ntslice;

/* Pass the job to the workforce for execution. */
         thrAddJob( wf, THR__REPORT_JOB, pdata, smf1_uncalc_iqu_job, 0, NULL,
                      status );
      }

/* Wait for the workforce to complete all jobs. */
      thrWait( wf, status );
   }

/* Free resources. */
   job_data = astFree( job_data );
}
Пример #22
0
void gsdac_getMapVars ( const gsdVars *gsdVars, const char *samMode,
                        mapVars *mapVars, int *status )

{

    const char * cell_sys;

    /* Check inherited status */
    if ( *status != SAI__OK ) return;


    /* Translate Switch mode. */
    if ( strncmp ( gsdVars->swMode, "POSITION_SWITCH", 15 ) == 0 ) {

        if ( gsdVars->chopping ) {
            if ( gsdVars->referenceX == 0.0 && gsdVars->referenceY == 0.0 )
                strcpy ( mapVars->swMode, "freqsw" );
            else
                strcpy ( mapVars->swMode, "pssw" );
        } else {
            if ( gsdVars->referenceX == 0.0 && gsdVars->referenceY == 0.0 ) {
                strcpy ( mapVars->swMode, "freqsw" );

                /* Print a message, this was likely intended as a freq. sw. */
                msgOutif(MSG__VERB," ", "SWITCH_MODE was POSITION_SWITCH and CHOPPING was 0, this was likely intended to be a frequency switch", status);
            } else strcpy ( mapVars->swMode, "pssw" );
        }

    } else if ( strncmp ( gsdVars->swMode, "BEAMSWITCH", 10 ) == 0 ) {

        if ( gsdVars->chopping ) {
            strcpy ( mapVars->swMode, "chop" );
        } else {
            strcpy ( mapVars->swMode, "none" );
            msgOutif(MSG__VERB," ", "SWITCH_MODE was BEAMSWITCH and CHOPPING was 0, this may be an error...)", status);
        }

    } else if ( strncmp ( gsdVars->swMode, "CHOPPING", 8 ) == 0 ) {

        strcpy ( mapVars->swMode, "freqsw" );
        if ( gsdVars->chopping ) {
            msgOutif(MSG__VERB," ", "SWITCH_MODE was CHOPPING and CHOPPING was 1, this appears to be a misconfigured frequency switch", status);
        }

    } else if ( strncmp ( gsdVars->swMode, "NO_SWITCH", 7 ) == 0 ) {

        strcpy ( mapVars->swMode, "none" );
        if ( gsdVars->chopping ) {
            msgOutif(MSG__VERB," ", "SWITCH_MODE was NO_SWITCH and CHOPPING was 1, this may be an error...", status);
        }

    } else {
        *status = SAI__ERROR;
        msgSetc ( "SWITCHMODE", gsdVars->swMode );
        errRep ( "gsdac_getMapVars", "Couldn't identify switch mode ^SWITCHMODE", status );
        return;
    }

    /* Get the chopping parameters for grid beamswitches
       and samples. */

    if ( strcmp ( mapVars->swMode, "chop" ) == 0 ) {

        if ( strncmp ( gsdVars->chopCoords, "AZ", 2 ) == 0 )
            strcpy ( mapVars->chopCrd, "AZEL" );
        else if ( strncmp ( gsdVars->chopCoords, "EQ", 2 ) == 0 )
            strcpy ( mapVars->chopCrd, "HADEC" );
        else if ( strncmp ( gsdVars->chopCoords, "RB", 2 ) == 0 )
            strcpy ( mapVars->chopCrd, "B1950" );
        else if ( strncmp ( gsdVars->chopCoords, "RJ", 2 ) == 0 )
            strcpy ( mapVars->chopCrd, "J2000" );
        else if ( strncmp ( gsdVars->chopCoords, "RD", 2 ) == 0 )
            strcpy ( mapVars->chopCrd, "APP" );
        else if ( strncmp ( gsdVars->chopCoords, "GA", 2 ) == 0 )
            strcpy ( mapVars->chopCrd, "GAL" );
        else {
            strcpy ( mapVars->chopCrd, "" );
            msgOutif(MSG__VERB," ",
                     "Couldn't identify chop coordinates, continuing anyway", status);
        }

    }

    /* Get the local offset coordinate system. */
    cell_sys = gsdac_code2tcssys( gsdVars->cellCode, status );
    if (*status == SAI__OK && strlen(cell_sys) == 0) {
        msgOutif(MSG__VERB," ",
                 "Couldn't identify cell coordinates, continuing anyway", status);
    }
    one_strlcpy( mapVars->loclCrd, cell_sys,
                 sizeof(mapVars->loclCrd), status );

    /* Convert to ACSIS formatted string. */
    sprintf ( mapVars->skyRefX, "[OFFSET] %.0f [%s]",
              gsdVars->referenceX, mapVars->loclCrd );
    sprintf ( mapVars->skyRefY, "[OFFSET] %.0f [%s]",
              gsdVars->referenceY, mapVars->loclCrd );

    /* Get the scanning coordinates. */
    strcpy ( mapVars->scanCrd, mapVars->loclCrd );

    /* Get the map and scan parameters for rasters. */
    if ( strcmp ( samMode, "scan" ) == 0
            && strcmp ( mapVars->swMode, "pssw" ) == 0 ) {

        /* Get the map height and width. */
        mapVars->mapHght = gsdVars->nMapPtsX * gsdVars->cellX;
        mapVars->mapWdth = gsdVars->nMapPtsY * gsdVars->cellY;

        /* Get the scan velocity and spacing. */
        if ( strncmp ( gsdVars->obsDirection, "HORIZONTAL", 10 ) == 0 ) {
            mapVars->scanVel = gsdVars->cellX * gsdVars->nMapPtsX /
                               gsdVars->scanTime;
            mapVars->scanDy = gsdVars->cellY;
        } else if ( strncmp ( gsdVars->obsDirection, "VERTICAL", 8 ) == 0 ) {
            mapVars->scanVel = gsdVars->cellY * gsdVars->nMapPtsY /
                               gsdVars->scanTime;
            mapVars->scanDy = gsdVars->cellX;
        } else {
            *status = SAI__ERROR;
            errRep ( "gsdac_getMapVars", "Error getting scan velocity",
                     status );
            return;
        }

        if ( gsdVars->scanRev ) strcpy ( mapVars->scanPat, "BOUSTROPHEDON" );
        else strcpy ( mapVars->scanPat, "RASTER" );

    }

    mapVars->scanPA = gsdVars->cellV2X;
    mapVars->mapPA = mapVars->scanPA - 90.0;

}
Пример #23
0
void smurf_jsatileinfo( int *status ) {

/* Local Variables */
   AstCmpRegion *overlap;
   AstFitsChan *fc;
   AstFrameSet *fs;
   AstObject *obj;
   AstRegion *region;
   AstRegion *target;
   HDSLoc *cloc = NULL;
   HDSLoc *xloc = NULL;
   char *jcmt_tiles;
   char *tilendf = NULL;
   char text[ 200 ];
   double dec[ 8 ];
   double dist;
   double dlbnd[ 2 ];
   double dubnd[ 2 ];
   double gx[ 8 ];
   double gy[ 8 ];
   double maxdist;
   double norm_radec[2];
   double point1[ 2 ];
   double point2[ 2 ];
   double ra[ 8 ];
   double ra0;
   double dec0;
   int *ipntr;
   int axes[ 2 ];
   int create;
   int dirlen;
   int el;
   int exists;
   int flag;
   int i;
   int indf1;
   int indf2;
   int indf3;
   int itile;
   int iv;
   int jtile;
   int lbnd[ 2 ];
   int local_origin;
   int nc;
   int place;
   int tlbnd[ 2 ];
   int tubnd[ 2 ];
   int ubnd[ 2 ];
   smf_jsaproj_t proj;
   int xt;
   int yt;
   smfJSATiling skytiling;
   void *pntr;

/* Check inherited status */
   if( *status != SAI__OK ) return;

/* Start a new AST context. */
   astBegin;

/* Get the instrument to use abnd get the parameters describing the
   layout of its JSA tiles. */
   smf_jsainstrument( "INSTRUMENT", NULL, SMF__INST_NONE, &skytiling,
                      status );

/* Return the maximum tile index. */
   parPut0i( "MAXTILE", skytiling.ntiles - 1, status );

/* Abort if an error has occurred. */
   if( *status != SAI__OK ) goto L999;

/* Decide what sort of projection to use. */
   parChoic( "PROJ", "HPX", "HPX,HPX12,XPHN,XPHS", 1, text, sizeof(text),
             status );
   proj = smf_jsaproj_fromstr( text, 1, status );

/* If required, create an all-sky NDF in which each pixel covers the area
   of a single tile, and holds the integer tile index. The NDF has an
   initial size of 1x1 pixels, but is expanded later to the required size. */
   lbnd[ 0 ] = ubnd[ 0 ] = lbnd[ 1 ] = ubnd[ 1 ] = 1;
   ndfCreat( "ALLSKY", "_INTEGER", 2, lbnd, ubnd, &indf3, status );

/* If a null (!) value was supplied for parameter ALLSKY, annull the
   error and pass on. */
   if( *status == PAR__NULL ) {
      errAnnul( status );

/* Otherwise, create a FrameSet describing the whole sky in which each
   pixel corresponds to a single tile. */
   } else {
      smf_jsatile( -1, &skytiling, 0, proj, NULL, &fs, NULL, lbnd, ubnd,
                   status );

/* Change the bounds of the output NDF. */
      ndfSbnd( 2, lbnd, ubnd, indf3, status );

/* Store the FrameSet in the NDF. */
      ndfPtwcs( fs, indf3, status );

/* Map the data array. */
      ndfMap( indf3, "Data", "_INTEGER", "WRITE/BAD", (void **) &ipntr, &el,
              status );

/* Create all-sky map using XPH projection. */
      if( *status == SAI__OK ) {

/* Loop round every tile index. */
         for( jtile = 0; jtile < skytiling.ntiles; jtile++ ) {

/* Get the zero-based (x,y) indices of the tile within an HPX projection.
   This flips the bottom left half-facet up to the top right. */
            smf_jsatilei2xy( jtile, &skytiling, &xt, &yt, NULL, status );

/* Convert these HPX indices to the corresponding indices within the
   required projection. Note, the lower left facet is split by the above
   call to smf_jsatilei2xy tile (i.e. (xt,yt) indices are *not* in the
   "raw" mode). For instance, (0,0) is not a valid tile. */
            smf_jsatilexyconv( &skytiling, proj, xt, yt, 0, &xt, &yt, status );

/* Get the vector index of the corresponding element of the all-sky NDF. */
            if( proj == SMF__JSA_HPX || proj == SMF__JSA_HPX12 ) {
               iv = xt + 5*skytiling.ntpf*yt;
            } else {
               iv = xt + 4*skytiling.ntpf*yt;
            }

/* Report an error if this element has already been assigned a tile
   index. Otherwise, store the tile index. */
            if( ipntr[ iv ] == VAL__BADI ) {
               ipntr[ iv ] = jtile;
            } else if( *status == SAI__OK ) {
               *status = SAI__ERROR;
               errRepf( "", "%s projection assigns multiple tiles to "
                        "pixel (%d,%d).", status, text, xt, yt );
               break;
            }
         }
      }

/* Store NDF title. */
      sprintf( text, "JSA tile indices for %s data", skytiling.name );
      ndfCput( text, indf3, "TITLE", status );

/* Store the instrument as a component in the SMURF extension. */
      ndfXnew( indf3, "SMURF", "INSTRUMENT", 0, 0, &xloc, status );
      ndfXpt0c( skytiling.name, indf3, "SMURF", "INSTRUMENT", status );
      datAnnul( &xloc, status );

/* Close the NDF. */
      ndfAnnul( &indf3, status );
   }

/* Abort if an error has occurred. */
   if( *status != SAI__OK ) goto L999;

/* Get the zero-based index of the required tile. If a null value is
   supplied, annull the error and skip to the end. */
   parGdr0i( "ITILE", 0, 0, skytiling.ntiles - 1, 0, &itile, status );
   if( *status == PAR__NULL ) {
       errAnnul( status );
       goto L999;
   }

/* See if the pixel origin is to be at the centre of the tile. */
   parGet0l( "LOCAL", &local_origin, status );

/* Display the tile number. */
   msgBlank( status );
   msgSeti( "ITILE", itile );
   msgSeti( "MAXTILE", skytiling.ntiles - 1);
   msgOut( " ", "   Tile ^ITILE (from 0 to ^MAXTILE):", status );

/* Get the FITS header, FrameSet and Region defining the tile, and the tile
   bounds in pixel indices. */
   smf_jsatile( itile, &skytiling, local_origin,  proj, &fc, &fs, &region,
                lbnd, ubnd, status );

/* Write the FITS headers out to a file, annulling the error if the
   header is not required. */
   if( *status == SAI__OK ) {
      atlDumpFits( "HEADER", fc, status );
      if( *status == PAR__NULL ) errAnnul( status );
   }

/* If required, write the Region out to a text file. */
   if( *status == SAI__OK ) {
      atlCreat( "REGION", (AstObject *) region, status );
      if( *status == PAR__NULL ) errAnnul( status );
   }

/* Store the lower and upper pixel bounds of the tile. */
   parPut1i( "LBND", 2, lbnd, status );
   parPut1i( "UBND", 2, ubnd, status );

/* Display pixel bounds on the screen. */
   msgSeti( "XL", lbnd[ 0 ] );
   msgSeti( "XU", ubnd[ 0 ] );
   msgSeti( "YL", lbnd[ 1 ] );
   msgSeti( "YU", ubnd[ 1 ] );
   msgOut( " ", "      Pixel bounds: (^XL:^XU,^YL:^YU)", status );

/* Get the RA,Dec at the tile centre. */
   if( astTest( fs, "SkyRef" ) ) {
      ra0 = astGetD( fs, "SkyRef(1)" );
      dec0 = astGetD( fs, "SkyRef(2)" );

/* Format the central RA and Dec. and display. Call astNorm on the
   coordinates provided that the frame set has the correct number of
   axes (which it should as it comes from smf_jsatile). */
      norm_radec[0] = ra0;
      norm_radec[1] = dec0;
      if (astGetI(fs, "Naxes") == 2) astNorm(fs, norm_radec);
      msgSetc( "RACEN",  astFormat( fs, 1, norm_radec[ 0 ] ));
      msgSetc( "DECCEN",  astFormat( fs, 2, norm_radec[ 1 ] ));
      msgOut( " ", "      Centre (ICRS): RA=^RACEN DEC=^DECCEN", status );

/* Transform a collection of points on the edge of the region (corners and
   side mid-points) from GRID coords to RA,Dec. */
      point1[ 0 ] = 0.5;
      point1[ 1 ] = 0.5;
      point2[ 0 ] = ubnd[ 0 ] - lbnd[ 0 ] + 1;
      point2[ 1 ] = ubnd[ 1 ] - lbnd[ 1 ] + 1;

      gx[ 0 ] = point1[ 0 ];         /* Bottom left */
      gy[ 0 ] = point1[ 1 ];

      gx[ 1 ] = point1[ 0 ];         /* Centre left */
      gy[ 1 ] = gy[ 0 ];

      gx[ 2 ] = point1[ 0 ];         /* Top left */
      gy[ 2 ] = point2[ 1 ];

      gx[ 3 ] = gx[ 0 ];             /* Top centre */
      gy[ 3 ] = point2[ 1 ];

      gx[ 4 ] = point2[ 0 ];         /* Top right */
      gy[ 4 ] = point2[ 1 ];

      gx[ 5 ] = point2[ 0 ];         /* Centre right */
      gy[ 5 ] = gy[ 0 ];

      gx[ 6 ] = point2[ 0 ];         /* Bottom right */
      gy[ 6 ] = point1[ 1 ];

      gx[ 7 ] = gx[ 0 ];             /* Bottom centre */
      gy[ 7 ] = point1[ 1 ];

      astTran2( fs, 8, gx, gy, 1, ra, dec );

/* Find the arc-distance from the centre to the furthest point from the
   centre. */
      point1[ 0 ] = ra0;
      point1[ 1 ] = dec0;
      maxdist = -1.0;

      for( i = 1; i < 8; i++ ) {
         if( ra[ i ] != AST__BAD && dec[ i ] != AST__BAD ) {
            point2[ 0 ] = ra[ i ];
            point2[ 1 ] = dec[ i ];
            dist = astDistance( fs, point1, point2 );
            if( dist > maxdist ) maxdist = dist;
         }
      }

/* Convert from radius to diameter. */
      maxdist *= 2.0;

/* Format this size as a dec value (i.e. arc-distance) and display it. */
      if( maxdist > 0.0 ) {
         msgSetc( "SIZE",  astFormat( fs, 2, maxdist ) );
         msgOut( " ", "      Size: ^SIZE", status );
      } else {
         maxdist = AST__BAD;
         msgOut( " ", "      Size: <unknown>", status );
      }

/* If a discontinuity passes through the tile, the centre and size may be
   unknown. */
   } else {
      ra0 = AST__BAD;
      dec0 = AST__BAD;
      maxdist = AST__BAD;
      msgOut( " ", "      Centre (ICRS): RA=<unknown> DEC=<unknown>", status );
      msgOut( " ", "      Size: <unknown>", status );
   }

/* Write the tile centre ra and dec in radians to the output parameters. */
   parPut0d( "RACEN", norm_radec[ 0 ], status );
   parPut0d( "DECCEN", norm_radec[ 1 ], status );

/* Write the size to the output parameter as radians. */
   parPut0d( "SIZE", maxdist, status );

/* Get the translation of the environment variable JSA_TILE_DIR. */
   jcmt_tiles = getenv( "JSA_TILE_DIR" );

/* Initialise the path to the tile's NDF to hold the root directory.
   Use the current working directory if JSA_TILE_DIR is undefined. */
   if( jcmt_tiles ) {
      nc = 0;
      tilendf = astAppendString( tilendf, &nc, jcmt_tiles );

   } else {

      nc = 512;
      jcmt_tiles = astMalloc( nc );

      while( !getcwd( jcmt_tiles, nc ) ) {
         nc *= 2;
         jcmt_tiles = astRealloc( jcmt_tiles, nc );
      }

      nc = 0;
      tilendf = astAppendString( tilendf, &nc, jcmt_tiles );
      jcmt_tiles = astFree( jcmt_tiles );
   }

/* Complete the path to the tile's NDF. */
   tilendf = astAppendString( tilendf, &nc, "/" );
   tilendf = astAppendString( tilendf, &nc, skytiling.subdir );
   dirlen = nc;
   sprintf( text, "/tile_%d.sdf", itile );
   tilendf = astAppendString( tilendf, &nc, text );

/* Write it to the output parameter. */
   parPut0c( "TILENDF", tilendf, status );

/* See if the NDF exists, and store the flag in the output parameter. */
   exists = access( tilendf, F_OK ) ? 0 : 1;
   parPut0l( "EXISTS", exists, status );

/* If the NDF does not exist, create it if required. */
   parGet0l( "CREATE", &create, status );
   if( !exists && create && *status == SAI__OK ) {

/* Write the NDF info to the screen. */
      msgSetc( "NDF",  tilendf );
      msgOutif( MSG__NORM, " ", "      NDF: ^NDF (created)", status );

/* Temporarily terminate the NDF path at the end of the subdirectory. */
      tilendf[ dirlen ] = 0;

/* Create the required directory (does nothing if the directory
   already exists).  It is given read/write/search permissions for owner
   and group, and read/search permissions for others. */
      (void) mkdir( tilendf, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH );

/* Replace the character temporarily overwritten above. */
      tilendf[ dirlen ] = '/';

/* Now create the tile's NDF. */
      ndfPlace( NULL, tilendf, &place, status );
      ndfNew( skytiling.type, 2, lbnd, ubnd, &place, &indf1, status );

/* Fill its data array with zeros. */
      ndfMap( indf1, "Data", skytiling.type, "WRITE/ZERO", &pntr, &el,
              status );

/* Store the WCS FrameSet. */
      ndfPtwcs( fs, indf1, status );

/* If the instrument jsatiles.have variance, fill the variance array with zeros. */
      if( skytiling.var ) {
         ndfMap( indf1, "Variance", skytiling.type, "WRITE/ZERO", &pntr,
                 &el, status );
      }

/* Create a SMURF extension. */
      ndfXnew( indf1, SMURF__EXTNAME, SMURF__EXTTYPE, 0, NULL, &xloc, status );

/* Store the tile number and instrument name in the extension. */
      datNew0I( xloc, "TILE", status );
      datFind( xloc, "TILE", &cloc, status );
      datPut0I( cloc, itile, status );
      datAnnul( &cloc, status );

      datNew0C( xloc, "INSTRUMENT", strlen( skytiling.name ), status );
      datFind( xloc, "INSTRUMENT", &cloc, status );
      datPut0C( cloc, skytiling.name, status );
      datAnnul( &cloc, status );

/* Create a weights NDF within the SMURF extension, and fill its data
   array with zeros. */
      ndfPlace( xloc, "WEIGHTS", &place, status );
      ndfNew( skytiling.type, 2, lbnd, ubnd, &place, &indf2, status );
      ndfMap( indf2, "Data", skytiling.type, "WRITE/ZERO", &pntr, &el,
              status );
      ndfPtwcs( fs, indf2, status );
      ndfAnnul( &indf2, status );

/* Annul the extension locator and the main NDF identifier. */
      datAnnul( &xloc, status );
      ndfAnnul( &indf1, status );

/* Write the NDF info to the screen. */
   } else {
      msgSetc( "NDF",  tilendf );
      msgSetc( "E",  exists ? "exists" : "does not exist" );
      msgOut( " ", "      NDF: ^NDF (^E)", status );
   }

/* Initialise TBND and TLBND to indicate no overlap. */
   tlbnd[ 0 ] = 1;
   tlbnd[ 1 ] = 1;
   tubnd[ 0 ] = 0;
   tubnd[ 1 ] = 0;

/* Attempt to to get an AST Region (assumed to be in some 2D sky coordinate
   system) using parameter "TARGET". */
   if( *status == SAI__OK ) {
      kpg1Gtobj( "TARGET", "Region",
                 (void (*)( void )) F77_EXTERNAL_NAME(ast_isaregion),
                 &obj, status );

/* Annul the error if none was obtained. */
      if( *status == PAR__NULL ) {
         errAnnul( status );

/* Otherwise, use the supplied object. */
      } else {
         target = (AstRegion *) obj;

/* If the target Region is 3-dimensional, remove the third axis, which
   is assumed to be a spectral axis. */
         if( astGetI( target, "Naxes" ) == 3 ) {
            axes[ 0 ] = 1;
            axes[ 1 ] = 2;
            target = astPickAxes( target, 2, axes, NULL );
         }

/* See if there is any overlap between the target and the tile. */
         overlap = NULL;
         flag = astOverlap( region, target );

         if( flag == 0 ) {
            msgOut( "", "      Cannot convert between the coordinate system of the "
                    "supplied target and the tile.", status );

         } else if( flag == 1 || flag == 6 ) {
            msgOut( "", "      There is no overlap between the target and the tile.",
                    status );

         } else if( flag == 2 ) {
            msgOut( "", "      The tile is contained within the target.",
                    status );
            tlbnd[ 0 ] = lbnd[ 0 ];
            tlbnd[ 1 ] = lbnd[ 1 ];
            tubnd[ 0 ] = ubnd[ 0 ];
            tubnd[ 1 ] = ubnd[ 1 ];

         } else if( flag == 3 ) {
            overlap = astCmpRegion( region, target, AST__AND, " " );

         } else if( flag == 4 ) {
            overlap = astCmpRegion( region, target, AST__AND, " " );

         } else if( flag == 5 ) {
            msgOut( "", "      The target and tile are identical.",
                    status );
            tlbnd[ 0 ] = lbnd[ 0 ];
            tlbnd[ 1 ] = lbnd[ 1 ];
            tubnd[ 0 ] = ubnd[ 0 ];
            tubnd[ 1 ] = ubnd[ 1 ];

         } else if( *status == SAI__OK ) {
            *status = SAI__OK;
            errRepf( "", "Unexpected value %d returned by astOverlap "
                     "(programming error).", status, flag );
         }

/* If a region containing the intersection of the tile and target was
   created above, map it into the grid coordinate system of the tile. */
         if( overlap ) {
            overlap = astMapRegion( overlap, astGetMapping( fs, AST__CURRENT,
                                                            AST__BASE ),
                                    astGetFrame( fs, AST__BASE ) );

/* Get its GRID bounds. */
            astGetRegionBounds( overlap, dlbnd, dubnd );

/* Convert to integer. */
            tlbnd[ 0 ] = ceil( dlbnd[ 0 ] - 0.5 );
            tlbnd[ 1 ] = ceil( dlbnd[ 1 ] - 0.5 );
            tubnd[ 0 ] = ceil( dubnd[ 0 ] - 0.5 );
            tubnd[ 1 ] = ceil( dubnd[ 1 ] - 0.5 );

/* Convert to PIXEL indices within the tile. */
            tlbnd[ 0 ] += lbnd[ 0 ] - 1;
            tlbnd[ 1 ] += lbnd[ 1 ] - 1;
            tubnd[ 0 ] += lbnd[ 0 ] - 1;
            tubnd[ 1 ] += lbnd[ 1 ] - 1;

            msgOutf( "", "      The target overlaps section (%d:%d,%d:%d).",
                     status, tlbnd[ 0 ], tubnd[ 0 ], tlbnd[ 1 ], tubnd[ 1 ] );
         }
      }
   }

/* Store the pixel index bounds of the tiles overlap with the target. */
   parPut1i( "TLBND", 2, tlbnd, status );
   parPut1i( "TUBND", 2, tubnd, status );

/* Arrive here if an error occurs. */
   L999:;

/* Free resources. */
   tilendf = astFree( tilendf );

/* End the AST context. */
   astEnd;

/* Issue a status indication.*/
   msgBlank( status );
   if( *status == SAI__OK ) {
      msgOutif( MSG__VERB, "", "JSATILEINFO succeeded.", status);
   } else {
      msgOutif( MSG__VERB, "", "JSATILEINFO failed.", status);
   }
}
Пример #24
0
   void ccdTclStop( ccdTcl_Interp *cinterp, int *status ) {
/*
*+
*  Name:
*     ccdTclStop

*  Purpose:
*     Delete a Tcl interpreter.

*  Language:
*     Starlink C

*  Description:
*     This routine should be called to shut down a Tcl interpreter which
*     was started by ccdTclStart.  It ought not to be shut down in any
*     other way.  This routine will attempt to execute even if the
*     status is set.

*  Arguments:
*     cinterp = ccdTcl_Interp *
*        The interpreter got from a previous ccdTclStart call.
*     status = int *
*        The global status.

*  Copyright:
*     Copyright (C) 2006 Particle Physics & Astronomy Research 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., 59 Temple Place,Suite 330, Boston, MA
*     02111-1307, USA

*  Authors:
*     {original_author_entry}

*  History:
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*-
*/

/* Local variables. */
      int ifd = cinterp->upfd[ 0 ];
      int ofd = cinterp->downfd[ 1 ];
      void (*handler)(int);

/* Write an 'exit' command to the Tcl interpreter.  This should cause it
   to shut down in an orderly fashion and, in particular, it will allow
   the Adam Message System to tidy up in whatever arcane way it sees fit.
   We ignore SIGPIPE but check for an I/O error, so that the program
   copes gracefully in the case that the pipe is broken. */
      handler = signal( SIGPIPE, SIG_IGN );
      if ( write( ofd, "exit", strlen( "exit" ) + 1 ) < 0 ) {
         if ( *status == SAI__OK ) {
            *status = SAI__ERROR;
         }
         msgSetc( "ERROR", strerror( errno ) );
         errRep( "CCD_TCL_PIPE", "^ERROR", status );
      }

/* Close the pipe communication file descriptors. */
      close( ofd );
      close( ifd );

/* Restore SIGPIPE handling. */
      signal( SIGPIPE, handler );

/* Finally free the memory associated with the interpreter structure itself. */
      free( cinterp );
   }
Пример #25
0
void smf_pread( Grp *igrp, const char *param, int *status ){

/* Local Variables: */
   AstMapping *dlatmap;
   AstMapping *dlonmap;
   AstMapping *taimap;
   AstTable *table;
   char file[ GRP__SZNAM + 1 ];
   char pbuf[ GRP__SZNAM + 1 ];
   const char *system;
   void *p;

/* Before we check the error status, see if we are annulling previously
   created Mappings. If so, get each formatted pointer from the group
   metadata, get an Object pointer form it, lock it for use by the
   current thread, and then annul it. Remove the metadata item from the
   group. */
   if( !param ) {

      pbuf[ 0 ] = 0;
      smf_get_grp_metadata( igrp, "DLONMAP", pbuf, status );
      if( pbuf[ 0 ] ) {
         sscanf( pbuf, "%p", &p );
         dlonmap = (AstMapping *) p;
         astLock( dlonmap, 0 );
         dlonmap = astAnnul( dlonmap );
         smf_remove_grp_metadata( igrp, "DLONMAP", status );
      }

      pbuf[ 0 ] = 0;
      smf_get_grp_metadata( igrp, "DLATMAP", pbuf, status );
      if( pbuf[ 0 ] ) {
         sscanf( pbuf, "%p", &p );
         dlatmap = (AstMapping *) p;
         astLock( dlatmap, 0 );
         dlatmap = astAnnul( dlatmap );
         smf_remove_grp_metadata( igrp, "DLATMAP", status );
      }

      return;
   }

/* Check the inherited status. */
   if( *status != SAI__OK ) return;

/* Use the specified parameter to get the name of the text file containing
   the table of pointing corrections. */
   parGet0c( param, file, sizeof( file ) - 1, status );

/* If no file was specified, annul the error. */
   if( *status == PAR__NULL ) {
      errAnnul( status );

/* If a file was obtained sccuesfully, read it. */
   } else if( *status == SAI__OK ) {

/* Start an AST context. */
      astBegin;

/* Attempt to read an AST Table from the text file. */
      table = atlReadTable( file, status );

/* Create a LutMap from each of the three columns. */
      taimap = (AstMapping *) atlTablelutMap( table, "TAI", status );
      dlonmap = (AstMapping *) atlTablelutMap( table, "DLON", status );
      dlatmap = (AstMapping *) atlTablelutMap( table, "DLAT", status );

/* Create Mappings that transforms TAI into a DLON and DLAT. These use
   linear interpolation for non-tabulated TAI values. */
      astInvert( taimap );
      dlonmap = (AstMapping *) astCmpMap( taimap, dlonmap, 1, " " );
      dlatmap = (AstMapping *) astCmpMap( taimap, dlatmap, 1, " " );

/* Format the pointers to these two Mappings and store them in the
   supplied group using names "DLONMAP" and "DLATMAP". */
      sprintf( pbuf, "%p", (void *) dlonmap );
      smf_add_grp_metadata( igrp, "DLONMAP", pbuf, status );

      sprintf( pbuf, "%p", (void *) dlatmap );
      smf_add_grp_metadata( igrp, "DLATMAP", pbuf, status );

/* See what system the DLON/DLAT values refer to (default to AZEL). Store
   it in the group.  */
      if( !astMapGet0C( table, "SYSTEM", &system ) ) system = "AZEL";
      smf_add_grp_metadata( igrp, "PSYSTEM", system, status );

/* Unlock the pointers to the Mappings so that they can be used by a
   different thread. This also exempts the pointers from AST context
   handling (until they are re-locked) so the following call to astEnd
   will not annull them. */
      astUnlock( dlonmap, 1 );
      astUnlock( dlatmap, 1 );

/* End the AST context. This annuls all Objects created during the
   context, except for the unlocked Mappings. */
      astEnd;

/* Debug message. */
      msgSetc( "F", file );
      msgSetc( "S", system );
      msgOutif( MSG__DEBUG, " ", "^S pointing corrections read from file ^F",
                status );

/* Issue a context message if anything went wrong. */
      if( *status != SAI__OK ) {
         msgSetc( "F", file );
         errRep( " ", "Failed to read pointing corrections from text file ^F.",
                 status );
      }
   }
}
Пример #26
0
void cupid_mon( int *status ) {
/*
*+
*  Name:
*     cupid_mon

*  Purpose:
*     Top-level CUPID function for A-task monolith on UNIX.

*  Language:
*     Starlink C

*  Type of Module:
*     ADAM A-task

*  Description:
*     This is the top-level A-task monolith function for the CUPID
*     suite of A-tasks.  Each CUPID command is an alias to a softlink
*     that points to this monolith.  The chosen command is obtained
*     from the ADAM routine TASK_GET_NAME.  The command may be specified
*     from the shell or ICL.  Given the command, the requested A-task
*     is called after a successful matching of the input string with a
*     valid task name.  If there is no match, an error report is made.

*  Parameters:
*     status
*        Pointer to the global status variable used by the ADAM fixed part.

*  Synopsis:
*     void cupid_mon( int *status );

*  Copyright:
*     Copyright (C) 2009 Science & Technology Facilities Council.
*     Copyright (C) 2005 Particle Physics & Astronomy Research 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 (STARLINK)
*     TIMJ: Tim Jenness (JAC, Hawaii)
*     {enter_new_authors_here}

*  History:
*     28-SEP-2005 (DSB):
*        Original version.
*     29-JUL-2009 (TIMJ):
*        Call taskGetName rather than Fortran.
*        Add CUPID and version number to NDF history.
*     31-JUL-2009 (DSB):
*        Use ndgBegpv/Endpv to provide automatic provenance propagation.
*     16-OCT-2009 (DSB):
*        Use ndgBeggh/ndgEndgh to record contents of group parameters in
*        the history component of output NDFs.
*     2011-01-19 (TIMJ):
*        Add leak checking to CUPID monolith
*     {enter_further_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*-
*/

/* Local variables: */
   char appname[NDF__SZAPP+1];    /* Application name for NDF History */
   char buff[PAR__SZNAM+7];       /* Application name for provenance handling */
   char filter[PAR__SZNAM+PAR__SZNAM+1];
   char name[PAR__SZNAM+1];       /* C character variable to hold name */
   int ast_caching;               /* Initial value of AST MemoryCaching tuning parameter */
   int emslev1;                   /* EMS level on entry */
   int emslev2;                   /* EMS level on exit */
   int ngrp0;                     /* Number of grp ids at start */
   int ngrp1;                     /* Number of grp ids at end */
   int nloc0;                     /* Number of active HDS Locators at start */
   int nloc1;                     /* Number of active HDS Locators at end */

/* Check the inherited status. */
   if( *status != SAI__OK ) return;

/* For debugging, watch one of the leaked GRP identifiers listed by the
   call to grpWatch at the end of this routine (if any). */
   /* grpWatch( 3129345, status ); */

/* Read the input error message stack level */
   emsLevel( &emslev1 );

/* Obtain the command from the environment.  This returns uppercase names. */
   taskGetName( name, sizeof(name), status );

/* Update the application name in the NDF history recording
   to include the version number of the application */
   snprintf( appname, NDF__SZAPP, "%-*s (%s V%s)", PAR__SZNAM,
             name, PACKAGE_UPCASE, PACKAGE_VERSION);
   ndfHappn( appname, status );

/* Make AST use the same variable for its inherited status. */
   astWatch( status );

/* Tell AST to re-cycle memory when possible. */
   ast_caching = astTune( "MemoryCaching", 1 );

/* Get the GRP and HDS status for leak checking - need the task name
   to mask out parameter names. Also need to mask out the monlith name */
   one_strlcpy( filter, "!CUPID_MON,!", sizeof(filter), status);
   one_strlcat( filter, name, sizeof(filter), status );
   grpInfoi( NULL, 0, "NGRP", &ngrp0, status );
   hdsInfoI( NULL, "LOCATORS", filter, &nloc0, status );

/* Begin a provenance block. This causes event handlers to be registered
   with the NDF library so that a handler routine in NDG is called every
   time an NDF is opened. This handler routine keeps a record of all
   NDFs that are opened for input or output, until the block is closed
   by calling ndgEndpv. */
   ndgBegpv( status );

/* Begin a GRP NDF history block. This causes the contents of GRP groups
   to be appended to default history text added to any NDFs during the
   block. */
   ndgBeggh( status );

/* Check the string against valid A-task names---if matched then call
   the relevant A-task. */

/* Finds a low frequency background surface. */
   if( !strcmp( name, "FINDBACK" ) ) {
      findback( status );

/* Identifies emission clumps within a 2- or 3D NDF. */
   } else if( !strcmp( name, "FINDCLUMPS" ) ) {
      findclumps( status );

/* Give help on CUPID commands. */
   } else if( !strcmp( name, "CUPIDHELP" ) ) {
      cupidhelp( status );

/* Create simulated data containing clumps and noise. */
   } else if( !strcmp( name, "MAKECLUMPS" ) ) {
      makeclumps( status );

/* Extract clump parameters from another image */
   } else if( !strcmp( name, "EXTRACTCLUMPS" ) ) {
      extractclumps( status );

/* Obtain information about one or more clumps. */
   } else if( !strcmp( name, "CLUMPINFO" ) ) {
      clumpinfo( status );

/* Report an error if the command name is not recognised. */
   } else if( *status == SAI__OK ) {
      *status = SAI__ERROR;
      errRep( "CUPID_MON_NOCOM", "CUPID: No such command ^CMD.", status );
   }

/* End the GRP NDF history block. */
   ndgEndgh( status );

/* End the provenance block. This will result in every output NDF being
   given a provenance extension containing a record of the input NDFs
   that the application accessed in order to create the output NDF. Any
   output NDF that already contains a provenance extension is left
   unchanged (so individual application can override this automatic
   provenance handling by adding a provenance extension to the output
   NDF itself). */
   sprintf( buff, "CUPID:%s", name );
   ndgEndpv( buff, status );

/* Re-instate the original value of the AST ObjectCaching tuning
   parameter. */
   astTune( "MemoryCaching", ast_caching );

/* Check for GRP leaks Do this in a new error reporting context so
   that we get the correct value even if an error has occurred. */
   errBegin( status );
   grpInfoi( NULL, 0, "NGRP", &ngrp1, status );

/* If there are more active groups now than there were on entry,
   there must be a problem (GRP identifiers are not being freed
   somewhere). So report it. */
   if (*status == SAI__OK && ngrp1 > ngrp0) {
     msgBlank( status );
     msgSetc( "NAME", name );
     msgSeti( "NGRP0", ngrp0 );
     msgSeti( "NGRP1", ngrp1 );
     msgOut( " ", "WARNING: The number of active "
             "GRP identifiers increased from ^NGRP0 to ^NGRP1 "
             "during execution of ^NAME (" PACKAGE_UPCASE " programming "
             " error).", status);
     msgBlank(status);
     grpWatch( 0, status );
   }
   errEnd( status );

/* Check for HDS leaks Do this in a new error reporting context so
   that we get the correct value even if an error has occurred. */
   errBegin( status );
   hdsInfoI( NULL, "LOCATORS", filter, &nloc1, status );

/* If there are more active locators now than there were on entry,
   there must be a problem (HDS locators are not being freed
   somewhere). So report it. */
   if (*status == SAI__OK && nloc1 > nloc0) {
     msgBlank( status );
     msgSetc( "NAME", name );
     msgSeti( "NLOC0", nloc0 );
     msgSeti( "NLOC1", nloc1 );
     msgOut( " ", "WARNING: The number of active "
             "HDS Locators increased from ^NLOC0 to ^NLOC1 "
             "during execution of ^NAME (" PACKAGE_UPCASE " programming "
             " error).", status);
     msgBlank(status);
     hdsShow("LOCATORS", status);
     hdsShow("FILES", status);
   }
   errEnd( status );

/* Read the exitt error message stack level */
   emsLevel( &emslev2 );

   if (*status == SAI__OK && emslev1 != emslev2 ) {
     errMark();
     msgBlank( status );
     msgSetc( "NAME", name );
     msgSeti( "LV1", emslev1);
     msgSeti( "LV2", emslev2);
     msgOut( " ", "WARNING: EMS Stack level went from ^LV1 to ^LV2"
             " during execution of ^NAME (" PACKAGE_UPCASE " programming"
             " error).", status );
     msgBlank(status);
     errRlse();
   }

/* Make AST use its own internal variable for its inherited status. */
   astWatch( NULL );

/* Clear out any remaining memory allocated by AST and report
   unintentional leaks. */
   astFlushMemory( 1 );

}
Пример #27
0
   ccdTcl_Interp *ccdTclStart( int *status ) {
/*
*+
*  Name:
*     ccdTclStart

*  Purpose:
*     Start up a Tcl interpreter.

*  Language:
*     Starlink C

*  Description:
*     This function returns a pointer to a ccdTcl_Interp structure, which
*     is the value which should be passed as the 'interp' argument to
*     most of the ccdTcl_* routines.  As currently implemented this is
*     NOT a Tcl_Interp structure (though a possible implementation of
*     the ccdTcl_* routines could use this), so don't use it as one.
*
*     Commands can be executed within the Tcl interpreter thus constructed
*     by calling ccdTclDo or one of the other similar functions.  The
*     correct way to free the resources associated with this pointer
*     is using a call to the ccdTclStop routine.

*  Arguments:
*     status = int *
*        The global status.

*  Return Value:
*     On successful execution, a pointer to a ccdTcl_Interp structure,
*     to be used for subsequent calls to related routines, is returned.
*     If there is an error then the status argument is set, and NULL
*     is returned.

*  Copyright:
*     Copyright (C) 2006 Particle Physics & Astronomy Research 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., 59 Temple Place,Suite 330, Boston, MA
*     02111-1307, USA

*  Authors:
*     {original_author_entry}

*  History:
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*-
*/

/* Local variables. */
      ccdTcl_Interp *cinterp;
      pid_t pid;

/* Check inherited status. */
      if ( *status != SAI__OK ) return NULL;

/* Get storage for the interpreter structure. */
      cinterp = malloc( sizeof( ccdTcl_Interp ) );
      if ( cinterp == NULL ) return NULL;

/* Create two pipes, one for shoving commands down, and one for pulling
   result strings up. */
      if ( pipe( cinterp->downfd ) || pipe( cinterp->upfd ) ) {
         *status = SAI__ERROR;
         errSyser( "ERROR", errno );
         errRep( "CCD_TCL_PROC", "pipe: ^ERROR", status );
         free( cinterp );
         return NULL;
      }

/* Child process, in which the Tcl interpreter will run. */
/* ----------------------------------------------------- */
      if ( ! ( pid = fork() ) ) {
         char *av[ 5 ];
         char *ccddir;
         char sifd[ 12 ];
         char sofd[ 12 ];

/* Close unwanted ends of the pipes. */
         close( cinterp->downfd[ 1 ] );
         close( cinterp->upfd[ 0 ] );

/* Ensure that the remaining file descriptors will stay open over an exec
   call. */
         fcntl( cinterp->downfd[ 0 ], F_SETFD, (long) 0 );
         fcntl( cinterp->upfd[ 1 ], F_SETFD, (long) 0 );

/* Overlay the Tcl interpreter on this process.  If the CCDPACK_DIR
   environment variable is defined then use the ccdwish binary there, else
   try to find one on the path. */
         av[ 1 ] = "-pipes";
         av[ 2 ] = sifd;
         av[ 3 ] = sofd;
         av[ 4 ] = NULL;
         sprintf( sifd, "%d", cinterp->downfd[ 0 ] );
         sprintf( sofd, "%d", cinterp->upfd[ 1 ] );
         ccddir = getenv( "CCDPACK_DIR" );
         if ( ccddir != NULL ) {
            av[ 0 ] = buffer;
            strcpy( buffer, ccddir );
            strcat( buffer, "/ccdwish" );
            execv( buffer, av );
         }
         else {
            av[ 0 ] = "ccdwish";
            execvp( "ccdwish", av );
         }

/* Execution will only continue here if ccdwish could not be executed. */
         *status = SAI__ERROR;
         errRep( "TCL_NOWISH", "Failed to execute ccdwish", status );
         return NULL;
      }

/* Parent process. */
/* --------------- */

/* Check that the fork worked. */
      if ( pid < 0 ) {
         *status = SAI__ERROR;
         msgSetc( "ERROR", strerror( errno ) );
         errRep( "CCD_TCL_PROC", "fork: ^ERROR", status );
         free( cinterp );
         return NULL;
      }

/* Close unwanted ends of pipes. */
      close( cinterp->downfd[ 0 ] );
      close( cinterp->upfd[ 1 ] );

/* Execute the CCDFixConvert procedure.  This prevents confusion between
   the temporary HDS container files created for foreign data files by
   the calling process and those created by the ccdwish child process. */
      ccdTclDo( cinterp, "CCDFixConvert tcl-", status );

/* Return the created interpreter structure. */
      return cinterp;
   }
Пример #28
0
void smurf_mon( int * status ) {

  /* Local variables */
  char taskname[PAR__SZNAM+1];
  char appname[NDF__SZAPP+1];
  char filter[PAR__SZNAM+PAR__SZNAM+1];
  int ngrp0;                   /* Number of grp ids at start */
  int ngrp1;                   /* Number of grp ids at end */
  int nloc0;                   /* Number of active HDS Locators at start */
  int nloc1;                   /* Number of active HDS Locators at end */
  int memory_caching;          /* Is AST current caching unused memory? */
  int emslev1;                 /* EMS level on entry */
  int emslev2;                 /* EMS level on exit */

  if ( *status != SAI__OK ) return;

  /* Read the input error message stack level */
  emsLevel( &emslev1 );

  /* Initialise AST */
  astBegin;
  memory_caching = astTune( "MemoryCaching", 1 );

  /* Register our status variable with AST */
  astWatch( status );

  /* If we are watching a particular memory Id reported by astActiveMemory
     we set the watch point here. */
  /* astWatchMemory( 29 ); */

  /* For debugging, watch one of the leaked GRP identifiers listed by the
     call to grpWatch at the end of this routine (if any). */
  /* grpWatch( 3129345, status ); */

  /* Mark any currently active NDF parameters, so that they will
     not be cancelled by the call to ndfCancl at the end of this
     function. */
  ndfCancl( "*", status );

  /* Find out the task name and provenance name we were invoked with */
  smf_get_taskname( taskname, NULL, status );

  /* Get the GRP and HDS status for leak checking - need the task name
     to mask out parameter names. Also need to mask out the monlith name */
  one_strlcpy( filter, "!SMURF_MON,!", sizeof(filter), status);
  one_strlcat( filter, taskname, sizeof(filter), status );
  grpInfoi( NULL, 0, "NGRP", &ngrp0, status );
  hdsInfoI( NULL, "LOCATORS", filter, &nloc0, status );


  /* Update the application name in the NDF history recording
     to include the version number of the application */
  snprintf( appname, NDF__SZAPP, "%-*s (%s V%s)", PAR__SZNAM,
            taskname, PACKAGE_UPCASE, PACKAGE_VERSION);
  ndfHappn( appname, status );

  /* Begin a GRP NDF history block. This causes the contents of GRP
     groups to be appended to default history text added to any NDFs
     during the block. */
  ndgBeggh( status );



  /* Call the subroutine associated with the requested task */
  if (strcmp( taskname, "BADBOLOS" ) == 0 ) {
    smurf_extinction( status );
  } else if (strcmp( taskname, "CALCDARK" ) == 0 ) {
    smurf_calcdark( status );
  } else if (strcmp( taskname, "CALCFLAT" ) == 0 ) {
    smurf_calcflat( status );
  } else if (strcmp( taskname, "CALCNOISE" ) == 0 ) {
    smurf_calcnoise( status );
  } else if (strcmp( taskname, "CALCQU" ) == 0 ) {
    smurf_calcqu( status );
  } else if (strcmp( taskname, "CALCRESP" ) == 0 ) {
    smurf_calcresp( status );
  } else if (strcmp( taskname, "COPYFLAT" ) == 0 ) {
    smurf_copyflat( status );
  } else if (strcmp( taskname, "DREAMSOLVE" ) == 0 ) {
    smurf_dreamsolve( status );
  } else if (strcmp( taskname, "DREAMWEIGHTS" ) == 0 ) {
    smurf_dreamweights( status );
  } else if (strcmp( taskname, "DSUTILS" ) == 0 ) {
    smurf_dsutils( status );
  } else if (strcmp( taskname, "EXTINCTION" ) == 0 ) {
    smurf_extinction( status );
  } else if (strcmp( taskname, "FIT1D" ) == 0 ) {
    smurf_fit1d( status );
  } else if (strcmp( taskname, "FIXSTEPS" ) == 0 ) {
    smurf_fixsteps( status );
  } else if (strcmp( taskname, "FLATFIELD" ) == 0 ) {
    smurf_flatfield( status );
  } else if (strcmp( taskname, "FTS2DEGLITCH" ) == 0 ) {
    smurf_fts2_deglitch( status );
  } else if (strcmp( taskname, "FTS2FLATFIELD" ) == 0 ) {
    smurf_fts2_flatfield( status );
  } else if (strcmp( taskname, "FTS2FREQCORR" ) == 0 ) {
    smurf_fts2_freqcorr( status );
  } else if (strcmp( taskname, "FTS2SPLIT" ) == 0 ) {
    smurf_fts2_split( status );
  } else if (strcmp( taskname, "FTS2INIT" ) == 0 ) {
    smurf_fts2_init( status );
  } else if (strcmp( taskname, "FTS2MASKMAP" ) == 0 ) {
    smurf_fts2_maskmap( status );
  } else if (strcmp( taskname, "FTS2OPCORR" ) == 0 ) {
    smurf_fts2_spatialwcs( status );
  } else if (strcmp( taskname, "FTS2PHASECORR" ) == 0 ) {
    smurf_fts2_phasecorr( status );
  } else if (strcmp( taskname, "FTS2PHASECORRDS" ) == 0 ) {
    smurf_fts2_phasecorrds( status );
  } else if (strcmp( taskname, "FTS2PORTIMBAL" ) == 0 ) {
    smurf_fts2_portimbal( status );
  } else if (strcmp( taskname, "FTS2REMOVEBSE" ) == 0 ) {
    smurf_fts2_removebse( status );
  } else if (strcmp( taskname, "FTS2SPECTRUM" ) == 0 ) {
    smurf_fts2_spectrum( status );
  } else if (strcmp( taskname, "FTS2TRANSCORR" ) == 0 ) {
    smurf_fts2_transcorr( status );
  } else if (strcmp( taskname, "GSD2ACSIS" ) == 0 ) {
    smurf_gsd2acsis( status );
  } else if (strcmp( taskname, "GSDSHOW" ) == 0 ) {
    smurf_gsdshow( status );
  } else if (strcmp( taskname, "IMPAZTEC" ) == 0 ) {
    smurf_impaztec( status );
  } else if (strcmp( taskname, "MAKECUBE" ) == 0 ) {
    smurf_makecube( status );
  } else if (strcmp( taskname, "MAKEMAP" ) == 0 ) {
    smurf_makemap( status );
  } else if (strcmp( taskname, "RAWFIXMETA" ) == 0 ) {
    smurf_rawfixmeta( status );
  } else if (strcmp( taskname, "RAWPRESS" ) == 0 ) {
    smurf_rawpress( status );
  } else if (strcmp( taskname, "RAWRECREATEWCS" ) == 0 ) {
    smurf_rawrecreatewcs( status );
  } else if (strcmp( taskname, "RAWREWRTSC2WCS" ) == 0 ) {
    smurf_rawrewrtsc2wcs( status );
  } else if (strcmp( taskname, "RAWUNPRESS" ) == 0 ) {
    smurf_rawunpress( status );
  } else if (strcmp( taskname, "REMSKY" ) == 0 ) {
    smurf_remsky( status );
  } else if (strcmp( taskname, "SC2CLEAN" ) == 0 ) {
    smurf_sc2clean( status );
  } else if (strcmp( taskname, "SC2CONCAT" ) == 0 ) {
    smurf_sc2concat( status );
  } else if (strcmp( taskname, "SC2EXPANDMODEL" ) == 0 ) {
    smurf_sc2expandmodel( status );
  } else if (strcmp( taskname, "SC2FFT" ) == 0 ) {
    smurf_sc2fft( status );
  } else if (strcmp( taskname, "SC2FILTERMAP" ) == 0 ) {
    smurf_sc2filtermap( status );
  } else if (strcmp( taskname, "SC2MAPFFT" ) == 0 ) {
    smurf_sc2mapfft( status );
  } else if (strcmp( taskname, "SC2PCA" ) == 0 ) {
    smurf_sc2pca( status );
  } else if (strcmp( taskname, "SC2SIM" ) == 0 ) {
    smurf_sc2sim( status );
  } else if (strcmp( taskname, "SC2THREADTEST" ) == 0 ) {
    smurf_sc2threadtest( status );
  } else if (strcmp( taskname, "SKYNOISE" ) == 0 ) {
    smurf_skynoise( status );
  } else if (strcmp( taskname, "SMURFCOPY" ) == 0 ) {
    smurf_smurfcopy( status );
  } else if (strcmp( taskname, "SMURFHELP" ) == 0 ) {
    smurf_smurfhelp( status );
  } else if (strcmp( taskname, "STACKFRAMES" ) == 0 ) {
    smurf_stackframes( status );
  } else if (strcmp( taskname, "STARECALC" ) == 0 ) {
    smurf_starecalc( status );
  } else if (strcmp( taskname, "TILEINFO" ) == 0 ) {
    smurf_tileinfo( status );
  } else if (strcmp( taskname, "TILELIST" ) == 0 ) {
    smurf_tilelist( status );
  } else if (strcmp( taskname, "TIMESORT" ) == 0 ) {
    smurf_timesort( status );
  } else if (strcmp( taskname, "UNMAKECUBE" ) == 0 ) {
    smurf_unmakecube( status );
  } else if (strcmp( taskname, "UNMAKEMAP" ) == 0 ) {
    smurf_unmakemap( status );
  } else {
    *status = SAI__ERROR;
    msgSetc( "TASK", taskname );
    errRep( "smurf_mon", "Unrecognized taskname: ^TASK", status);
  }


  /* End the GRP NDF history block. */
  ndgEndgh( status );

  /* Clear cached info from sc2ast_createwcs. */
  sc2ast_createwcs(SC2AST__NULLSUB, NULL, NULL, NULL, NO_FTS, NULL, status);

  /* Clear WVM caches (one for each thread). */
  smf_calc_wvm_clear( status );

  /* Free AST resources */
  astTune( "MemoryCaching", memory_caching );
  astEnd;

  /* Check for GRP leaks Do this in a new error reporting context so
   * that we get the correct value even if an error has occurred. */
  errBegin( status );
  grpInfoi( NULL, 0, "NGRP", &ngrp1, status );

  /* If there are more active groups now than there were on entry,
   * there must be a problem (GRP identifiers are not being freed
   * somewhere). So report it. */
  if (*status == SAI__OK && ngrp1 > ngrp0) {
    msgBlank( status );
    msgSetc( "NAME", taskname );
    msgSeti( "NGRP0", ngrp0 );
    msgSeti( "NGRP1", ngrp1 );
    msgOut( " ", "WARNING: The number of active "
            "GRP identifiers increased from ^NGRP0 to ^NGRP1 "
            "during execution of ^NAME (" PACKAGE_UPCASE " programming "
            " error).", status);
    msgBlank(status);
    grpWatch( 0, status );
  }
  errEnd( status );

  /* The NDF library registers locators with SUBPAR for any NDFs that
     are opened directly using ndfAssoc or ndfExist. These locators are
     only annulled when the associated parameters are cancelled, but most
     smurf applications do not explicitly cancel their NDF parameters.
     This means that such locators are picked up by the following check
     for dangling HDS locators. In order to prevent this, we cancel any
     remaining NDF parameters now, excluding any that were marked by the
     call to ndfCancl at the start of this routine. */
  ndfCancl( " ", status );

  /* Check for HDS leaks Do this in a new error reporting context so
   * that we get the correct value even if an error has occurred. */
  errBegin( status );
  hdsInfoI( NULL, "LOCATORS", filter, &nloc1, status );

  /* If there are more active locators now than there were on entry,
   * there must be a problem (HDS locators are not being freed
   * somewhere). So report it. */
  if (*status == SAI__OK && nloc1 > nloc0) {
    msgBlank( status );
    msgSetc( "NAME", taskname );
    msgSeti( "NLOC0", nloc0 );
    msgSeti( "NLOC1", nloc1 );
    msgOut( " ", "WARNING: The number of active "
            "HDS Locators increased from ^NLOC0 to ^NLOC1 "
            "during execution of ^NAME (" PACKAGE_UPCASE " programming "
            " error).", status);
    msgBlank(status);
    hdsShow("LOCATORS", status);
    hdsShow("FILES", status);
    printf("filter - %s\n",filter);
  }
  errEnd( status );

  /* Read the exitt error message stack level */
  emsLevel( &emslev2 );

  if (*status == SAI__OK && emslev1 != emslev2 ) {
    errMark();
    msgBlank( status );
    msgSetc( "NAME", taskname );
    msgSeti( "LV1", emslev1);
    msgSeti( "LV2", emslev2);
    msgOut( " ", "WARNING: EMS Stack level went from ^LV1 to ^LV2"
            " during execution of ^NAME (" PACKAGE_UPCASE " programming"
            " error).", status );
    msgBlank(status);
    errRlse();
  }

  /* configure AST --with-memdebug, and uncomment the following lines
     to see how much memory usage SMURF hit at its peak */
  /*
  {
    size_t memcurrent,mempeak;
    astMemoryStats( 0, &mempeak, &memcurrent );
    msgOutf( "", "SMURF: === current /peak memory usage: %zu / %zu MiB ===",
             status, memcurrent/SMF__MIB, mempeak/SMF__MIB );
  }
  */

  /* The astCheckMemory function does nothing unless AST has been compiled
   * with the MEM_DEBUG flag. If this is the case, then it reports the number
   * of memory blocks that have not been freed (useful for identifying memory
   * leaks). Use astActiveMemory() below to list all active memory and
   * then use astWatchMemory() at the start of this routine to get reports
   * when a particular ID is used. Set a breakpoint in the debugger for
   * astMemoryAlarm_
   */
  astActiveMemory("Exit:");
  astCheckMemory;
}
Пример #29
0
void smf_rebinsparse( smfData *data, int first, int *ptime, AstFrame *ospecfrm,
                      AstMapping *ospecmap, AstSkyFrame *oskyframe,
                      Grp *detgrp, int lbnd_out[ 3 ], int ubnd_out[ 3 ],
                      int genvar, float *data_array, float *var_array,
                      int *ispec, float *texp_array, float *teff_array,
                      double *fcon, int *status ){

/* Local Variables */
   AstCmpMap *fmap = NULL;      /* Mapping from spectral grid to topo freq Hz */
   AstCmpMap *ssmap = NULL;     /* I/p GRID-> o/p PIXEL Mapping for spectral axis */
   AstFitsChan *fc = NULL;      /* Storage for FITS headers */
   AstFrame *specframe = NULL;  /* Spectral Frame in input FrameSet */
   AstFrame *specframe2 = NULL; /* Temporary copy of SpecFrame in input WCS */
   AstFrameSet *fs = NULL;      /* A general purpose FrameSet pointer */
   AstFrameSet *swcsin = NULL;  /* FrameSet describing spatial input WCS */
   AstMapping *fsmap = NULL;    /* Base->Current Mapping extracted from a FrameSet */
   AstMapping *specmap = NULL;  /* PIXEL -> Spec mapping in input FrameSet */
   char *fftwin = NULL;  /* Name of FFT windowing function */
   const char *name = NULL; /* Pointer to current detector name */
   const double *tsys=NULL; /* Pointer to Tsys value for first detector */
   dim_t timeslice_size; /* No of detector values in one time slice */
   double *spectab = NULL;/* Workspace for spectral output grid positions */
   double *xin = NULL;   /* Workspace for detector input grid positions */
   double *xout = NULL;  /* Workspace for detector output pixel positions */
   double *yin = NULL;   /* Workspace for detector input grid positions */
   double *yout = NULL;  /* Workspace for detector output pixel positions */
   double at;            /* Frequency at which to take the gradient */
   double dnew;          /* Channel width in Hz */
   double fcon2;         /* Variance factor for whole file */
   double k;             /* Back-end degradation factor */
   double tcon;          /* Variance factor for whole time slice */
   float *pdata = NULL;  /* Pointer to next data sample */
   float *qdata = NULL;  /* Pointer to next data sample */
   float rtsys;          /* Tsys value */
   float teff;           /* Effective integration time, times 4 */
   float texp;           /* Total time ( = ton + toff ) */
   float toff;           /* Off time */
   float ton;            /* On time */
   int *nexttime = NULL; /* Pointer to next time slice index to use */
   int dim[ 3 ];         /* Output array dimensions */
   int found;            /* Was current detector name found in detgrp? */
   int good;             /* Are there any good detector samples? */
   int ibasein;          /* Index of base Frame in input FrameSet */
   int ichan;            /* Index of current channel */
   int iv;               /* Offset to next element */
   int iz;               /* Output grid index on axis 3 */
   int nchan;            /* Number of input spectral channels */
   int pixax[ 3 ];       /* The output fed by each selected mapping input */
   int specax;           /* Index of spectral axis in input FrameSet */
   size_t irec;          /* Index of current input detector */
   size_t itime;         /* Index of current time slice */
   smfHead *hdr = NULL;  /* Pointer to data header for this time slice */

/* Check inherited status */
   if( *status != SAI__OK ) return;

/* Begin an AST context.*/
   astBegin;

/* Store a pointer to the input NDFs smfHead structure. */
   hdr = data->hdr;

/* Store the dimensions of the output array. */
   dim[ 0 ] = ubnd_out[ 0 ] - lbnd_out[ 0 ] + 1;
   dim[ 1 ] = ubnd_out[ 1 ] - lbnd_out[ 1 ] + 1;
   dim[ 2 ] = ubnd_out[ 2 ] - lbnd_out[ 2 ] + 1;

/* Store the number of pixels in one time slice */
   timeslice_size = (data->dims)[ 0 ]*(data->dims)[ 1 ];

/* We want a description of the spectral WCS axis in the input file. If
   the input file has a WCS FrameSet containing a SpecFrame, use it,
   otherwise we will obtain it from the FITS header later. NOTE, if we knew
   that all the input NDFs would have the same spectral axis calibration,
   then the spectral WCS need only be obtained from the first NDF. However,
   in the general case, I presume that data files may be combined that use
   different spectral axis calibrations, and so these differences need to
   be taken into account. */
   if( hdr->tswcs ) {
      fs = astClone( hdr->tswcs );

/* The first axis should be a SpecFrame. See if this is so. If not annul
   the specframe pointer. */
      specax = 1;
      specframe = astPickAxes( fs, 1, &specax, NULL );
      if( !astIsASpecFrame( specframe ) ) specframe = astAnnul( specframe );
   }

/* If the above did not yield a SpecFrame, use the FITS-WCS headers in the
   FITS extension of the input NDF. Take a copy of the FITS header (so that
   the contents of the header are not changed), and then read a FrameSet
   out of it. */
   if( !specframe ) {
      fc = astCopy( hdr->fitshdr );
      astClear( fc, "Card" );
      fs = astRead( fc );

/* Extract the SpecFrame that describes the spectral axis from the current
   Frame of this FrameSet. This is assumed to be the third WCS axis (NB
   the different axis number). */
      specax = 3;
      specframe = astPickAxes( fs, 1, &specax, NULL );
   }

/* Split off the 1D Mapping for this single axis from the 3D Mapping for
   the whole WCS. This results in "specmap" holding the Mapping from
   SpecFrame value to GRID value. */
   fsmap = astGetMapping( fs, AST__CURRENT, AST__BASE );
   astMapSplit( fsmap, 1, &specax, pixax, &specmap );

/* Invert the Mapping for the spectral axis so that it goes from input GRID
   coord to spectral coord. */
   astInvert( specmap );

/* Get a Mapping that converts values in the input spectral system to the
   corresponding values in the output spectral system. */
   fs = astConvert( specframe, ospecfrm, "" );

/* Concatenate these Mappings with the supplied spectral Mapping to get
   a Mapping from the input spectral grid axis (pixel axis 1) to the
   output spectral grid axis (pixel axis 3). Simplify the Mapping. */
   ssmap = astCmpMap( astCmpMap( specmap, astGetMapping( fs, AST__BASE,
                                                         AST__CURRENT ),
                                 1, " " ),
                      ospecmap, 1, " " );
   ssmap = astSimplify( ssmap );

/* Create a table with one element for each channel in the input array,
   holding the index of the nearest corresponding output channel. */
   nchan = (data->dims)[ 0 ];
   spectab = astMalloc( sizeof( *spectab )*nchan );
   if( spectab ) {
      for( ichan = 0; ichan < nchan; ichan++ ) spectab[ ichan ] = ichan + 1;
      astTran1( ssmap, nchan, spectab, 1, spectab );
      for( ichan = 0; ichan < nchan; ichan++ ) {
         if( spectab[ ichan ] != AST__BAD ) {
            iz = floor( spectab[ ichan ] + 0.5 );
            if( iz >= 1 && iz <= dim[ 2 ] ) {
               spectab[ ichan ] = iz;
            } else {
               spectab[ ichan ] = 0;
            }
         } else {
            spectab[ ichan ] = 0;
         }
      }
   }

/* Allocate work arrays big enough to hold the coords of all the
   detectors in the current input file.*/
   xin = astMalloc( (data->dims)[ 1 ] * sizeof( *xin ) );
   yin = astMalloc( (data->dims)[ 1 ] * sizeof( *yin ) );
   xout = astMalloc( (data->dims)[ 1 ] * sizeof( *xout ) );
   yout = astMalloc( (data->dims)[ 1 ] * sizeof( *yout ) );

/* Initialise a string to point to the name of the first detector for which
   data is available */
   name = hdr->detname;

/* Store input coords for the detectors. Axis 1 is the detector index, and
   axis 2 is a dummy axis that always has the value 1. */
   for( irec = 0; irec < (data->dims)[ 1 ]; irec++ ) {
      xin[ irec ] = irec + 1.0;
      yin[ irec ] = 1.0;

/* If a group of detectors to be used was supplied, search the group for
   the name of the current detector. If not found, set the GRID coords bad. */
      if( detgrp ) {
         found = grpIndex( name, detgrp, 1, status );
         if( !found ) {
            xin[ irec ] = AST__BAD;
            yin[ irec ] = AST__BAD;
         }
      }

/* Move on to the next available detector name. */
      name += strlen( name ) + 1;
   }

/* Find the constant factor associated with the current input file. This
   is the squared backend degradation factor, divided by the noise bandwidth.
   Get the required FITS headers, checking they were found. */
   if( astGetFitsF( hdr->fitshdr, "BEDEGFAC", &k ) &&
       astGetFitsS( hdr->fitshdr, "FFT_WIN", &fftwin ) ){

/* Get a Mapping that converts values in the input spectral system to
   topocentric frequency in Hz, and concatenate this Mapping with the
   Mapping from input GRID coord to the input spectral system. The result
   is a Mapping from input GRID coord to topocentric frequency in Hz. */
      specframe2 = astCopy( specframe );
      astSet( specframe2, "system=freq,stdofrest=topo,unit=Hz" );
      fmap = astCmpMap( specmap, astGetMapping( astConvert( specframe,
                                                            specframe2,
                                                            "" ),
                                                AST__BASE, AST__CURRENT ),
                        1, " " );

/* Differentiate this Mapping at the mid channel position to get the width
   of an input channel in Hz. */
      at = 0.5*nchan;
      dnew = astRate( fmap, &at, 1, 1 );

/* Modify the channel width to take account of the effect of the FFT windowing
   function. Allow undef value because FFT_WIN for old data had a broken value
   in hybrid subband modes. */
      if( dnew != AST__BAD ) {
         dnew = fabs( dnew );

         if( !strcmp( fftwin, "truncate" ) ) {
            dnew *= 1.0;

         } else if( !strcmp( fftwin, "hanning" ) ) {
            dnew *= 1.5;

	    } else if( !strcmp( fftwin, "<undefined>" ) ) {
	      /* Deal with broken data - make an assumption */
	       dnew *= 1.0;

         } else if( *status == SAI__OK ) {
            *status = SAI__ERROR;
            msgSetc( "W", fftwin );
            errRep( FUNC_NAME, "FITS header FFT_WIN has unknown value "
                    "'^W' (programming error).", status );
         }

/* Form the required constant. */
         fcon2 = k*k/dnew;

      } else {
         fcon2 = VAL__BADD;
      }

   } else {
      fcon2 = VAL__BADD;
   }

/* Return the factor needed for calculating Tsys from the variance. */
   if( first ) {
      *fcon = fcon2;
   } else if( fcon2 != *fcon ) {
      *fcon = VAL__BADD;
   }

/* Initialise a pointer to the next time slice index to be used. */
   nexttime = ptime;

/* Loop round all the time slices in the input file. */
   for( itime = 0; itime < (data->dims)[ 2 ] && *status == SAI__OK; itime++ ) {

/* If this time slice is not being pasted into the output cube, pass on. */
      if( nexttime ){
         if( *nexttime != itime ) continue;
         nexttime++;
      }

/* Store a pointer to the first input data value in this time slice. */
      pdata = ( (float *) (data->pntr)[ 0 ] ) + itime*timeslice_size;

/* Get a FrameSet describing the spatial coordinate systems associated with
   the current time slice of the current input data file. The base frame in
   the FrameSet will be a 2D Frame in which axis 1 is detector number and
   axis 2 is unused. The current Frame will be a SkyFrame (the SkyFrame
   System may be any of the JCMT supported systems). The Epoch will be
   set to the epoch of the time slice. */
      smf_tslice_ast( data, itime, 1, NO_FTS, status );
      swcsin = hdr->wcs;

/* Note the total exposure time (texp) for all the input spectra produced by
   this time slice. */
      ton = hdr->state->acs_exposure;
      if( ton == 0.0 ) ton = VAL__BADR;

      toff = hdr->state->acs_offexposure;
      if( toff == 0.0 ) toff = VAL__BADR;

      if( ton != VAL__BADR && toff != VAL__BADR ) {
         texp = ton + toff;
         teff = 4*ton*toff/( ton + toff );
      } else {
         texp = VAL__BADR;
         teff = VAL__BADR;
      }

/* If output variances are being calculated on the basis of Tsys values
   in the input, find the constant factor associated with the current
   time slice. */
      tcon = AST__BAD;
      if( genvar == 2 && fcon2 != AST__BAD && texp != VAL__BADR ) {
         tcon = fcon2*( 1.0/ton + 1.0/toff );

/* Get a pointer to the start of the Tsys values for this time slice. */
         tsys = hdr->tsys + hdr->ndet*itime;
      }

/* We now create a Mapping from detector index to position in oskyframe. */
      astInvert( swcsin );
      ibasein = astGetI( swcsin, "Base" );
      fs = astConvert( swcsin, oskyframe, "SKY" );
      astSetI( swcsin, "Base", ibasein );
      astInvert( swcsin );

      if( fs == NULL ) {
         if( *status == SAI__OK ) {
            if (data->file) {
               smf_smfFile_msg(data->file, "FILE", 1, "<unknown>");
            } else {
               msgSetc( "FILE", "<unknown>" );
            }
            *status = SAI__ERROR;
            errRep( FUNC_NAME, "The spatial coordinate system in ^FILE "
                    "is not compatible with the spatial coordinate "
                    "system in the first input file.", status );
         }
         break;
      }

/* Transform the positions of the detectors from input GRID to oskyframe
   coords. */
      astTran2( fs, (data->dims)[ 1 ], xin, yin, 1, xout, yout );

/* Loop round all detectors. */
      for( irec = 0; irec < (data->dims)[ 1 ]; irec++ ) {

/* If the detector has a valid position, see if it produced any good
   data values. */
         if( xout[ irec ] != AST__BAD && yout[ irec ] != AST__BAD ) {
            qdata = pdata;
            good = 0;
            for( ichan = 0; ichan < nchan; ichan++ ){
               if( *(qdata++) != VAL__BADR ) {
                  good = 1;
                  break;
               }
            }

/* If it did, calculate the variance associated with each detector
   sample (if required), based on the input Tsys values, and copy the
   spectrum to the output NDF. */
            if( good ) {
               if( *ispec < dim[ 0 ] ){
                  rtsys = tsys ? (float) tsys[ irec ] : VAL__BADR;
                  if( rtsys <= 0.0 ) rtsys = VAL__BADR;
                  if( tcon != AST__BAD && genvar == 2 && rtsys != VAL__BADR ) {
                     var_array[ *ispec ] = tcon*rtsys*rtsys;
                  } else if( var_array ) {
                     var_array[ *ispec ] = VAL__BADR;
                  }

                  if( texp != VAL__BADR ) {
                     texp_array[ *ispec ] = texp;
                     teff_array[ *ispec ] = teff;
                  }

                  for( ichan = 0; ichan < nchan; ichan++, pdata++ ) {
                     iz = spectab[ ichan ] - 1;
                     if( iz >= 0 && iz < dim[ 2 ] ) {
                        iv = *ispec + dim[ 0 ]*iz;
                        data_array[ iv ] = *pdata;
                     }
                  }

                  (*ispec)++;

               } else if( *status == SAI__OK ){
                  *status = SAI__ERROR;
                  msgSeti( "DIM", dim[ 0 ] );
                  errRep( " ", "Too many spectra (more than ^DIM) for "
                          "the output NDF (programming error).", status );
                  break;
               }

/* If this detector does not have any valid data values, increment the data
   pointer to point at the first sample for the next detector. */
            } else {
               pdata += nchan;
            }

/* If this detector does not have a valid position, increment the data
   pointer to point at the first sample for the next detector. */
         } else {
            pdata += nchan;
         }
      }

/* For efficiency, explicitly annul the AST Objects created in this tight
   loop. */
      fs = astAnnul( fs );
   }

/* Free resources */
   spectab = astFree( spectab );
   xin = astFree( xin );
   yin = astFree( yin );
   xout = astFree( xout );
   yout = astFree( yout );

/* End the AST context. This will annul all AST objects created within the
   context (except for those that have been exported from the context). */
   astEnd;
}
Пример #30
0
   static char *ccdTclEval( ccdTcl_Interp *cinterp, const char *cmd, int *status ) {
/*
*+
*  Name:
*     ccdTclEval

*  Purpose:
*     Evaluate a Tcl command.

*  Language:
*     Starlink C

*  Description:
*     This routine executes a command in the Tcl interpreter specified
*     by the cinterp argument, and returns the interpreter's result
*     as a character string.  If the return code from the Tcl
*     interpreter was not TCL_OK, then the status argument will be set.
*
*     It does it by writing the text of the command down the pipe to
*     the child process set up by a previous ccdTclStart call, and then
*     reading the response sent back up the pipe from that process.
*     It also watches for, and outputs appropriately, messages for
*     output via the CCDPACK logging system which may come up the pipe.
*
*     This function is declared static, and so not intended for use
*     by external code.  External routines should use ccdTclDo or one
*     of the other ccdTcl* functions instead.

*  Arguments:
*     cinterp = ccdTcl_Interp *
*        The interpreter got from a previous ccdTclStart call.
*     cmd = const char *
*        A string representing a Tcl command.  As currently implemented
*        this probably ought not to be too long; below 4096 characters
*        should be all right.
*     status = int *
*        The global status.

*  Return Value:
*     A pointer to a static character string is returned, which contains
*     the string result of the evaluation.  This will be overwritten by
*     the next call to this routine.

*  Copyright:
*     Copyright (C) 2006 Particle Physics & Astronomy Research 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., 59 Temple Place,Suite 330, Boston, MA
*     02111-1307, USA

*  Authors:
*     {original_author_entry}

*  History:
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*-
*/

/* Local variables. */
      int bytes;
      int ifd = cinterp->upfd[ 0 ];
      int ofd = cinterp->downfd[ 1 ];
      int tclrtn;
      void (*handler)(int);
      char *c;
      static char retbuf[ BUFLENG ];
      DECLARE_CHARACTER( fmsg, MSG__SZMSG );
      DECLARE_CHARACTER( fname, MSG__SZMSG );

/* Check inherited status. */
      if ( *status != SAI__OK ) return NULL;

/* Write the text of the command to execute to the downward pipe, so that
   the child process can execute it.  We ignore a SIGPIPE but check for
   an I/O error, so that the program deals gracefully with a broken pipe. */
      handler = signal( SIGPIPE, SIG_IGN );
      if ( write( ofd, cmd, strlen( cmd ) + 1 ) < 0 ) {
         *status = SAI__ERROR;
         msgSetc( "ERROR", strerror( errno ) );
         errRep( "CCD_TCL_WRITE", "^ERROR", status );
      }
      signal( SIGPIPE, handler );

/* Loop until we get a return status which indicates the command has
   completed (i.e. not one which just requires output through the ADAM
   message system). */
      do {

/* Read the Tcl return status from the upward pipe. */
         tclrtn = -1;
         bytes = read( ifd, &tclrtn, sizeof( int ) );

/* Read the result of the evaluation from the upward pipe. */
         c = retbuf - 1;
         *retbuf = '\0';
         do {
            if ( ++c >= retbuf + BUFLENG ) {
               *status = SAI__ERROR;
               errRep( "CCD_TCL_BUF", "Buffer overflow", status );
               return NULL;
            }
            bytes = read( ifd, c, 1 );

/* If the read failed then we probably caught a signal or the child
   process stopped writing in the middle of a command.  Neither of these
   should happen, so signal an error.  It might be desirable to do
   something smarter than this on receipt of a signal (like try the
   read again) but I don't think that it is a very likely eventuality. */
            if ( bytes != 1 ) {
               strcpy( c, "\n   Tcl communications error\n" );
               c += strlen( c );
               tclrtn = -1;
            }
         } while ( *c != '\0' );

/* If the Tcl return status was CCD_CCDMSG, CCD_CCDLOG or CCD_CCDERR then
   what follows are two strings, separated by a carriage return, to output
   via the ADAM message system. */
         if ( tclrtn == CCD_CCDLOG || tclrtn == CCD_CCDERR ||
              tclrtn == CCD_CCDMSG ) {
            c = index( retbuf, '\n' );
            *(c++) = '\0';
            cnfExprt( retbuf, fname, MSG__SZMSG );
            cnfExprt( c, fmsg, MSG__SZMSG );
            if ( tclrtn == CCD_CCDLOG ) {
               F77_CALL(ccd1_msg)( CHARACTER_ARG(fname), CHARACTER_ARG(fmsg),
                                   INTEGER_ARG(status)
                                   TRAIL_ARG(fname) TRAIL_ARG(fmsg) );
            }
            else if ( tclrtn == CCD_CCDERR ) {
               F77_CALL(ccd1_errep)( CHARACTER_ARG(fname), CHARACTER_ARG(fmsg),
                                     INTEGER_ARG(status)
                                     TRAIL_ARG(fname) TRAIL_ARG(fmsg) );
            }
            else if ( tclrtn == CCD_CCDMSG ) {
               F77_CALL(msg_out)( CHARACTER_ARG(fname), CHARACTER_ARG(fmsg),
                                  INTEGER_ARG(status)
                                  TRAIL_ARG(fname) TRAIL_ARG(fmsg) );
            }
         }
      } while ( tclrtn == CCD_CCDLOG || tclrtn == CCD_CCDERR ||
                tclrtn == CCD_CCDMSG );

/* If the Tcl return status was not TCL_OK, then flag an error and write
   an error report. */
      if ( tclrtn != TCL_OK ) {
         int done = 0;
         char *estart;
         const char *fmt = ( tclrtn == TCL_ERROR ) ? "Tcl error:\n%s"
                                             : "Unexpected Tcl return:\n%s";
         snprintf( buffer, BUFLENG - strlen( fmt ), fmt, retbuf );
         *status = SAI__ERROR;
         for ( estart = buffer; ! done; estart = c + 1 ) {
            for ( c = estart; *c != '\n' && *c != '\0'; c++ );
            if ( *c == '\0' ) done = 1;
            *c = '\0';
            errRep( "CCD_TCL_TCLERR", estart, status );
         }
      }

/* Return the result. */
      return retbuf;
   }