Ejemplo n.º 1
0
void smurf_sc2clean( int *status ) {
  smfArray *array = NULL;    /* Data to be cleaned */
  Grp *basegrp=NULL;         /* Grp containing first file each chunk */
  size_t basesize;           /* Number of files in base group */
  smfArray *bbms = NULL;     /* Bad bolometer masks */
  smfArray *concat=NULL;     /* Pointer to a smfArray */
  size_t contchunk;          /* Continuous chunk counter */
  smfArray *darks = NULL;    /* Dark data */
  int ensureflat;            /* Flag for flatfielding data */
  smfArray *flatramps = NULL;/* Flatfield ramps */
  AstKeyMap *heateffmap = NULL;    /* Heater efficiency data */
  smfData *odata = NULL;     /* Pointer to output data struct */
  Grp *fgrp = NULL;          /* Filtered group, no darks */
  size_t gcount=0;           /* Grp index counter */
  size_t idx;                /* Subarray counter */
  Grp *igrp = NULL;          /* Input group of files */
  smfGroup *igroup=NULL;     /* smfGroup corresponding to igrp */
  dim_t maxconcat=0;         /* Longest continuous chunk length in samples */
  double maxlen=0;           /* Constrain maxconcat to this many seconds */
  size_t ncontchunks=0;      /* Number continuous chunks outside iter loop */
  Grp *ogrp = NULL;          /* Output group of files */
  size_t osize;              /* Total number of NDF names in the output group */
  dim_t padStart=0;          /* How many samples padding at start */
  dim_t padEnd=0;            /* How many samples padding at end */
  size_t size;               /* Number of files in input group */
  int temp;                  /* Temporary signed integer */
  int usedarks;              /* flag for using darks */
  ThrWorkForce *wf = NULL;   /* Pointer to a pool of worker threads */
  int writecom;              /* Write COMmon mode to NDF if calculated? */
  int writegai;              /* Write GAIns to NDF if calculated? */

  /* Main routine */
  ndfBegin();

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

  /* Read the input file */
  kpg1Rgndf( "IN", 0, 1, "", &igrp, &size, status );

  /* Filter out darks */
  smf_find_science( wf, igrp, &fgrp, 1, NULL, NULL, 1, 1, SMF__NULL, &darks,
                    &flatramps, &heateffmap, NULL, status );

  /* input group is now the filtered group so we can use that and
     free the old input group */
  size = grpGrpsz( fgrp, status );
  grpDelet( &igrp, status);
  igrp = fgrp;
  fgrp = NULL;

  if (size == 0) {
    msgOutif(MSG__NORM, " ","All supplied input frames were filtered,"
       " nothing to do", status );
    goto CLEANUP;
  }

  /* --- Parse ADAM parameters ---------------------------------------------- */

  /* Maximum length of a continuous chunk */
  parGdr0d( "MAXLEN", 0, 0, VAL__MAXD, 1, &maxlen, status );

  /* Padding */
  parGdr0i( "PADSTART", 0, 0, VAL__MAXI, 1, &temp, status );
  padStart = (dim_t) temp;

  parGdr0i( "PADEND", 0, 0, VAL__MAXI, 1, &temp, status );
  padEnd = (dim_t) temp;

  /* Are we using darks? */
  parGet0l( "USEDARKS", &usedarks, status );

  /* Are we flatfielding? */
  parGet0l( "FLAT", &ensureflat, status );

  /* Write COM/GAI to NDFs if calculated? */
  parGet0l( "COM", &writecom, status );
  parGet0l( "GAI", &writegai, status );

  /* Get group of bolometer masks and read them into a smfArray */
  smf_request_mask( wf, "BBM", &bbms, status );

  /* Group the input files by subarray and continuity ----------------------- */
  smf_grp_related( igrp, size, 1, 0, maxlen-padStart-padEnd, NULL, NULL,
                   &maxconcat, NULL, &igroup, &basegrp, NULL, status );

  /* Obtain the number of continuous chunks and subarrays */
  if( *status == SAI__OK ) {
    ncontchunks = igroup->chunk[igroup->ngroups-1]+1;
  }

  basesize = grpGrpsz( basegrp, status );

  /* Get output file(s) */
  kpg1Wgndf( "OUT", basegrp, basesize, basesize,
             "More output files required...",
             &ogrp, &osize, status );

  /* Loop over continuous chunks and clean -----------------------------------*/
  gcount = 1;
  for( contchunk=0;(*status==SAI__OK)&&contchunk<ncontchunks; contchunk++ ) {
    AstKeyMap *keymap=NULL;
    int dkclean;
    AstKeyMap *sub_instruments=NULL;

    /* Place cleaning parameters into a keymap and set defaults. Do
       this inside the loop in case we are cleaning files with
       differing sub-instruments.  Note that we use the map-maker
       defaults file here (which loads the sc2clean defaults) so that
       we populate the locked keymap with all the parameters that
       people may come across to allow them to load their map-maker
       config directly into sc2clean.
    */

    sub_instruments = smf_subinst_keymap( SMF__SUBINST_NONE,
                                          NULL, igrp,
                                          igroup->subgroups[contchunk][0],
                                          status );

    keymap = kpg1Config( "CONFIG", "$SMURF_DIR/smurf_makemap.def",
                         sub_instruments, 1, status );
    if( sub_instruments ) sub_instruments = astAnnul( sub_instruments );

    /* Now rerun smf_grp_related to figure out how long each downsampled
       chunk of data will be. */

    if( basegrp ) grpDelet( &basegrp, status );
    if( igroup ) smf_close_smfGroup( &igroup, status );

    smf_grp_related( igrp, size, 1, 0, maxlen-padStart-padEnd, NULL, keymap,
                     &maxconcat, NULL, &igroup, &basegrp, NULL, status );

    /* Concatenate this continuous chunk */
    smf_concat_smfGroup( wf, NULL, igroup, usedarks ? darks:NULL, bbms, flatramps,
                         heateffmap, contchunk, ensureflat, 1, NULL, 0, NULL,
                         NULL, NO_FTS, padStart, padEnd, 0, &concat, NULL, status );

    if( *status == SAI__OK) {
      /* clean the dark squids now since we might need to use them
         to clean the bolometer data */

      smf_get_cleanpar( keymap, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                        &dkclean, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                        NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                        NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                        NULL, NULL, NULL, status );

      for( idx=0; dkclean&&(*status==SAI__OK)&&idx<concat->ndat; idx++ ) {
        odata = concat->sdata[idx];

        if( odata && odata->da && odata->da->dksquid ) {
          smfData *dksquid = odata->da->dksquid;
          AstKeyMap *kmap=NULL;

          msgOut("", TASK_NAME ": cleaning dark squids", status);

          /* fudge the header so that we can get at JCMTState */
          dksquid->hdr = odata->hdr;

          /* clean darks using cleandk.* parameters */
          astMapGet0A( keymap, "CLEANDK", &kmap );
          array = smf_create_smfArray( status );
          smf_addto_smfArray( array, dksquid, status );
          smf_clean_smfArray( wf, array, NULL, NULL, NULL, kmap, status );
          if( array ) {
            array->owndata = 0;
            smf_close_related( wf, &array, status );
          }
          if( kmap ) kmap = astAnnul( kmap );

          /* Unset hdr pointer so that we don't accidentally close it */
          dksquid->hdr = NULL;
        }
      }

      /* Then the main data arrays */
      if( *status == SAI__OK ) {
        smfArray *com = NULL;
        smfArray *gai = NULL;
        char filename[GRP__SZNAM+1];

        msgOut("", TASK_NAME ": cleaning bolometer data", status );
        smf_clean_smfArray( wf, concat, NULL, &com, &gai, keymap, status );

        /* If ADAM parameters for COM or GAI were specified, and the
           common-mode was calculated, export to files here */

        if( writecom && com ) {
          for( idx=0; (*status==SAI__OK)&&(idx<com->ndat); idx++ ) {
            smf_model_createHdr( com->sdata[idx], SMF__COM, concat->sdata[idx],
                                 status );
            smf_stripsuffix( com->sdata[idx]->file->name,
                             SMF__DIMM_SUFFIX, filename, status );

            smf_dataOrder( wf, com->sdata[idx], 1, status );

            smf_write_smfData( wf, com->sdata[idx], NULL, filename, NULL, 0,
                               NDF__NOID, MSG__NORM, 0, NULL, NULL, status );
          }
        }

        if( writegai && gai ) {
          for( idx=0; (*status==SAI__OK)&&(idx<gai->ndat); idx++ ) {
            smf_model_createHdr( gai->sdata[idx], SMF__GAI, concat->sdata[idx],
                                 status );
            smf_stripsuffix( gai->sdata[idx]->file->name,
                             SMF__DIMM_SUFFIX, filename, status );

            smf_dataOrder( wf, gai->sdata[idx], 1, status );
            smf_write_smfData( wf, gai->sdata[idx], NULL, filename, NULL, 0,
                               NDF__NOID, MSG__NORM, 0, NULL, NULL, status );
          }
        }

        /* Close com and gai */
        if( com ) smf_close_related( wf, &com, status );
        if( gai ) smf_close_related( wf, &gai, status );

      }

      /* Report statistics (currently need a smfArray for that) */
      if (*status == SAI__OK) {
        size_t last_qcount[SMF__NQBITS];
        size_t last_nmap = 0;
        smf_qualstats_report( wf, MSG__VERB, SMF__QFAM_TSERIES, 1, concat,
                              last_qcount, &last_nmap, 1, NULL, NULL, status );
      }

      /* Clean up for contchunk loop */
      if( keymap ) keymap = astAnnul( keymap );
    }

    /* Export concatenated/cleaned data for each subarray to NDF file */
    for( idx=0; (*status==SAI__OK)&&idx<concat->ndat; idx++ ) {
      odata = concat->sdata[idx];

      /* Complete the history information in the output NDF so that it
         includes group parameters accessed since the default history
         information was written to the NDF (in smf_open_and_flatfield). */
      smf_puthistory( odata, "SMURF:SC2CLEAN", status );

      /* Ensure ICD data order */
      smf_dataOrder( wf, odata, 1, status );

      if( odata->file && odata->file->name ) {
        smf_write_smfData( wf, odata, NULL, NULL, ogrp, gcount, NDF__NOID,
                           MSG__VERB, 0, NULL, NULL, status );
      } else {
        *status = SAI__ERROR;
        errRep( FUNC_NAME,
                "Unable to determine file name for concatenated data.",
                status );
      }

      /* Increment the group index counter */
      gcount++;
    }

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

  /* Write out the list of output NDF names, annulling the error if a null
     parameter value is supplied. */
  if( *status == SAI__OK && ogrp ) {
    grpList( "OUTFILES", 0, 0, NULL, ogrp, status );
    if( *status == PAR__NULL ) errAnnul( status );
  }

 CLEANUP:

  /* Tidy up after ourselves: release the resources used by the grp routines */
  if( darks ) smf_close_related( wf, &darks, status );
  if( flatramps ) smf_close_related( wf, &flatramps, status );
  if (heateffmap) heateffmap = smf_free_effmap( heateffmap, status );
  if( bbms ) smf_close_related( wf, &bbms, status );
  if( igrp ) grpDelet( &igrp, status);
  if( ogrp ) grpDelet( &ogrp, status);
  if( basegrp ) grpDelet( &basegrp, status );
  if( igroup ) smf_close_smfGroup( &igroup, status );
  fftw_cleanup();
  ndfEnd( status );
}
Ejemplo n.º 2
0
void smurf_sc2concat( int *status ) {

  /* Local Variables */
  Grp *basegrp=NULL;         /* Grp containing first file each chunk */
  size_t basesize;           /* Number of files in base group */
  smfArray *concat=NULL;     /* Pointer to a smfArray */
  size_t contchunk;          /* Continuous chunk counter */
  smfArray *darks = NULL;    /* dark frames */
  int ensureflat;            /* Flag for flatfielding data */
  Grp *fgrp = NULL;          /* Filtered group, no darks */
  smfArray * flatramps = NULL; /* Flatfield ramps */
  AstKeyMap *heateffmap = NULL;    /* Heater efficiency data */
  size_t gcount=0;           /* Grp index counter */
  size_t idx;                /* Subarray counter */
  int usedarks;              /* flag for using darks */
  Grp *igrp = NULL;          /* Group of input files */
  smfGroup *igroup=NULL;     /* smfGroup corresponding to igrp */
  size_t isize;              /* Number of files in input group */
  dim_t maxconcat=0;         /* Longest continuous chunk length in samples */
  double maxlen;             /* Constrain maxconcat to this many seconds */
  size_t ncontchunks=0;      /* Number continuous chunks outside iter loop */
  Grp *ogrp = NULL;          /* Output files  */
  size_t osize;              /* Number of files in input group */
  dim_t padStart=0;          /* How many samples padding at start */
  dim_t padEnd=0;            /* How many samples padding at end */
  int temp;                  /* Temporary signed integer */
  ThrWorkForce *wf = NULL;   /* Pointer to a pool of worker threads */

  if (*status != SAI__OK) return;

  /* Main routine */
  ndfBegin();

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

  /* Read the input file */
  kpg1Rgndf( "IN", 0, 1, "", &igrp, &isize, status );

  /* Filter out darks */
  smf_find_science( igrp, &fgrp, 1, NULL, NULL, 1, 1, SMF__NULL, &darks,
                    &flatramps, &heateffmap, NULL, status );

  /* input group is now the filtered group so we can use that and
     free the old input group */
  isize = grpGrpsz( fgrp, status );
  grpDelet( &igrp, status);
  igrp = fgrp;
  fgrp = NULL;

  if (isize == 0) {
    msgOutif(MSG__NORM, " ","All supplied input frames were filtered,"
       " nothing to do", status );
    goto CLEANUP;
  }

  /* --- Parse ADAM parameters ------------------------ */

  /* Maximum length of a continuous chunk */
  parGdr0d( "MAXLEN", 0, 0, VAL__MAXD, 1, &maxlen, status );

  /* Padding */
  parGdr0i( "PADSTART", 0, 0, VAL__MAXI, 1, &temp, status );
  padStart = (dim_t) temp;

  parGdr0i( "PADEND", 0, 0, VAL__MAXI, 1, &temp, status );
  padEnd = (dim_t) temp;

  /* Are we using darks? */
  parGet0l( "USEDARKS", &usedarks, status );

  /* Are we flatfielding? */
  parGet0l( "FLAT", &ensureflat, status );

  /* Group the input files by subarray and continuity */
  smf_grp_related( igrp, isize, 1, 0, maxlen-padStart-padEnd, NULL, NULL,
                   &maxconcat, NULL, &igroup, &basegrp, NULL, status );

  /* Obtain the number of continuous chunks and subarrays */
  if( *status == SAI__OK ) {
    ncontchunks = igroup->chunk[igroup->ngroups-1]+1;
  }

  basesize = grpGrpsz( basegrp, status );

  /* Get output file(s) */
  kpg1Wgndf( "OUT", basegrp, basesize, basesize,
             "More output files required...",
             &ogrp, &osize, status );

  /* Loop over continuous chunks */
  gcount = 1;
  for( contchunk=0;(*status==SAI__OK)&&contchunk<ncontchunks; contchunk++ ) {

    /* Concatenate this continuous chunk */
    smf_concat_smfGroup( wf, NULL, igroup, usedarks ? darks:NULL, NULL, flatramps,
                         heateffmap, contchunk, ensureflat, 1, NULL, 0, NULL, NULL,
                         NO_FTS, padStart, padEnd, 0, &concat, NULL, status );

    /* Export concatenated data for each subarray to NDF file */
    for( idx=0; (*status==SAI__OK)&&idx<concat->ndat; idx++ ) {
      if( concat->sdata[idx]->file && concat->sdata[idx]->file->name ) {
        smf_write_smfData( concat->sdata[idx], NULL, NULL, ogrp, gcount,
                           NDF__NOID, MSG__VERB, 0, status );
      } else {
        *status = SAI__ERROR;
        errRep( FUNC_NAME,
                "Unable to determine file name for concatenated data.",
                status );
      }

      /* Increment the group index counter */
      gcount++;
    }

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

  }

  /* Write out the list of output NDF names, annulling the error if a null
     parameter value is supplied. */
  if( *status == SAI__OK && ogrp ) {
    grpList( "OUTFILES", 0, 0, NULL, ogrp, status );
    if( *status == PAR__NULL ) errAnnul( status );
  }

 CLEANUP:
  if( darks ) smf_close_related( &darks, status );
  if( flatramps ) smf_close_related( &flatramps, status );
  if (heateffmap) heateffmap = smf_free_effmap( heateffmap, status );
  if( igrp ) grpDelet( &igrp, status);
  if( basegrp ) grpDelet( &basegrp, status );
  if( ogrp ) grpDelet( &ogrp, status );
  if( igroup ) smf_close_smfGroup( &igroup, status );

  ndfEnd( status );

  if( *status == SAI__OK ) {
    msgOutif(MSG__VERB," ","SC2CONCAT succeeded.", status);
  } else {
    msgOutif(MSG__VERB," ","SC2CONCAT failed.", status);
  }

}
Ejemplo n.º 3
0
void
smf_flat_params( const smfData * refdata, const char resistpar[],
                 const char methpar[], const char orderpar[], const char snrminpar[],
                 double * refohms, double **resistance, int * outrows,
                 int * outcols, smf_flatmeth  *flatmeth,
                 int * order, double * snrmin, smfData ** heateff,
                 int * status ) {

  dim_t datarows = 0;       /* Number of rows in refdata */
  dim_t datacols = 0;       /* Number of columns in refdata */
  size_t j = 0;             /* Counter, index */
  char method[SC2STORE_FLATLEN]; /* flatfield method string */
  size_t nbols;              /* Number of bolometers */
  double refohmsval = 0.0;   /* Internal version of refohms */
  AstKeyMap * resmap = NULL; /* Resistor map */
  AstKeyMap * subarrays = NULL; /* Subarray lookup table */
  char thissub[32];          /* This sub-instrument string */

  if (resistance) *resistance = NULL;

  if (*status != SAI__OK) return;

  if (!refdata) {
    *status = SAI__ERROR;
    errRep( "", "Must provide reference data file to calculate flatfield parameters"
            " (possible programming error)", status );
    return;
  }

  /* Based on refdata we now need to calculate the default reference
     resistance and retrieve the correct heater efficiency file for each array.
     We need the unique subarray string so that we can set up a look up keymap.
     There is no code in SMURF to return all the known subarrays but
     we need to know all the options in order to use kpg1Config. */
  subarrays = astKeyMap( " " );
  astMapPut0I( subarrays, "CG450MK2_M0907D0501", 0, NULL );
  astMapPut0I( subarrays, "CG850MK2_M0904D0503", 0, NULL );
  astMapPut0I( subarrays, "SG850_M0906D1005", 0, NULL );
  astMapPut0I( subarrays, "SG850_M1002D1006", 0, NULL );
  astMapPut0I( subarrays, "SG850_M1005D1007", 0, NULL );
  astMapPut0I( subarrays, "SG850_M1003D1004", 0, NULL );
  astMapPut0I( subarrays, "SG450_M1004D1000", 0, NULL );
  astMapPut0I( subarrays, "SG450_M1007D1002", 0, NULL );
  astMapPut0I( subarrays, "SG450_M1006D1003", 0, NULL );
  astMapPut0I( subarrays, "SG450_M1009D1008", 0, NULL );

  /* and indicate which subarray we are interested in (uppercased) */
  smf_fits_getS( refdata->hdr, "ARRAYID", thissub, sizeof(thissub), status );
  { /* need to uppercase */
    size_t l = strlen(thissub);
    for (j=0;j<l;j++) {
      thissub[j] = toupper(thissub[j]);
    }
  }
  astMapPut0I( subarrays, thissub, 1, NULL );

  /* Read the config file */
  resmap = kpg1Config( resistpar, "$SMURF_DIR/smurf_calcflat.def",
                       subarrays, 1, status );
  subarrays = astAnnul( subarrays );

  if (*status != SAI__OK) goto CLEANUP;

  /* Read the reference resistance */
  astMapGet0D( resmap, "REFRES", &refohmsval );

  if (refohms && *status == SAI__OK) {
    *refohms = refohmsval;
    msgOutiff(MSG__VERB, "",
              "Read reference resistance for subarray %s of %g ohms\n",
              status, thissub, *refohms );
  }

  /* We no longer want to read per-bolometer resistor values from the
     config file. To retain backwards compatibility with the current
     implementation of smf_flat_standardpow we simply fill the
     per-bol resistance array with the reference resistance which
     effectively disables smf_flat_standardpow */

  smf_get_dims( refdata, &datarows, &datacols, NULL, NULL, NULL, NULL, NULL, status );
  nbols = datacols * datarows;

  if (*status == SAI__OK && resistance ) {
    *resistance = astMalloc( nbols*sizeof(**resistance) );
    for (j = 0; j < (size_t)nbols; j++) {
      (*resistance)[j] = refohmsval;
    }
  }

  /* Get the heater efficiency file */
  if (heateff && astMapHasKey( resmap, "HEATEFF" ) ) {
    const char * heateffstr = NULL;
    if (astMapGet0C( resmap, "HEATEFF", &heateffstr )) {
      Grp * heateffgrp = NULL;
      smfData * heatefftmp = NULL;
      heateffgrp = grpNew( "heateff", status );
      grpPut1( heateffgrp, heateffstr, 0, status );
      smf_open_file( NULL, heateffgrp, 1, "READ", SMF__NOTTSERIES|SMF__NOFIX_METADATA, &heatefftmp, status );

      /* Divorce the smfData from the underlying file. This file stays open for the entire
         duration of the data processing and can some times lead to issues when we attempt
         to close it an hour after we opened it (it's usually on an NFS disk) */
      if (*status == SAI__OK) {
        *heateff = smf_deepcopy_smfData( NULL, heatefftmp, 0,
                                         SMF__NOCREATE_FILE | SMF__NOCREATE_FTS |
                                         SMF__NOCREATE_DA,
                                         0, 0, status );
        smf_close_file(NULL, &heatefftmp, status);
      }

      /* Check the dimensions */
      if (*status == SAI__OK) {
        dim_t heatrows = 0;
        dim_t heatcols = 0;
        smf_get_dims( *heateff, &heatrows, &heatcols, NULL, NULL, NULL, NULL, NULL, status );

        if (*status == SAI__OK) {
          if ( datarows != heatrows || datacols != heatcols ) {
            *status = SAI__ERROR;
            errRepf( "", "Dimensions of heater efficiency file %s are (%zu, %zu)"
                     " but flatfield has dimensions (%zu, %zu)",
                     status, heateffstr, (size_t)heatrows, (size_t)heatcols,
                     (size_t)datarows, (size_t)datacols);
          }
        }

        if (*status == SAI__OK) {
          smf_dtype_check_fatal( *heateff, NULL, SMF__DOUBLE, status );
          if (*status == SMF__BDTYP) {
            errRepf("", "Heater efficiency data in %s should be double precision",
                   status, heateffstr);
          }
        }

        if (*status == SAI__OK) {
          char heateffarrid[32];
          smf_fits_getS( refdata->hdr, "ARRAYID", heateffarrid, sizeof(heateffarrid), status );
          if (*status != SAI__OK) errAnnul( status );
          if (strcasecmp( thissub, heateffarrid ) != 0 ) {
            if (*status == SAI__OK) {
              *status = SAI__ERROR;
              errRepf("", "Subarray associated with heater efficiency image (%s)"
                     " does not match that of the data to be flatfielded (%s)",
                      status, heateffarrid, thissub );
            }
          }
        }
      }
      if (heateffgrp) grpDelet( &heateffgrp, status );
    }
  }

  if (methpar && flatmeth) {
    /* See if we want to use TABLE or POLYNOMIAL mode */
    parChoic( methpar, "POLYNOMIAL", "POLYNOMIAL, TABLE", 1,
              method, sizeof(method), status );

    *flatmeth = smf_flat_methcode( method, status );

    if (*flatmeth == SMF__FLATMETH_POLY) {
      /* need an order for the polynomial */
      if (order && orderpar) {
        parGdr0i( orderpar, 1, 1, 3, 1, order, status );

        /* and if the order is 1 then we can ask for the snr min */
        if (snrminpar && *order == 1) {
          parGet0d( snrminpar, snrmin, status );
        }
      }

    } else {
      /* need an snr min for table mode responsivities */
      if (snrminpar) parGet0d( snrminpar, snrmin, status );
    }
  }

  if (outrows) *outrows = datarows;
  if (outcols) *outcols = datacols;

 CLEANUP:
  resmap = astAnnul( resmap );
  if (*status != SAI__OK) {
    if (resistance && *resistance) *resistance = astFree( *resistance );
    if (heateff && *heateff) smf_close_file( NULL, heateff, status );
  }

  return;

}
Ejemplo n.º 4
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);
   }
}
Ejemplo n.º 5
0
void smurf_sc2threadtest( int *status ) {

  /* Local Variables */
  smfArray **res=NULL;       /* array of smfArrays of test data */
  smfData *data=NULL;        /* Pointer to SCUBA2 data struct */
  dim_t datalen;             /* Number of data points */
  smfFilter *filt=NULL;      /* Frequency domain filter */
  size_t i;                  /* Loop counter */
  size_t j;                  /* Loop counter */
  smfTimeChunkData *job_data=NULL; /* Array of pointers for job data */
  size_t joblen;             /* Number of chunks per job */
  size_t k;                  /* Loop counter */
  size_t nchunks;            /* Number of chunks */
  size_t nsub;               /* Number of subarrays */
  int nthread;               /* Number of threads */
  smfTimeChunkData *pdata=NULL; /* Pointer to data for single job */
  int temp;                  /* Temporary integer */
  size_t tsteps;             /* How many time steps in chunk */
  struct timeval tv1, tv2;   /* Timers */
  ThrWorkForce *wf = NULL;   /* Pointer to a pool of worker threads */

  double *dat=NULL;
  dim_t nbolo;
  dim_t ntslice;
  dim_t ndata;
  size_t bstride;
  size_t tstride;
  dim_t offset;

  if (*status != SAI__OK) return;

  /* Get input parameters */
  parGdr0i( "NTHREAD", 1, 1, NUM__MAXI, 1, &nthread, status );
  parGdr0i( "TSTEPS", 6000, 0, NUM__MAXI, 1, &temp, status );
  tsteps = (size_t) temp;
  parGdr0i( "NCHUNKS", 1, 1, NUM__MAXI, 1, &temp, status );
  nchunks = (size_t) temp;
  parGdr0i( "NSUB", 1, 1, 4, 1, &temp, status );
  nsub = (size_t) temp;

  msgSeti("N",nthread);
  msgOut( "", TASK_NAME ": Running test with ^N threads", status );

  /*** TIMER ***/
  smf_timerinit( &tv1, &tv2, status );

  /* Create some fake test data in the form of an array of smfArrays */

  msgSeti("T",tsteps);
  msgSeti("C",nchunks);
  msgSeti("NS",nsub);
  msgOut( "", TASK_NAME
          ": Creating ^NS subarrays of data with ^C chunks * ^T samples",
          status );

  res = astCalloc( nchunks, sizeof(*res) );

  for( k=0; (*status==SAI__OK)&&(k<nchunks); k++ ) {

    res[k] = smf_create_smfArray( status );

    for( i=0; (*status==SAI__OK)&&(i<nsub); i++ ) {
      /* Create individual smfDatas and add to array */
      data = smf_create_smfData( SMF__NOCREATE_FILE |
                                 SMF__NOCREATE_DA |
                                 SMF__NOCREATE_FTS, status );

      if( *status==SAI__OK ) {
        data->dtype=SMF__DOUBLE;
        data->ndims=3;
        data->dims[0]=40;
        data->dims[1]=32;
        data->dims[2]=(dim_t) tsteps;
        datalen=1;
        data->isFFT=-1;
        for( j=0; j<data->ndims; j++ ) datalen *= data->dims[j];

        data->hdr->steptime = 0.005;

        data->pntr[0] = astCalloc( datalen, smf_dtype_sz(data->dtype,status) );
        data->qual = astCalloc( datalen, sizeof(*data->qual) );
      }

      smf_addto_smfArray( res[k], data, status );
    }
  }

  /*** TIMER ***/
  msgOutf( "", "** %f seconds generating data", status,
           smf_timerupdate(&tv1,&tv2,status) );

  msgOut( "", TASK_NAME
          ": Starting test 1 __parallel time: dataOrder__", status );

  /* Create a pool of threads. */
  wf = thrGetWorkforce( nthread, status );

  /* Work out number of chunks per thread */
  joblen = nchunks/nthread;
  if( joblen == 0 ) joblen = 1; /* At least one chunk per thread */

  /* The first test will process separate time chunks of data in
     parallel, re-ordering each to bolo-ordered format. All subarrays
     and an integer number of input file chunks all go into a single
     thread. Start by allocating and initializing a number of
     smfTimeChunkData's that hold the information required for each
     thread */

  job_data = astCalloc( nthread, sizeof(*job_data) );

  for( i=0; (i<(size_t)nthread) && (*status==SAI__OK); i++ ) {
    pdata = job_data + i;

    pdata->type = 0;                /* Start with a data re-order */
    pdata->data = res;              /* Pointer to main data array */
    pdata->chunk1 = i*joblen;       /* Index of first chunk for job */
    pdata->nchunks = nchunks;       /* Total number of time chunks in data */
    pdata->ijob = -1;               /* Flag job as available to do work */

    /* The last thread has to pick up the remainder of chunks */
    if( i==(size_t)(nthread-1) ) pdata->chunk2=nchunks-1;
    else pdata->chunk2 = (i+1)*joblen-1; /* Index of last chunk for job */

    /* Ensure a valid chunk range, or set to a length that we know to ignore */
    if( pdata->chunk1 >= nchunks ) {
      pdata->chunk1 = nchunks;
      pdata->chunk2 = nchunks;
    } else if( pdata->chunk2 >= nchunks ) {
      pdata->chunk2 = nchunks-1;
    }

    if( pdata->chunk1 >= nchunks ) {
      /* Nothing for this thread to do */
      msgSeti( "W", i+1);
      msgOutif( MSG__DEBUG, "",
                "-- parallel time: skipping thread ^W, nothing to do",
                status);
    } else {
      /* Since we know there is one job_data per thread, just submit jobs
         immediately */
      pdata->ijob = thrAddJob( wf, THR__REPORT_JOB, pdata, smfParallelTime,
                                 0, NULL, status );
    }
  }

  /* Wait until all of the submitted jobs have completed */
  thrWait( wf, status );

  /* Annul the bad status that we set in smfParallelTime */
  if( *status == SMF__INSMP ) {
    errAnnul( status );
    msgOut( "", " *** Annulled SMF__INSMP set in smfParallelTime *** ",
            status );
  } else {
    msgOut( "", " *** Flushing good status *** ", status );
    errFlush( status );
  }

  /*** TIMER ***/
  msgOutf( "", "** %f seconds to complete test", status,
           smf_timerupdate(&tv1,&tv2,status) );

  /* The second test will boxcar smooth bolometers from time chunks in
     parallel */

  msgOut( "", TASK_NAME
          ": Starting test 2 __parallel time: boxcar smooth__", status );

  for( i=0; (i<(size_t)nthread) && (*status==SAI__OK); i++ ) {
    pdata = job_data + i;

    pdata->type = 1;                /* Boxcar smooth */

    if( pdata->chunk1 >= nchunks ) {
      /* Nothing for this thread to do */
      msgSeti( "W", i+1);
      msgOutif( MSG__DEBUG, "",
                "-- parallel time: skipping thread ^W, nothing to do",
                status);
    } else {
      /* Since we know there is one job_data per thread, just submit jobs
         immediately */
      pdata->ijob = thrAddJob( wf, THR__REPORT_JOB, pdata, smfParallelTime,
                                 0, NULL, status );
    }
  }

  /* Wait until all of the submitted jobs have completed */
  thrWait( wf, status );

  /*** TIMER ***/
  msgOutf( "", "** %f seconds to complete test", status,
           smf_timerupdate(&tv1,&tv2,status) );

  msgOut( "", TASK_NAME
          ": *** Next 2 tests will be done twice due to FFTW planning *****",
          status );

  for( k=0; k<2; k++ ) {

    /* The third test will FFT filter bolometers from time chunks in
       parallel */

    msgOut( "", TASK_NAME
            ": Starting test 3 __parallel time: FFT filter__", status );

    for( i=0; (i<(size_t)nthread) && (*status==SAI__OK); i++ ) {
      pdata = job_data + i;

      pdata->type = 2;                /* FFT filter */

      if( pdata->chunk1 >= nchunks ) {
        /* Nothing for this thread to do */
        msgSeti( "W", i+1);
        msgOutif( MSG__DEBUG, "",
                  "-- parallel time: skipping thread ^W, nothing to do",
                  status);
      } else {
        /* Since we know there is one job_data per thread, just submit jobs
           immediately */
        pdata->ijob = thrAddJob( wf, THR__REPORT_JOB, pdata, smfParallelTime,
                                 0, NULL, status );
      }
    }

    /* Wait until all of the submitted jobs have completed */
    thrWait( wf, status );

    /*** TIMER ***/
    msgOutf( "", "** %f seconds to complete test", status,
             smf_timerupdate(&tv1,&tv2,status) );

    msgOut( "", TASK_NAME
            ": Starting test 4 __FFTW filter using internal threading__",
            status );

    for( i=0; (*status==SAI__OK)&&(i<nchunks); i++ ) {
      filt = smf_create_smfFilter( res[i]->sdata[0], status );
      smf_filter_ident( filt, 1, status );

      for( j=0; (*status==SAI__OK)&&(j<nsub); j++ ) {
        msgOutiff( MSG__DEBUG, "", "  filter chunk %zu/%zu, bolo %zu/%zu",
                   status, i+1, nchunks, j+1, nsub );
        smf_filter_execute( wf, res[i]->sdata[j], filt, 0, 0, status );
      }

      if( filt ) filt = smf_free_smfFilter( filt, status );
    }
    /*** TIMER ***/
    msgOutf( "", "** %f seconds to complete test", status,
             smf_timerupdate(&tv1,&tv2,status) );
  }

  msgOut( "", TASK_NAME
          ": **************************************************************",
          status );

  /* Series of short single-thread array index tests */
  data = res[0]->sdata[0];
  dat = data->pntr[0];

  smf_get_dims( data, NULL, NULL, &nbolo, &ntslice, &ndata, &bstride,
                &tstride, status );

  msgOut("","Array index test #1: two multiplies in inner loop",status);
  smf_timerinit( &tv1, &tv2, status );
  for( i=0; i<nbolo; i++ ) {
    for( j=0; j<ntslice; j++ ) {
      dat[i*bstride + j*tstride] += 5;
    }
  }
  msgOutf( "", "** %f seconds to complete test", status,
           smf_timerupdate(&tv1,&tv2,status) );

  msgOut("","Array index test #2: only index increments",status);
  smf_timerinit( &tv1, &tv2, status );
  for( i=0; i<nbolo*bstride; i+=bstride ) {
    for( j=i; j<(i+ntslice*tstride); j+=tstride ) {
      dat[j] += 5;
    }
  }
  msgOutf( "", "** %f seconds to complete test", status,
           smf_timerupdate(&tv1,&tv2,status) );

  msgOut("","Array index test #3: one multiply in outer loop",status);
  smf_timerinit( &tv1, &tv2, status );
  offset = 0;
  for( i=0; i<nbolo; i++ ) {
    offset = i*bstride;
    for( j=0; j<ntslice; j++ ) {
      dat[offset] += 5;
      offset += tstride;
    }
  }
  msgOutf( "", "** %f seconds to complete test", status,
           smf_timerupdate(&tv1,&tv2,status) );

  /* Clean up */
  if( res ) {
    for( i=0; i<nchunks; i++ ) {
      if( res[i] ) {
        smf_close_related( &res[i], status );
      }
    }
    res = astFree( res );
  }
  job_data = astFree( job_data );

  /* Ensure that FFTW doesn't have any used memory kicking around */
  fftw_cleanup();

}
Ejemplo n.º 6
0
void smurf_smurfcopy ( int * status ) {

  smfData * data = NULL;     /* input file struct */
  size_t dtypsz;             /* Number of bytes in data type */
  Grp *fgrp = NULL;          /* Filtered group, no darks */
  size_t i;                  /* Loop counter */
  smfFile * ifile = NULL;    /* Input smfFile */
  Grp *igrp = NULL;          /* Input group */
  unsigned char * inptr = NULL; /* Pointer to start of section to copy */
  int islice;                /* int time slice from parameter */
  int lbnd[2];               /* Lower coordinate bounds of output file */
  size_t nelem;              /* Number of elements to copy */
  smfData * odata = NULL;    /* output file struct */
  size_t offset;             /* offset into data array */
  smfFile * ofile = NULL;    /* output smfFile */
  Grp *ogrp = NULL;          /* Output group */
  size_t outsize;            /* Total number of NDF names in the output group */
  dim_t slice;               /* Time index to extract */
  size_t size;               /* Number of files in input group */
  int ubnd[2];               /* Upper coordinate bounds of output file */

  if (*status != SAI__OK) return;

  ndfBegin();

  /* Read the input file */
  /* As a proof of concept do not allow multiple input files */
  kpg1Rgndf( "IN", 1, 1, "", &igrp, &size, status );

  /* Filter out darks */
  smf_find_science( igrp, &fgrp, 1, NULL, NULL, 0, 0, SMF__NULL, NULL, NULL,
                    NULL, NULL, status );

  /* input group is now the filtered group so we can use that and
     free the old input group */
  size = grpGrpsz( fgrp, status );
  grpDelet( &igrp, status);
  igrp = fgrp;
  fgrp = NULL;

  if (size > 0) {
  /* Get output file(s) */
  kpg1Wgndf( "OUT", igrp, size, size, "More output files required...",
             &ogrp, &outsize, status );
  } else {
    msgOutif(MSG__NORM, " ","All supplied input frames were DARK,"
       " nothing to extract", status );
  }

  /* Allow the user to specify a text file containing a table of pointing
     corrections. Corresponding Mappings are created form the column data
     in this table and stored in the "igrp" group as items of metadata. */
  smf_pread( igrp, "POINTING", status );

  /* Use a loop so that we look like other routines and simplify
     the change if we support multiple input files */
  for (i=1; i<=size; i++) {

    /* Open the input file using standard routine */
    smf_open_and_flatfield( igrp, NULL, i, NULL, NULL, NULL, &data, status );
    if (*status != SAI__OK) break;

    if (*status == SAI__OK) {
      if (!data->file->isTstream  || data->ndims != 3) {
        smf_close_file( &data, status );
        *status = SAI__ERROR;
        errRep(" ", "Input data do not represent time series", status);
        break;
      }
    }

    /* get the slice position - knowing the maximum allowed
       Somewhat problematic in a loop if we want to allow
       different slices per file. Best bet is to allow multiple
       slices in a single file but only one file.
     */

    msgSeti( "MAX", (data->dims)[2] );
    msgOutif( MSG__NORM, " ", "File has ^MAX slices.", status );

    parGdr0i( "SLICE",1, 0, (data->dims)[2], 1, &islice, status);
    slice = islice;
    if (slice == 0) slice = (data->dims)[2];

    /* construct output bounds */
    lbnd[0] = (data->lbnd)[0];
    lbnd[1] = (data->lbnd)[1];
    ubnd[0] = lbnd[0] + (data->dims)[0] - 1;
    ubnd[1] = lbnd[1] + (data->dims)[1] - 1;

    /* Open an output file (losing history) but we do not want
       to propagate the full NDF size to the output file */

    smf_open_newfile( ogrp, i, data->dtype, 2, lbnd, ubnd, 0,
                      &odata, status );
    ofile = odata->file;
    ifile = data->file;

    /* protect against null pointer smfFile */
    if (*status == SAI__OK) {

      /* sort out provenance */
      smf_accumulate_prov( data, igrp, i, ofile->ndfid,
                           "SMURF:SMURFCOPY", NULL, status );

      /* copy the slice in */
      dtypsz = smf_dtype_size( odata, status );
      nelem = (data->dims)[0] * (data->dims)[1];
      offset = (slice - 1) * nelem * dtypsz;
      inptr = (data->pntr)[0];
      memcpy( (odata->pntr)[0], inptr + offset, nelem * dtypsz );

      /* World coordinates - note the 0 indexing relative to GRID */
      smf_tslice_ast( data, slice-1, 1, status );
      ndfPtwcs( data->hdr->wcs, ofile->ndfid, status );

      /* Write the FITS header */
      kpgPtfts( ofile->ndfid, data->hdr->fitshdr, status );

      /* JCMTSTATE */
      sc2store_writejcmtstate( ofile->ndfid, 1, &((data->hdr->allState)[slice-1]),
                               status );

    }

    /* cleanup */
    smf_close_file( &data, status );
    smf_close_file( &odata, status );

  }

  /* tidy */
  if (igrp) {
    smf_pread( igrp, NULL, status );
    grpDelet( &igrp, status );
  }
  if (ogrp) grpDelet( &ogrp, status );

  ndfEnd(status);

}