コード例 #1
0
ファイル: smf_find_science.c プロジェクト: andrecut/starlink
static void smf__calc_flatobskey( smfHead *hdr, char * keystr, size_t keylen,
                                  int *status ) {

  int curheat = 0;
  int detbias = 0;
  char subarray[10];
  double shutter = 0.0;
  size_t nwrite = 0;
  int utdate = 0;

  if (*status != SAI__OK) return;
  if (!hdr) return;

  /* get reference heater value, bias, shutter and subarray string */
  /* PIXHEAT and DETBIAS are not written by the simulator so we default
     those to 0 */
  smf_getfitsi( hdr, "PIXHEAT", &curheat, status );
  if (*status == SMF__NOKWRD) errAnnul(status);

  /* As of September 1st we heater track after doing the flat ramp.
     This means that the heater value will have changed slightly between
     ramp and science. */
  smf_getfitsi( hdr, "UTDATE", &utdate, status );
  if (utdate >= 20110901 &&
      (hdr->obstype == SMF__TYP_SCIENCE || hdr->obstype == SMF__TYP_POINTING)) {
    curheat = 0;
  }

  smf_getfitsi( hdr, "DETBIAS", &detbias, status );
  if (*status == SMF__NOKWRD) errAnnul(status);

  smf_getfitsd( hdr, "SHUTTER", &shutter, status );
  smf_find_subarray( hdr, subarray, sizeof(subarray), NULL,
                     status );
  if (*status != SAI__OK) return;

  nwrite = snprintf(keystr, keylen, "%s_%s_%.1f_%d_%d",
                    hdr->obsidss, subarray, shutter, detbias, curheat );

  if (nwrite >= keylen) {
    /* The string was truncated */
    *status = SMF__STRUN;
    errRep("", "String truncation forming flatfield key (Possible programming error)",
           status );
  }

}
コード例 #2
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);
    }
}
コード例 #3
0
ファイル: smf_subip.c プロジェクト: edwardchapin/starlink
void smf_subip(  ThrWorkForce *wf, smfArray *res, smfArray *lut, int *lbnd_out,
                 int *ubnd_out, AstKeyMap *keymap, AstFrameSet *outfs, int *status ) {

/* Local Variables: */
   HDSLoc *loc = NULL;
   HDSLoc *sloc = NULL;
   SmfSubIPData *job_data = NULL;
   SmfSubIPData *pdata;
   char ipref[200];
   char subname[10];
   const char *ipdata;
   const char *qu;
   dim_t bolostep;
   dim_t nbolo;
   dim_t ntslice;
   double *angcdata;
   double *c0data;
   double *imapdata;
   double *ipang;
   double *p0data;
   double *p1data;
   int angcndf;
   int c0ndf;
   int imapndf;
   int iw;
   int nmap;
   int nw;
   int p0ndf;
   int p1ndf;
   size_t bstride;
   size_t idx;
   size_t tstride;
   smfData *data;
   smf_qual_t *qua_data;

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

/* Check if we have pol2 data, and see if it is Q or U. */
   qu = NULL;
   for( idx = 0; idx < res->ndat; idx++ ) {
      data = res->sdata[idx];

      if( !strcmp( data->hdr->dlabel, "Q" ) ){
         if( !qu ) {
            qu = "Q";
         } else if( strcmp( qu, "Q" ) ) {
            *status = SAI__ERROR;
            break;
         }

      } else if( !strcmp( data->hdr->dlabel, "U" ) ) {
         if( !qu ) {
            qu = "U";
         } else if( strcmp( qu, "U" ) ) {
            *status = SAI__ERROR;
            break;
         }

      } else if( qu ) {
         *status = SAI__ERROR;
         qu = NULL;
         break;
      }
   }

/* Report an error if there is a mix of pol2 and non-pol2, or a mix of Q
   and U. */
   if( *status != SAI__OK ) {
      if( qu ) {
         errRep( "", "smf_subip: Input data contains mix of Q and U "
                 "data", status );
      } else {
         errRep( "", "smf_subip: Input data contains mix of POL2 and "
                 "non-POL2 data", status );
      }

/* If we have pol2 data, get the path to the total intensity image that
   is to be used to define the level of IP correction required. If no
   value is supplied, annul the error and set "qu" NULL to indicate we should
   leave immediately. */
   } else if( qu && *status == SAI__OK ) {
      parGet0c( "IPREF", ipref, sizeof(ipref), status );
      if( *status == PAR__NULL ) {
         errAnnul( status );
         qu = NULL;
      }
   }

/* If we are applying IP correction... */
   if( qu && *status == SAI__OK ) {
      msgOutf( "", "smf_subip: applying instrumental polarisation %s "
               "correction based on total intensity map `%s'", status,
               qu, ipref );

/* Get an identifier for the IPREF NDF. */
      ndfFind( NULL, ipref, &imapndf, status );

/* Resample the NDFs data values onto the output map grid. */
      imapdata = smf_alignndf( imapndf, outfs, lbnd_out, ubnd_out,
                               status );

/* Annul the NDF identifier. */
      ndfAnnul( &imapndf, status );

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

/* Get the path to the container file holding the IP model parameters. */
      ipdata = "$STARLINK_DIR/share/smurf/ipdata.sdf";
      astMapGet0C( keymap, "IPDATA", &ipdata );

/* Open the container file. */
      hdsOpen( ipdata, "READ", &loc, status );

/* Do the IP correction for each subarray (s8a, s8b, etc) in turn. */
      for( idx = 0; idx < res->ndat && *status == SAI__OK; idx++ ) {
         data = res->sdata[idx];

/* Get an array holding the angle (rad.s) from north to focal plane Y,
   measured positive in the sense of rotation from focal plane Y to focal
   plane X, for every bolometer sample in the smfData. The values are bolo
   ordered so that "bstride" is 1 and "tstsride" is nbolo. */
         ipang = smf1_calcang( data, status );

/* Get the number of bolometers and time slices for the current subarray,
   together with the strides between adjacent bolometers and adjacent
   time slices. */
         smf_get_dims( data,  NULL, NULL, &nbolo, &ntslice, NULL, &bstride,
                       &tstride, status );

/* Get a locator for the structure holding the IP parameters for the
   current subarray */
         smf_find_subarray( data->hdr, subname, sizeof( subname ), NULL,
                            status );
         datFind( loc, subname, &sloc, status );

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

/* Get identifiers for the NDFs holding the individual parameters. Each
   NDF holds a parameter value for each bolometer. */
         ndfFind( sloc, "P0", &p0ndf, status );
         ndfFind( sloc, "P1", &p1ndf, status );
         ndfFind( sloc, "C0", &c0ndf, status );
         ndfFind( sloc, "ANGC", &angcndf, status );

/* Map them. Check each one has the expected number of elements. */
         ndfMap( p0ndf, "DATA", "_DOUBLE", "READ", (void **) &p0data,
                 &nmap, status );
         if( nmap != (int) nbolo && *status == SAI__OK ) {
            *status = SAI__ERROR;
            ndfMsg( "N", p0ndf );
            errRep( "", "smf_subip: Bad dimensions for ^N - should be 32x40.", status );
         }

         ndfMap( p1ndf, "DATA", "_DOUBLE", "READ", (void **) &p1data,
                 &nmap, status );
         if( nmap != (int) nbolo && *status == SAI__OK ) {
            *status = SAI__ERROR;
            ndfMsg( "N", p1ndf );
            errRep( "", "smf_subip: Bad dimensions for ^N - should be 32x40.", status );
         }

         ndfMap( c0ndf, "DATA", "_DOUBLE", "READ", (void **) &c0data,
                 &nmap, status );
         if( nmap != (int) nbolo && *status == SAI__OK ) {
            *status = SAI__ERROR;
            ndfMsg( "N", c0ndf );
            errRep( "", "smf_subip: Bad dimensions for ^N - should be 32x40.", status );
         }

         ndfMap( angcndf, "DATA", "_DOUBLE", "READ", (void **) &angcdata,
                 &nmap, status );
         if( nmap != (int) nbolo && *status == SAI__OK ) {
            *status = SAI__ERROR;
            ndfMsg( "N", angcndf );
            errRep( "", "smf_subip: Bad dimensions for ^N - should be 32x40.", status );
         }

/* Get a pointer to the quality array for the residuals. */
         qua_data = smf_select_qualpntr( data, NULL, status );

/* See how many bolometers to process in each thread. */
         bolostep = nbolo/nw;
         if( bolostep == 0 ) bolostep = 1;

/* Create jobs to apply the IP correction to a range of bolometers. */
         for( iw = 0; iw < nw; iw++ ) {
            pdata = job_data + iw;

/* Set the range of bolometers (b1 to b2) to be processed by the current
   job. */
            pdata->b1 = iw*bolostep;
            if( iw < nw - 1 ) {
               pdata->b2 = pdata->b1 + bolostep - 1;
            } else {
               pdata->b2 = nbolo - 1 ;
            }

/* Store the other info needed by the worker thread. */
            pdata->ntslice = ntslice;
            pdata->nbolo = nbolo;
            pdata->res_data = res->sdata[idx]->pntr[0];
            pdata->lut_data = lut->sdata[idx]->pntr[0];
            pdata->qua_data = qua_data;
            pdata->ipang = ipang;
            pdata->bstride = bstride;
            pdata->tstride = tstride;
            pdata->imapdata = imapdata;
            pdata->qu = qu;
            pdata->p0data = p0data;
            pdata->p1data = p1data;
            pdata->c0data = c0data;
            pdata->angcdata = angcdata;
            pdata->allstate = data->hdr->allState;

/* Submit the job for execution by the next available thread. */
            thrAddJob( wf, 0, pdata, smf1_subip, 0, NULL, status );
         }

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

/* End the NDF context, thus unmapping and freeing all NDF identifiers
   created since the context was started. */
         ndfEnd( status );

/* Free locator for subarray IP parameters. */
         datAnnul( &sloc, status );
         ipang = astFree( ipang );
      }

/* Free resources. */
      datAnnul( &loc, status );
      imapdata = astFree( imapdata );
      job_data = astFree( job_data );
   }
}
コード例 #4
0
ファイル: smf_subip.c プロジェクト: edwardchapin/starlink
/* Returns an array holding the angle (rad.s) from north to focal plane Y,
   measured positive in the sense of rotation from focal plane Y to focal
   plane X, for every bolometer sample in a smfData. The values are bolo
   ordered so that "bstride" is 1 and "tstsride" is nbolo. The returned
   array should be freed using astFre when no longer needed. */
static double *smf1_calcang( smfData *data, int *status ){

/* Local Variables: */
   AstFrameSet *fpfset;
   AstFrameSet *wcs;
   AstMapping *g2s;
   AstMapping *s2f;
   const char *usesys;
   dim_t ibolo;
   dim_t itime;
   dim_t nbolo;
   dim_t ncol;
   dim_t ntslice;
   double *fx2;
   double *fx;
   double *fy2;
   double *fy;
   double *gx;
   double *gy;
   double *pr;
   double *result;
   double *sx;
   double *sy;
   int subsysnum;

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

/* Get the number of bolometers and time slices, together with the strides
   between adjacent bolometers and adjacent time slices. */
   smf_get_dims( data,  NULL, &ncol, &nbolo, &ntslice, NULL, NULL, NULL,
                 status );

/* Allocate the returned array. */
   result = astMalloc( nbolo*ntslice*sizeof( *result ) );

/* Allocate arrays to hold the grid coords for every bolometer. */
   gx = astMalloc( nbolo*sizeof( *gx ) );
   gy = astMalloc( nbolo*sizeof( *gy ) );

/* Allocate arrays to hold the sky coords for every bolometer. */
   sx = astMalloc( nbolo*sizeof( *sx ) );
   sy = astMalloc( nbolo*sizeof( *sy ) );

/* Allocate arrays to hold the focal plane coords for every bolometer. */
   fx = astMalloc( nbolo*sizeof( *fx ) );
   fy = astMalloc( nbolo*sizeof( *fy ) );

/* Allocate arrays to hold the focal plane coords of a point slightly to
   the north of every bolometer. */
   fx2 = astMalloc( nbolo*sizeof( *fx2 ) );
   fy2 = astMalloc( nbolo*sizeof( *fy2 ) );

/* Get the AST code equivalent to the tracking system. */
   usesys = sc2ast_convert_system( (data->hdr->allState)[0].tcs_tr_sys, status );
   if( *status == SAI__OK ) {

/* Initialise the arrays holding the grid coords for every bolometer. */
      for( ibolo = 0; ibolo < nbolo; ibolo++ ) {
         gx[ ibolo ] = ibolo % ncol + 1;
         gy[ ibolo ] = ibolo / ncol + 1;
      }

/* Get the GRID->focal plane FrameSet (the same for every time slice). */
      smf_find_subarray( data->hdr, NULL, 0, &subsysnum, status );
      sc2ast_createwcs( subsysnum, NULL, data->hdr->instap, data->hdr->telpos,
                        NO_FTS, &fpfset, status);

/* Use this to transform the bolometrer GRID coords to focal plane. */
      astTran2( fpfset, nbolo, gx, gy, 1, fx, fy );

/* Loop over all time slices. */
      pr = result;
      for( itime = 0; itime < ntslice; itime++ ) {

/* Get the WCS FrameSet for the time slice, and set its current Frame to the tracking
   frame. */
         smf_tslice_ast( data, itime, 1, NO_FTS, status );
         wcs = data->hdr->wcs;
         if( wcs ) {
            astSetC( wcs, "System", usesys );

/* Get the mapping from GRID to SKY. */
            astBegin;
            g2s = astSimplify( astGetMapping( wcs, AST__BASE, AST__CURRENT ));

/* Get the mapping from SKY to focal plane (x,y) (the index of the FPLANE
   Frame is fixed at 3 by file sc2ast.c). */
            s2f = astSimplify( astGetMapping( wcs, AST__CURRENT, 3 ) );

/* Transform the grid coords of all bolometers to SKY coordinates using the FrameSet. */
            astTran2( g2s, nbolo, gx, gy, 1, sx, sy );

/* Increment the sky positions slightly to the north. */
            for( ibolo = 0; ibolo < nbolo; ibolo++ ) sy[ ibolo ] += 1.0E-6;

/* Transform these modified sky coordinates to focal plane. */
            astTran2( s2f, nbolo, sx, sy, 1, fx2, fy2 );
            astEnd;

/* Loop round all bolometers. */
            for( ibolo = 0; ibolo < nbolo; ibolo++ ) {

/* Get the angle from north to focal plane Y, measured positive in the
   sense of rotation from focal plane Y to focal plane X. */
               if(  fx[ibolo] != VAL__BADD &&  fy[ibolo] != VAL__BADD &&
                   fx2[ibolo] != VAL__BADD && fy2[ibolo] != VAL__BADD ) {
                  *(pr++) = atan2( fx[ibolo] - fx2[ibolo], fy2[ibolo] - fy[ibolo] );
               } else {
                  *(pr++) = VAL__BADD;
               }
            }

         } else {
            for( ibolo = 0; ibolo < nbolo; ibolo++ ) *(pr++) = VAL__BADD;
         }
      }
   }

/* Free resources. */
   fx = astFree( fx );
   fy = astFree( fy );
   fx2 = astFree( fx2 );
   fy2 = astFree( fy2 );
   sx = astFree( sx );
   sy = astFree( sy );
   gx = astFree( gx );
   gy = astFree( gy );

/* Return the array of angle values. */
   return result;
}
コード例 #5
0
ファイル: smf_write_bolomap.c プロジェクト: andrecut/starlink
void smf_write_bolomap( ThrWorkForce *wf, smfArray *res, smfArray *lut,
                        smfArray *qua, smfDIMMData *dat, dim_t msize,
                        const Grp *bolrootgrp, int varmapmethod,
                        const int *lbnd_out, const int *ubnd_out,
                        AstFrameSet *outfset, int *status ) {

  int addtomap=0;               /* Set if adding to existing map */
  size_t bstride;               /* Bolometer stride */
  double *curmap=NULL;          /* Pointer to current map being rebinned */
  double *curvar=NULL;          /* Pointer to variance associate with curmap */
  dim_t dsize;                  /* Size of data arrays in containers */
  size_t idx=0;                 /* index within subgroup */
  size_t k;                     /* loop counter */
  int *lut_data=NULL;           /* Pointer to DATA component of lut */
  char name[GRP__SZNAM+1];      /* Buffer for storing names */
  dim_t nbolo;                  /* Number of bolometers */
  size_t nbolomaps = 0;         /* Number of bolomaps written */
  char *pname=NULL;             /* Poiner to name */
  smf_qual_t *qua_data=NULL;    /* Pointer to DATA component of qua */
  double *res_data=NULL;        /* Pointer to DATA component of res */

  if( *status != SAI__OK ) return;

  if( !res || !lut || !qua || !dat || !bolrootgrp ||
      !lbnd_out || !ubnd_out || !outfset ) {
    *status = SAI__ERROR;
    errRep( "", FUNC_NAME ": NULL inputs supplied", status );
    return;
  }

  /* Loop over subgroup index (subarray) */
  for( idx=0; idx<res->ndat; idx++ ) {
    smf_qual_t *bolomask = NULL;
    double *bmapweight = NULL;
    double *bmapweightsq = NULL;
    int *bhitsmap = NULL;

    /* Pointers to everything we need */
    res_data = res->sdata[idx]->pntr[0];
    lut_data = lut->sdata[idx]->pntr[0];
    qua_data = qua->sdata[idx]->pntr[0];

    smf_get_dims( res->sdata[idx], NULL, NULL, &nbolo, NULL,
                  &dsize, &bstride, NULL, status );

    /* Make a copy of the quality at first time slice as a good
       bolo mask, and then set quality to SMF__Q_BADB. Later we
       will unset BADB for one bolo at a time to make individual
       maps. */

    bolomask = astMalloc( nbolo*sizeof(*bolomask) );
    bmapweight = astMalloc( msize*sizeof(*bmapweight) );
    bmapweightsq = astMalloc( msize*sizeof(*bmapweightsq) );
    bhitsmap = astMalloc( msize*sizeof(*bhitsmap) );

    if( *status == SAI__OK ) {
      for( k=0; k<nbolo; k++ ) {
        bolomask[k] = qua_data[k*bstride];
        qua_data[k*bstride] = SMF__Q_BADB;
      }

      /* Identify good bolos in the copied mask and produce a map */
      for( k=0; (k<nbolo)&&(*status==SAI__OK); k++ ) {
        if( !(bolomask[k]&SMF__Q_BADB) ) {
          Grp *mgrp=NULL;       /* Temporary group to hold map names */
          smfData *mapdata=NULL;/* smfData for new map */
          char tmpname[GRP__SZNAM+1]; /* temp name buffer */
          char thisbol[20];     /* name particular to this bolometer */
          size_t col, row;
          char subarray[10];

          nbolomaps++;

          /* Set the quality back to good for this single bolometer */
          qua_data[k*bstride] = bolomask[k];

          /* Create a name for the new map, take into account the
             chunk number and subarray. Only required if we are using a single
             output container. */
          pname = tmpname;
          grpGet( bolrootgrp, 1, 1, &pname, sizeof(tmpname), status );
          one_strlcpy( name, tmpname, sizeof(name), status );
          one_strlcat( name, ".", sizeof(name), status );

          /* Subarray, column and row. HDS does not care about case but we
             convert to upper case anyhow. */
          smf_find_subarray( res->sdata[idx]->hdr, subarray, sizeof(subarray),
                             NULL, status );
          if (*status == SAI__OK) {
            size_t len = strlen(subarray);
            size_t n = 0;
            for (n=0; n<len; n++) {
              subarray[n] = toupper(subarray[n]);
            }
          }

          col = (k % res->sdata[idx]->dims[1])+1;
          row = (k / res->sdata[idx]->dims[1])+1;

          sprintf( thisbol, "%3sC%02zuR%02zu",
                   subarray,
                   col,   /* x-coord */
                   row ); /* y-coord */

          one_strlcat( name, thisbol, sizeof(name), status );
          mgrp = grpNew( "bolomap", status );
          grpPut1( mgrp, name, 0, status );

          msgOutf( "", "*** Writing single bolo map %s", status,
                   name );

          /* Try to open an existing extention first. Create a new map
             array, and then later we'll add it to the existing
             one. If it isn't there, create it. */

          smf_open_file( mgrp, 1, "UPDATE", 0, &mapdata, status );

          if( *status == SAI__OK ) {
            /* Allocate memory for the new rebinned data */
            curmap = astCalloc( msize, sizeof(*curmap) );
            curvar = astCalloc( msize, sizeof(*curvar) );
            addtomap = 1;
          } else if( *status == DAT__NAMIN ) {
            /* Create a new extension */
            errAnnul( status );
            smf_open_newfile ( mgrp, 1, SMF__DOUBLE, 2, lbnd_out,
                               ubnd_out, SMF__MAP_VAR, &mapdata, status);

            /* Rebin directly into the newly mapped space */
            if( *status == SAI__OK ) {
              curmap = mapdata->pntr[0];
              curvar = mapdata->pntr[1];
              addtomap = 0;
            }
          }

          /* Rebin the data for this single bolometer. Don't care
             about variance weighting because all samples from
             same detector are about the same. */

          smf_rebinmap1( wf, res->sdata[idx],
                         dat->noi ? dat->noi[0]->sdata[idx] : NULL,
                         lut_data, 0, 0, 0, NULL, 0,
                         SMF__Q_GOOD, varmapmethod,
                         AST__REBININIT | AST__REBINEND,
                         curmap, bmapweight, bmapweightsq, bhitsmap,
                         curvar, msize, NULL, status );

          /* If required, add this new map to the existing one */
          if( addtomap ) {
            size_t i;
            double *oldmap=NULL;
            double *oldvar=NULL;
            double weight;

            if( *status == SAI__OK ) {

              oldmap = mapdata->pntr[0];
              oldvar = mapdata->pntr[1];

              for( i=0; i<msize; i++ ) {
                if( oldmap[i]==VAL__BADD ) {
                  /* No data in this pixel in the old map, just copy */
                  oldmap[i] = curmap[i];
                  oldvar[i] = curvar[i];
                } else if( curmap[i]!=VAL__BADD &&
                           oldvar[i]!=VAL__BADD && oldvar[i]!=0 &&
                           curvar[i]!=VAL__BADD && curvar[i]!=0 ) {
                  /* Both old and new values available */
                  weight = 1/oldvar[i] + 1/curvar[i];
                  oldmap[i] = (oldmap[i]/oldvar[i] + curmap[i]/curvar[i]) /
                    weight;
                  oldvar[i] = 1/weight;
                }
              }
            }

            /* Free up temporary arrays */
            curmap = astFree( curmap );
            curvar = astFree( curvar );
          }

          /* Write out COLNUM and ROWNUM to FITS header */
          if( *status == SAI__OK ) {
            AstFitsChan *fitschan=NULL;

            fitschan = astFitsChan ( NULL, NULL, " " );

            atlPtfti( fitschan, "COLNUM", col, "bolometer column", status);
            atlPtfti( fitschan, "ROWNUM", row, "bolometer row", status );
            atlPtfts( fitschan, "SUBARRAY", subarray, "Subarray identifier",
                      status );
            kpgPtfts( mapdata->file->ndfid, fitschan, status );

            if( fitschan ) fitschan = astAnnul( fitschan );


            /* Set the bolo to bad quality again */
            qua_data[k*bstride] = SMF__Q_BADB;

            /* Write WCS */
            smf_set_moving(outfset,NULL,status);
            ndfPtwcs( outfset, mapdata->file->ndfid, status );
          }

          /* Clean up */
          if( mgrp ) grpDelet( &mgrp, status );
          if( mapdata ) smf_close_file( &mapdata, status );

        }
      }

      /* Set quality back to its original state */
      for( k=0; k<nbolo; k++ ) {
        qua_data[k*bstride] = bolomask[k];
      }
    }

    /* Free up memory */
    bolomask = astFree( bolomask );
    bmapweight = astFree( bmapweight );
    bmapweightsq = astFree( bmapweightsq );
    bhitsmap = astFree( bhitsmap );
  }

  msgOutf( "", "*** Wrote %zu bolo maps", status, nbolomaps );

}
コード例 #6
0
ファイル: smf_fix_data.c プロジェクト: astrobuff/starlink
int smf_fix_data ( msglev_t msglev, smfData * data, int * status ) {

  int have_fixed = 0;        /* Did we fix anything? */
  smfHead *hdr = NULL;       /* Data header struct */
  size_t i;                  /* Loop counter */
  size_t j;                  /* Loop counter */
  size_t k;                  /* Loop counter */
  size_t l;                  /* Loop counter */
  sc2ast_subarray_t subnum;  /* subarray number */
  int was_fixed = 0;         /* Were these data fixed before? */

  if (*status != SAI__OK) return have_fixed;

  /* Validate arguments - need smfData with smfHead including FITS
     and state */
  smf_validate_smfData( data, 1, 0, status );
  if (*status != SAI__OK) return have_fixed;

  hdr = data->hdr;
  smf_validate_smfHead( hdr, 1, 1, status );
  if (*status != SAI__OK) return have_fixed;

  /* Only works on SCUBA-2 time-series data */
  if( (hdr->instrument != INST__SCUBA2) ||
      (data->ndims != 3) ) {
    return have_fixed;
  }

  /* Need to at least have a DATA component. It might be a good idea
     to check if there is a file associated with the data, and check
     to see whether the caller mapped the DATA, VARIANCE, QUALITY. If
     they only mapped a subset of those, we could generate a warning that
     this routine may be introducing an inconsistency */
  if( !data->pntr[0] ) {
    return have_fixed;
  }

  /* Check to see if a FIXDATA FITS keyword exists -- if so, smf_fix_data
     has already been run on the data and we return. */
  smf_getfitsi( hdr, SMFFIXDATA, &was_fixed, status );
  if( *status == SMF__NOKWRD ) {
    errAnnul( status );
  } else {
    return have_fixed;
  }

  /* Fix the May/June 2011 s4a row readout order error. Check the
     subarray first, then get the MJD for the start of the observation
     to decide if we need to proceed. */

  smf_find_subarray( hdr, NULL, 0, &subnum, status );
  if( (*status == SAI__OK) && (subnum == S4A) ) {
    double dateendfix;       /* UTC MJD end date when fix needed */
    double dateobs;          /* UTC MJD observation start */
    double datestartfix;     /* UTS MJD start date when fix needed */
    AstTimeFrame *tf = NULL; /* time frame for date conversion */

    /* Get the MJD for start of the observation */
    smf_find_dateobs( hdr, &dateobs, NULL, status );

    /* Get the MJD for the first and last dates bracketing the period
       during which the row order fix needs to be done */

    tf = astTimeFrame( " " );
    astSet( tf, "TimeScale=UTC" );

    /* From Mike Macintosh Thu, 7 Jul 2011 15:07:51 +0000:

       "I did a scan of the engineering MCE status files and it looks
       the 'missing' row on s4a originated between 09:30 and 10:30 HST
       on 26 May 2011. I haven't checked in detail whether the
       'missing' row was consistently missing after that date but the
       assumption is that it was."
    */

    astSet( tf, "TimeOrigin=%s", "2011-05-26T19:00:00" );
    datestartfix = astGetD( tf, "TimeOrigin" );

    /* From Dan Bintley Wed, 06 Jul 2011 00:23:18 -1000:

       "I have changed the source code in

       /jac_sw/itsroot/scuba2_src/scuba2Da/setup/SG450_M1004D1000/mce_zero.txt"
    */

    astSet( tf, "TimeOrigin=%s", "2011-07-06T10:23:00" );
    dateendfix = astGetD( tf, "TimeOrigin" );

    tf = astAnnul( tf );

    /* Proceed with fix if within date range */
    if( (*status == SAI__OK) && (dateobs >= datestartfix) &&
        (dateobs <= dateendfix) ) {
      size_t targetbolo;
      size_t sourcebolo;
      size_t bstride;
      dim_t ncols;
      dim_t nrows;
      dim_t ntslice;
      size_t tstride;

      msgOutif( msglev, "", INDENT "Reparing row order readout error", status );

      smf_get_dims( data, &nrows, &ncols, NULL, &ntslice, NULL, &bstride,
                    &tstride, status );

      if( (*status==SAI__OK) && (nrows != 40) ) {
        *status = SAI__ERROR;
        errRep( "", FUNC_NAME ": looks like we need to fix the data, but we "
                "don't have 40 rows.", status );
      }

      /* Rows 0--13 are OK, row 14 was not read out
         (FIXDATA_S4A_MISSROW), so we need to move all of rows 14--38
         up to the range 15--39. After doing the shift, overwrite the
         missing row 14 with 0 (or should this be VAL__BAD? in some
         situations?) */

      if( *status==SAI__OK ) {
        /* Row counter */
        for( i=nrows-1; (*status==SAI__OK)&&(i>=(FIXDATA_S4A_MISSROW+1)); i-- ){
          for( j=0; (*status==SAI__OK)&&(j<ncols); j++ ) {
            smf_qual_t *qual = data->qual;

            /* Calculate the bolo index */
            if( SC2STORE__ROW_INDEX ) {
              /* Fastest changing index is column number */
              sourcebolo = (i-1)*ncols + j;
              targetbolo = i*ncols + j;
            } else {
              /* Fastest changing index is row number */
              sourcebolo = (i-1) + j*nrows;
              targetbolo = i + j*nrows;
            }

            /* Loop for DATA / VARIANCE components */
            for( l=0; (*status==SAI__OK)&&(l<2); l++ ) {
              void *buf = data->pntr[l];

              if( buf ) {
                switch( data->dtype ) {
                case SMF__INTEGER:
                  for( k=0; k<ntslice; k++ ) {
                    ((int *)buf)[targetbolo*bstride + k*tstride] =
                      ((int *)buf)[sourcebolo*bstride + k*tstride];
                  }

                  if( i==(FIXDATA_S4A_MISSROW+1) ) {
                    for( k=0; k<ntslice; k++ ) {
                      ((int *)buf)[sourcebolo*bstride + k*tstride] = 0;
                    }
                  }
                  break;
     
                case SMF__USHORT:
                  for( k=0; k<ntslice; k++ ) {
                    ((unsigned short *)buf)[targetbolo*bstride + k*tstride] =
                      ((unsigned short *)buf)[sourcebolo*bstride + k*tstride];
                  }

                  if( i==(FIXDATA_S4A_MISSROW+1) ) {
                    for( k=0; k<ntslice; k++ ) {
                      ((unsigned short *)buf)[sourcebolo*bstride + k*tstride] =
                        0;
                    }
                  }

                  break;
           
                case SMF__DOUBLE:
                  for( k=0; k<ntslice; k++ ) {
                    ((double *)buf)[targetbolo*bstride + k*tstride] =
                      ((double *)buf)[sourcebolo*bstride + k*tstride];
                  }

                  if( i==(FIXDATA_S4A_MISSROW+1) ) {
                    for( k=0; k<ntslice; k++ ) {
                      ((double *)buf)[sourcebolo*bstride + k*tstride] =
                        0;
                    }
                  }

                  break;

                default:
                  *status = SAI__ERROR;
                  errRepf( "", FUNC_NAME
                           ": Don't know how to handle %s type.", status,
                           smf_dtype_str(data->dtype,status) );
                }
              }
            }

            /* Now do quality: Just set SMF__Q_BADDA for the dead
               row. Not sure if I should do something with sidecar
               quality as well? */
            if( qual ) {
              for( k=0; k<ntslice; k++ ) {
                qual[targetbolo*bstride + k*tstride] =
                  qual[sourcebolo*bstride + k*tstride];
              }
              
              if( i==(FIXDATA_S4A_MISSROW+1) ) {
                for( k=0; k<ntslice; k++ ) {
                  qual[sourcebolo*bstride + k*tstride] = SMF__Q_BADDA;
                }
              }
            }



          }
        }
      }

      /* If we get here and status is OK, set return value */
      if( *status == SAI__OK ) {
        have_fixed |= SMF__FIXED_ROWORDER;
      }
    }
  }

  /* Set FITS header so that we know smf_fix_data was run */
  smf_fits_updateL( hdr, SMFFIXDATA, have_fixed,
                    (have_fixed ? "Data have been fixed" : "Data do not require fixing"),
                    status );

  return have_fixed;
}
コード例 #7
0
void smf_clean_smfArray( ThrWorkForce *wf, smfArray *array,
                         smfArray **noisemaps, smfArray **com, smfArray **gai,
                         AstKeyMap *keymap, int *status ) {

  /* Local Variables */
  double badfrac;           /* Fraction of bad samples to flag bad bolo */
  smfData *data=NULL;       /* Pointer to individual smfData */
  int compreprocess;        /* COMmon-mode cleaning as pre-processing step */
  dim_t dcfitbox;           /* width of box for measuring DC steps */
  int dclimcorr;            /* Min number of correlated steps */
  int dcmaxsteps;           /* number of DC steps/min. to flag bolo bad */
  dim_t dcsmooth;           /* median filter width before finding DC steps */
  double dcthresh;          /* n-sigma threshold for primary DC steps */
  int dofft;                /* are we doing a freq.-domain filter? */
  int dkclean;              /* Flag for dark squid cleaning */
  smfFilter *filt=NULL;     /* Frequency domain filter */
  double flagfast;          /* Threshold for flagging slow slews */
  double flagslow;          /* Threshold for flagging slow slews */
  dim_t idx;                /* Index within subgroup */
  size_t nflag;             /* Number of elements flagged */
  double noisecliphigh = 0; /* Sigma clip high-noise outlier bolos */
  double noisecliplow = 0;  /* Sigma clip low-noise outlier bolos */
  int noiseclipprecom = 0;  /* Noise clipping before common-mode cleaning? */
  const char *opteff=NULL;  /* Pointer to optical efficiency NDF file name*/
  int opteffdiv;            /* Divide data by the optical efficiencies? */
  int order;                /* Order of polynomial for baseline fitting */
  char param[ 20 ];         /* Buffer for config parameter name */
  dim_t pcalen;             /* Chunk length for PCA cleaning */
  double pcathresh;         /* n-sigma threshold for PCA cleaning */
  double spikethresh;       /* Threshold for finding spikes */
  dim_t spikebox=0;         /* Box size for spike finder */
  struct timeval tv1, tv2;  /* Timers */
  int whiten;               /* Apply whitening filter? */
  int zeropad;              /* Pad with zeros? */

  /* Main routine */
  if (*status != SAI__OK) return;

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

  /* Check for valid inputs */

  if( !array || (array->ndat < 1) ) {
    *status = SAI__ERROR;
    errRep( "", FUNC_NAME ": No data supplied", status );
  }

  if( array->sdata[0]->ndims != 3 ) {
    *status = SMF__WDIM;
    errRepf( "", FUNC_NAME ": Supplied smfData has %zu dims, needs 3", status,
             data->ndims );
    return;
  }

  if( !keymap ) {
    *status = SAI__ERROR;
    errRep( "", FUNC_NAME ": NULL AstKeyMap supplied", status );
    return;
  }

  /* Get cleaning parameters */
  smf_get_cleanpar( keymap, array->sdata[0], &badfrac, &dcfitbox, &dcmaxsteps,
                    &dcthresh, &dcsmooth, &dclimcorr, &dkclean,
                    NULL, &zeropad, NULL, NULL, NULL, NULL, NULL,
                    NULL, NULL, NULL, &flagslow, &flagfast, &order,
                    &spikethresh, &spikebox, &noisecliphigh, &noisecliplow,
                    NULL, &compreprocess, &pcalen, &pcathresh, NULL, NULL, NULL,
                    &noiseclipprecom, status );

  /* Loop over subarray */
  for( idx=0; (idx<array->ndat)&&(*status==SAI__OK); idx++ ) {
    data = array->sdata[idx];

    /* Update quality by synchronizing to the data array VAL__BADD values */
    msgOutif(MSG__VERB,"", FUNC_NAME ": update quality", status);
    smf_update_quality( data, 1, NULL, 0, badfrac, status );

    /*** TIMER ***/
    msgOutiff( SMF__TIMER_MSG, "", FUNC_NAME ":   ** %f s updating quality",
               status, smf_timerupdate(&tv1,&tv2,status) );

    /* Fix DC steps */
    if( dcthresh && dcfitbox ) {
      msgOutiff(MSG__VERB, "", FUNC_NAME
                ": Flagging bolos with %lf-sigma DC steps in %" DIM_T_FMT " "
                "samples as bad, using %" DIM_T_FMT
                "-sample median filter and max %d "
                "DC steps per min before flagging entire bolo bad...", status,
                dcthresh, dcfitbox, dcsmooth, dcmaxsteps);

      smf_fix_steps( wf, data, dcthresh, dcsmooth, dcfitbox, dcmaxsteps,
                     dclimcorr, 0, &nflag, NULL, NULL, status );

      msgOutiff(MSG__VERB, "", FUNC_NAME": ...%zd flagged\n", status, nflag);

      /*** TIMER ***/
      msgOutiff( SMF__TIMER_MSG, "", FUNC_NAME ":   ** %f s fixing DC steps",
                 status, smf_timerupdate(&tv1,&tv2,status) );
    }

    /* Flag Spikes */
    if( spikethresh ) {
      msgOutif(MSG__VERB," ", FUNC_NAME ": flag spikes...", status);
      smf_flag_spikes( wf, data, SMF__Q_FIT, spikethresh, spikebox,
                       &nflag, status );
      msgOutiff(MSG__VERB,"", FUNC_NAME ": ...found %zd", status, nflag );

      /*** TIMER ***/
      msgOutiff( SMF__TIMER_MSG, "", FUNC_NAME ":   ** %f s flagging spikes",
                 status, smf_timerupdate(&tv1,&tv2,status) );
    }

    /*  Flag periods of stationary pointing, and update scanspeed to more
        accurate value */
    if( flagslow || flagfast ) {
      if( data->hdr && data->hdr->allState ) {
        double scanvel=0;

        if( flagslow ) {
          msgOutiff( MSG__VERB, "", FUNC_NAME
                     ": Flagging regions with slew speeds < %.2lf arcsec/sec",
                     status, flagslow );
        }

        if( flagfast ) {
          msgOutiff( MSG__VERB, "", FUNC_NAME
                     ": Flagging regions with slew speeds > %.2lf arcsec/sec",
                     status, flagfast );


          /* Check to see if this was a sequence type that involved
             motion.  If not, skip this section */
          if( data && data->hdr && (
                                    (data->hdr->seqtype==SMF__TYP_SCIENCE) ||
                                    (data->hdr->seqtype==SMF__TYP_POINTING) ||
                                    (data->hdr->seqtype==SMF__TYP_FOCUS) ||
                                    (data->hdr->seqtype==SMF__TYP_SKYDIP))
                                 && (data->hdr->obsmode!=SMF__OBS_STARE) ) {

            smf_flag_slewspeed( data, flagslow, flagfast, &nflag, &scanvel,
                              status );
            msgOutiff( MSG__VERB,"", "%zu new time slices flagged", status,
                       nflag);

            if( msgIflev( NULL, status ) >= MSG__VERB ) {
              msgOutf( "", FUNC_NAME ": mean SCANVEL=%.2lf arcsec/sec"
                       " (was %.2lf)", status, scanvel, data->hdr->scanvel );
            }

            data->hdr->scanvel = scanvel;

            /*** TIMER ***/
            msgOutiff( SMF__TIMER_MSG, "", FUNC_NAME
                       ":   ** %f s flagging outlier slew speeds",
                       status, smf_timerupdate(&tv1,&tv2,status) );
          } else {
            msgOutif( MSG__VERB, "", FUNC_NAME
                      ": not a moving sequence or missing header, "
                      "skipping slew speed flagging", status );
          }
        }
      } else {
        msgOutif( MSG__DEBUG, "", FUNC_NAME
                  ": Skipping flagslow/flagfast because no header present",
                  status );
      }
    }

    /* Clean out the dark squid signal */
    if( dkclean ) {
      msgOutif(MSG__VERB, "", FUNC_NAME
               ": Cleaning dark squid signals from data.", status);
      smf_clean_dksquid( data, 0, 100, NULL, 0, 0, 0, status );

      /*** TIMER ***/
      msgOutiff( SMF__TIMER_MSG, "", FUNC_NAME ":   ** %f s DKSquid cleaning",
                 status, smf_timerupdate(&tv1,&tv2,status) );
    }

    /* Apply optical efficiency corrections. */
    one_strlcpy( param, "OPTEFF", sizeof(param), status );
    smf_find_subarray( data->hdr, param + strlen(param),
                       sizeof(param) - strlen(param), NULL, status );
    astChrCase( NULL, param, 1, 0 );
    if( astMapHasKey( keymap, param ) ) {
      astMapGet0I( keymap, "OPTEFFDIV", &opteffdiv );
      if ( astMapGet0C( keymap, param, &opteff ) ) {
        msgOutiff( MSG__VERB,"", FUNC_NAME ": %s bolometer values "
                   "by factors read from NDF %s", status,
                   opteffdiv ? "Dividing" : "Multiplying", opteff );
        smf_scale_bols( wf, data, NULL, opteff, param, opteffdiv, status );
      }
    }

    /* Remove baselines */
    if( order >= 0 ) {
      msgOutiff( MSG__VERB,"", FUNC_NAME
                 ": Fitting and removing %i-order polynomial baselines",
                 status, order );

      smf_fit_poly( wf, data, order, 1, NULL, status );

      /*** TIMER ***/
      msgOutiff( SMF__TIMER_MSG, "", FUNC_NAME
                 ":   ** %f s removing poly baseline",
                 status, smf_timerupdate(&tv1,&tv2,status) );
    }
  }

  /* Mask noisy bolos here if happening before common-mode cleaning */
  if( (*status == SAI__OK) && ((noisecliphigh>0.0) || (noisecliplow>0.0)) &&
      noiseclipprecom ) {

    smf__noisymask( wf, data, noisemaps, noisecliphigh, noisecliplow,
                    zeropad, &tv1, &tv2, status );
  }


  /* Optionally call smf_calcmodel_com to perform a subset of the following
     tasks as a pre-processing step:

       - remove the common-mode
       - flag outlier data using common-mode rejection
       - determine relative flatfields using amplitude of common-mode

     In order to do this we need to set up some temporary model container
     files so that the routine can be called properly. All of the same
     COMmon-mode and GAIn model parameters (e.g. com.* and gai.*) will be
     used here. However, in addition the "compreprocess" flag must be set
     for this operation to be performed. */

  if( compreprocess ) {
    smfArray *comdata = NULL;
    smfGroup *comgroup = NULL;
    smfDIMMData dat;
    smfArray *gaidata = NULL;
    smfGroup *gaigroup = NULL;
    smfArray *quadata = NULL;
    smfData *thisqua=NULL;

    msgOutif(MSG__VERB," ", FUNC_NAME ": Remove common-mode", status);

    /* Create model containers for COM, GAI */
    smf_model_create( wf, NULL, &array, NULL, NULL, NULL, NULL, NULL, 1, SMF__COM,
                      0, NULL, 0, NULL, NULL, &comgroup, &comdata, keymap,
                      status );

    smf_model_create( wf, NULL, &array, NULL, NULL, NULL, NULL, NULL, 1, SMF__GAI,
                      0, NULL, 0, NULL, NULL, &gaigroup, &gaidata, keymap,
                      status );

    /* Manually create quadata to share memory with the quality already
       stored in array */

    quadata = smf_create_smfArray( status );
    for( idx=0; (*status==SAI__OK) && (idx<array->ndat); idx++ ) {
      /* Create several new smfDatas, but they will all be freed
         properly when we close quadata */
      thisqua = smf_create_smfData( SMF__NOCREATE_DA | SMF__NOCREATE_HEAD |
                                    SMF__NOCREATE_FILE, status );

      /* Probably only need pntr->[0], but fill in the dimensionality
         information to be on the safe side */
      thisqua->dtype = SMF__QUALTYPE;
      thisqua->ndims = array->sdata[idx]->ndims;
      thisqua->isTordered = array->sdata[idx]->isTordered;
      memcpy( thisqua->dims, array->sdata[idx]->dims, sizeof(thisqua->dims) );
      memcpy( thisqua->lbnd, array->sdata[idx]->lbnd, sizeof(thisqua->lbnd) );
      thisqua->pntr[0] = smf_select_qualpntr( array->sdata[idx], NULL, status );

      smf_addto_smfArray( quadata, thisqua, status );
    }

    /* Set up the smfDIMMData and call smf_calcmodel_com */
    memset( &dat, 0, sizeof(dat) );
    dat.res = &array;
    dat.gai = &gaidata;
    dat.qua = &quadata;
    dat.noi = NULL;

    smf_calcmodel_com( wf, &dat, 0, keymap, &comdata, SMF__DIMM_FIRSTITER,
                       status );

    /*** TIMER ***/
    msgOutiff( SMF__TIMER_MSG, "", FUNC_NAME
               ":   ** %f s removing common-mode",
               status, smf_timerupdate(&tv1,&tv2,status) );

    /* Clean up and/or return values */
    if( com ) {
      *com = comdata;
    } else {
      if( comdata ) smf_close_related( &comdata, status );
    }

    if( gai ) {
      *gai = gaidata;
    } else {
      if( gaidata ) smf_close_related( &gaidata, status );
    }

    if( comgroup ) smf_close_smfGroup( &comgroup, status );
    if( gaigroup ) smf_close_smfGroup( &gaigroup, status );

    /* Before closing quadata unset all the pntr[0] since this is shared
       memory with the quality associated with array */
    if( quadata ) {
      for( idx=0; idx<quadata->ndat; idx++ ) {
        quadata->sdata[idx]->pntr[0] = NULL;
      }
      if( quadata ) smf_close_related( &quadata, status );
    }
  }

  /* PCA cleaning */
  if( pcathresh ) {
    /* Loop over subarray */
    for( idx=0; (idx<array->ndat)&&(*status==SAI__OK); idx++ ) {
      data = array->sdata[idx];

      smf_clean_pca_chunks( wf, data, pcalen, pcathresh, keymap, status );
    }

    /*** TIMER ***/
    msgOutiff( SMF__TIMER_MSG, "", FUNC_NAME ":   ** %f s PCA cleaning",
               status, smf_timerupdate(&tv1,&tv2,status) );
  }

  /* Allocate space for noisemaps if required */

  if( noisemaps ) {
    *noisemaps = smf_create_smfArray( status );
  }

  /* Loop over subarray */

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

    /* Filter the data. Note that we call smf_filter_execute to apply
       a per-bolometer whitening filter even if there is no
       explicitly requested smfFilter (in which case the
       smf_filter_fromkeymap call will leave the real/imaginary parts
       of the filter as NULL pointers and they will get ignored inside
       smf_filter_execute). */

    filt = smf_create_smfFilter( data, status );
    smf_filter_fromkeymap( filt, keymap, data->hdr, &dofft, &whiten, status );

    if( (*status == SAI__OK) && dofft ) {
      msgOutif( MSG__VERB, "", FUNC_NAME ": frequency domain filter", status );
      smf_filter_execute( wf, data, filt, 0, whiten, status );

      /*** TIMER ***/
      msgOutiff( SMF__TIMER_MSG, "", FUNC_NAME ":   ** %f s filtering data",
                 status, smf_timerupdate(&tv1,&tv2,status) );
    }
    filt = smf_free_smfFilter( filt, status );

    /* Mask noisy bolos here if happening after common-mode cleaning */
    if( (*status == SAI__OK) && ((noisecliphigh>0.0) || (noisecliplow>0.0)) &&
        !noiseclipprecom ) {

      smf__noisymask( wf, data, noisemaps, noisecliphigh, noisecliplow,
                      zeropad, &tv1, &tv2, status );
    }

  }
}
コード例 #8
0
ファイル: smf_choose_darks.c プロジェクト: astrobuff/starlink
void smf_choose_darks( const smfArray *darks, const smfData *indata,
                       size_t *dark1, size_t *dark2, int * status ) {
  size_t i;          /* loop counter */
  int refseq;        /* Sequence count of input science data */
  sc2ast_subarray_t refsubnum;     /* Subarray number of science data */

  *dark1 = SMF__BADIDX;
  *dark2 = SMF__BADIDX;

  if (*status  != SAI__OK) return;
  if (!darks) return;
  if (!smf_validate_smfData( indata, 1, 0, status ) ) return;

  /* get reference sequence counter and subarray number */
  smf_find_seqcount( indata->hdr, &refseq, status );
  smf_find_subarray( indata->hdr, NULL, (size_t)0, &refsubnum, status );

  /* Loop through all the darks looking for ones that only differ
     from the reference sequence counter by 1 */
  for (i=0; i< darks->ndat; i++) {
    smfData *thisdark = (darks->sdata)[i];
    sc2ast_subarray_t thissubnum;
    smf_find_subarray( thisdark->hdr, NULL, (size_t)0, &thissubnum, status );

    /* see if we even need to look at the sequence counter */
    if (thissubnum == refsubnum &&
        strcmp( indata->hdr->obsidss, thisdark->hdr->obsidss ) == 0 ) {
      int thisseq;
      int seqdiff;
      smf_find_seqcount( thisdark->hdr, &thisseq, status );
      seqdiff = refseq - thisseq;

      if ( seqdiff == 1 ) {
        /* Valid previous dark */
        *dark1 = i;
      } else if (seqdiff == -1 ) {
        /* Valid next dark */
        *dark2 = i;
      } else if (seqdiff == 0) {
        /* should not be possible */
        if (*status == SAI__OK) {
          *status = SAI__ERROR;
          errRep(" ","Should not be possible for dark and science "
                 "observation to have identical sequence counter.", status );
          return;
        }
      }
    }

    /* finish if we have everything */
    if (*dark1 != SMF__BADIDX && *dark2 != SMF__BADIDX) break;

  }

  if (*dark1 == SMF__BADIDX) {
    msgOutif( MSG__VERB, " ","Unable to find any prior dark", status );
  }
  if (*dark2 == SMF__BADIDX) {
    msgOutif( MSG__VERB, " ","Unable to find any following dark", status );
  }

}
コード例 #9
0
ファイル: smf_flat_write.c プロジェクト: bbrond/starlink
void smf_flat_write( smf_flatmeth flatmeth, const char * flatname,
                     double refres, const smfData * bolval,
                     const smfData * powref, const smfData * bolref,
                     const smfData * polyfit, const Grp * prvgrp, int * status ) {

  size_t colsize;              /* number of columns */
  double *dbuf = NULL;         /* input double buffer for mean data */
  double *dvar = NULL;         /* input double buffer for variance of data */
  char fitsrec[SC2STORE__MAXFITS*SZFITSCARD+1]; /* Store for FITS records */
  int *ibuf = NULL;            /* int buffer for mean data */
  int indf = NDF__NOID;        /* NDF identifier for output file */
  size_t ncards;               /* number of fits cards */
  size_t numbols;              /* number of bolometers */
  double *outvar = NULL;       /* buffer for variance of data */
  int place = NDF__NOPL;       /* Dummy placeholder for NDF */
  size_t rowsize;              /* number of rows */
  JCMTState *state = NULL;     /* State for this flatfield */
  sc2ast_subarray_t subnum;    /* subarray number */

  AstFrameSet *result, *spacefset;
  AstLutMap *heatmap;
  AstFrame *heatfrm;


  int *dksquid;           /* pointer to dummy dark SQUID data */
  size_t j;               /* loop counter */
  int jig_vert[1][2];     /* dummy jiggle vertices */
  double jig_path[1][2];  /* dummy jiggle path */
  size_t nframes = 0;     /* Number of frames in bolval */
  int npath = 0;          /* size of jiggle path */
  int nvert = 0;          /* number of jiggle vertices */
  char *xmlfile = NULL;   /* dummy xmlfile name */

  if (*status != SAI__OK) return;

  if (!bolval->da) {
    *status = SAI__ERROR;
    errRep( "", "No flatfield solution provided for writing",
            status );
    return;
  }

  if (!bolval->da->heatval) {
    *status = SAI__ERROR;
    errRep( "", "Must provide heater values in DA struct to smf_flat_write"
            " (possible programming error)", status );
    return;
  }

  /* note that colsize is the number of rows and rowsize is the number of
     columns */
  colsize = (bolval->dims)[SC2STORE__ROW_INDEX];
  rowsize = (bolval->dims)[SC2STORE__COL_INDEX];
  numbols = colsize * rowsize;
  nframes = (bolval->dims)[2];

  /* Make sure we have a FLAT header that reflects this file
     as the flatfield solution */
  smf_fits_updateS( bolval->hdr, "FLAT", flatname, "Name of flat-field file",
                    status );

  /* Create a FITS header for DA */
  smf_fits_export2DA( bolval->hdr->fitshdr, &ncards, fitsrec, status );

  /* Copy the data as integers so it can be written to data file. To
     prevent overflow in the variance we store that as doubles */

  ibuf = astMalloc( (numbols * nframes)*sizeof(*ibuf) );
  outvar = astMalloc( (numbols * nframes)*sizeof(*outvar) );

  dbuf = (bolval->pntr)[0];
  dvar = (bolval->pntr)[1];

  if (*status == SAI__OK) {
    for (j = 0; j < (nframes * numbols); j++) {
      /* These started off as integers so the mean value must fit in
         an integer */
      if ( dbuf[j] == VAL__BADD) {
        ibuf[j] = VAL__BADI;
      } else {
        ibuf[j] = (int)dbuf[j];
      }
      /* Same data type so no need to convert bad values */
      if (dvar) {
        outvar[j] = dvar[j];
      } else {
        outvar[j] = VAL__BADD;
      }
    }
  }

  /* get subarray number */
  smf_find_subarray( bolval->hdr, NULL, 0, &subnum, status );

  /* Create dummy components for output file */
  dksquid = astCalloc ( rowsize* nframes, sizeof(*dksquid) );
  jig_vert[0][0] = 0;
  jig_vert[0][1] = 0;
  jig_path[0][0] = 0.0;
  jig_path[0][1] = 0.0;

  sc2store_setcompflag ( SC2STORE__NONE, status );
  sc2store_wrtstream ( flatname, subnum, ncards,
                       fitsrec, colsize, rowsize, nframes,
                       (bolref->dims)[2], refres, 0, smf_flat_methstring( flatmeth, status ),
                       bolval->hdr->allState, NULL,
                       ibuf, dksquid, (bolref->pntr)[0], (powref->pntr)[0],
                       "FLATCAL", NULL, NULL, jig_vert,
                       nvert, jig_path, npath, xmlfile, status );

  sc2store_free ( status );

  /* To copy in the variance and modify fix up the WCS we need to reopen
     the file */

  ndfOpen( NULL, flatname, "UPDATE", "OLD", &indf, &place, status );

  /* make sure that history is not written twice */
  ndfHsmod( "SKIP", indf, status );

  if (outvar) {
    void *pntr[3];
    int el;
    ndfStype( "_DOUBLE", indf, "VARIANCE", status );
    ndfMap( indf, "VARIANCE", "_DOUBLE", "WRITE", pntr, &el, status );
    if (*status == SAI__OK) {
      memcpy( pntr[0], outvar, sizeof(*outvar)*el );
    }
  }

  /* For the WCS a time frame is less relevant than heater settings */
  astBegin;

  /* Create frame for focal plane coordinates */
  sc2ast_createwcs( subnum, NULL, NULL, NULL, NO_FTS, &spacefset, status );

  /* Copy it to make sure we do not mess with the cache */
  result = astCopy( spacefset );

  /* and switch to BOLO frame which is best for bolometer analysis */
  {
    int frnum = AST__NOFRAME;
    kpg1Asffr( result, "BOLO", &frnum, status );
    if (frnum != AST__NOFRAME) astSetI( result, "CURRENT", frnum );
  }

  /* Create a simple frame for heater settings */
  heatfrm = astFrame( 1, "Domain=HEATER,Label(1)=Heater Setting" );
  heatmap = astLutMap( nframes, bolval->da->heatval, 1.0, 1.0, " " );

  /* Append the heater axis to the spatial frameset */
  atlAddWcsAxis( result, (AstMapping *)heatmap, (AstFrame *) heatfrm,
                 NULL, NULL, status );

  /* write it to the NDF */
  ndfPtwcs( result, indf, status );


  /* Write provenance information */
  if (prvgrp) {
    size_t size = grpGrpsz( prvgrp, status );
    char prvname[ 2 * PAR__SZNAM + 1];

    smf_get_taskname( NULL, prvname, status );
    for (j=1; j<=size; j++) {
      smf_accumulate_prov( NULL, prvgrp, j, indf, prvname, NULL, status );
    }

  }

  /* Write the polynomial expansion into an extension */
  if (polyfit) {
    char fitfile[GRP__SZNAM+1];
    int fndf = NDF__NOID;
    place = NDF__NOPL;
    one_strlcpy( fitfile, flatname, sizeof(fitfile), status );
    one_strlcat( fitfile, ".MORE.SMURF.FLATFIT", sizeof(fitfile), status );

    /* create the file */
    smf_write_smfData( polyfit, NULL, fitfile, NULL, 0, NDF__NOID,
                       MSG__VERB, 0, status );

    /* Same WCS as the main file */
    ndfOpen( NULL, fitfile, "UPDATE", "OLD", &fndf, &place, status );
    ndfPtwcs( result, fndf, status );
    ndfAnnul( &fndf, status );

  }

  astEnd;

  ndfAnnul( &indf, status);

  if (ibuf) ibuf = astFree( ibuf );
  if (outvar) outvar = astFree( outvar );
  if (dksquid) dksquid = astFree( dksquid );
  if (state) state = astFree( state );
}
コード例 #10
0
ファイル: smf_store_image.c プロジェクト: andrecut/starlink
void smf_store_image( smfData *data, HDSLoc *scu2redloc, int cycle, int ndim,
		      int dims[], int nsampcycle, int vxmin, int vymin,
		      double *image, double *zero, int *status) {

  smfHead *hdr = NULL;             /* Pointer to header struct */
  HDSLoc *bz_imloc = NULL;         /* HDS locator */
  int bzindf;                      /* NDF identifier for bolometer zero points */
  double *bzptr = NULL;            /* Pointer to mapped space for zero points */
  int el;                          /* Number of elements mapped */
  int frame;                       /* Mean timeslice index for image */
  AstFitsChan *imfits=NULL;        /* FITS header for each reconstructed image */
  char imname[DAT__SZNAM];         /* Name of structure for image */
  double *imptr = NULL;            /* Pointer to mapped space for image */
  int j;                           /* Loop counter */
  int lbnd[2];                     /* Lower dimension bounds */
  int ntot;                        /* Total number of elements */
  int place;                       /* NDF placeholder */
  char prvname[2*PAR__SZNAM +1];   /* Provenance creator */
  int seqend;                      /* End index */
  int seqstart;                    /* Starting index */
  int slice;                       /* Index of current time slice */
  int strnum;                      /* Structure element number */
  sc2ast_subarray_t subnum;        /* Subarray index number */
  int ubnd[2];                     /* Upper dimension bounds */
  int uindf;                       /* NDF identifier */
  AstFrameSet *wcs = NULL;         /* WCS info */

  if ( *status != SAI__OK ) return;

  seqstart = cycle * nsampcycle;
  seqend = seqstart + nsampcycle - 1;

  slice = (int)( (seqstart + seqend ) /2);
  smf_tslice_ast( data, slice, 1, status);

  astBegin;

  /* Old beginning */

  /* Get structure for nth constructed image */
  strnum = cycle + 1;
  sprintf ( imname, "I%d", strnum );

  ntot = 1;
  for ( j=0; j<ndim; j++ ) {
    lbnd[j] = 1;
    ubnd[j] = lbnd[j] + dims[j] - 1;
    ntot *= dims[j];
  }
  ndfPlace ( scu2redloc, imname, &place, status );
  ndfNew ( "_DOUBLE", ndim, lbnd, ubnd, &place, &uindf, status );
  ndfHcre ( uindf, status );

  /* Map the data array */
  ndfMap ( uindf, "DATA", "_DOUBLE", "WRITE", (void *)&imptr, &el,
	   status );

  /* Copy image array */
  if ( *status == SAI__OK ) {
    memcpy( imptr, image, ntot*sizeof(*imptr));
  }

  /* Derive WCS */
  hdr = data->hdr;
  smf_find_subarray(hdr, NULL, 0, &subnum, status );
  sc2ast_createwcs( subnum, hdr->state, hdr->instap, hdr->telpos, &wcs, status );

  /* Shift the coord frame is either vxmin or vymin is non-zero */
  if ( vxmin != 0 || vymin != 0 ) {
    sc2ast_moveframe ( -(double)vxmin, -(double)vymin, wcs, status );
  }

  /* This should probably be a user-option but ICRS is probably a safe
     assumption */
  sc2ast_set_output_system( hdr->state->tcs_tr_sys, wcs, status );

  /* Sort out provenance. */
  smf_get_taskname( NULL, prvname, status );
  smf_updateprov( uindf, data, NDF__NOID, prvname, NULL, status );

  /* Store world coordinate transformations */
  ndfPtwcs ( wcs, uindf, status );

  /* Store the bolometer zero points as an NDF in the extension */
  if (zero) {
    ndfXnew ( uindf, "BOLZERO", "SCUBA2_ZER_ARR", 0, 0, &bz_imloc,
	      status );
    ndfPlace ( bz_imloc, "ZERO", &place, status );

    /* Create the array for bolometer zeros */
    lbnd[0] = SC2STORE__BOL_LBND;
    ubnd[0] = lbnd[0] + dims[0] - 1;
    lbnd[1] = SC2STORE__BOL_LBND;
    ubnd[1] = lbnd[1] + dims[1] - 1;
    ndfNew ( "_DOUBLE", 2, lbnd, ubnd, &place, &bzindf, status );
    ndfHcre ( bzindf, status );

    /* Map the data array */
    ndfMap ( bzindf, "DATA", "_DOUBLE", "WRITE", (void *)&bzptr, &el,
	     status );

    /* Copy image array */
    if ( *status == SAI__OK ) {
      memcpy( bzptr, zero, dims[0]*dims[1]*sizeof(*zero));
    }

    /* Unmap the data array */
    ndfUnmap ( bzindf, "DATA", status );
    ndfAnnul ( &bzindf, status );

    /* Free the locators for the frame */
    datAnnul ( &bz_imloc, status );

  }

  /* Store the FITS headers */
  frame = (int)( (seqstart + seqend ) /2);
  /* Quick and dirty method - just copy the full FITS header */
  imfits = astCopy( hdr->fitshdr );
  astSetFitsI( imfits, "SUBSCAN", strnum,
	       "Subscan number of reconstructed image", 0);

  kpgPtfts( uindf, imfits, status );

  /* Unmap the data array */
  ndfUnmap ( uindf, "DATA", status );
  ndfAnnul ( &uindf, status );

  astEnd;

}
コード例 #11
0
void smf_choose_closest( const smfArray *alldata, const smfData *indata,
                       size_t *previdx, size_t *nextidx, int * status ) {
  size_t i;          /* loop counter */
  double reftime;    /* MJD of input science data */
  sc2ast_subarray_t refsubnum; /* Subarray number of science data */

  smf_timediff prev; /* information on closest previous */
  smf_timediff next; /* information on closest next */

  *previdx = SMF__BADIDX;
  *nextidx = SMF__BADIDX;

  if (*status  != SAI__OK) return;
  if (!indata) return;

  /* get reference MJD and subarray number */
  smf_find_dateobs( indata->hdr, &reftime, NULL, status );
  smf_find_subarray( indata->hdr, NULL, 0, &refsubnum, status );

  /* initialise the diff structs */
  prev.diff = VAL__MAXD;
  prev.index = SMF__BADIDX;
  next.diff = VAL__MAXD;
  next.index = SMF__BADIDX;

  /* loop through all the files finding the ones closest in time
     with the correct subarray number */
  for (i=0; (*status==SAI__OK)&&(i<alldata->ndat); i++) {
    smfData *thisfile = (alldata->sdata)[i];
    sc2ast_subarray_t thissubnum;
    smf_find_subarray( thisfile->hdr, NULL, 0, &thissubnum, status );

    /* see if we even need to look at the time */
    if ( (*status==SAI__OK) && (thissubnum == refsubnum) ) {
      double thistime;
      double diff;
      smf_find_dateobs( thisfile->hdr, &thistime, NULL, status );
      diff = reftime - thistime;
      if (diff >= 0) {
        if (prev.diff > diff) {
          prev.diff = diff;
          prev.index = i;
        }
      } else if (diff < 0) {
        diff = fabs(diff);
        if (next.diff > diff) {
          next.diff = diff;
          next.index = i;
        }
      }
    }
  }

  if (prev.index == SMF__BADIDX) {
    msgOutif( MSG__VERB, " ","Unable to find any prior dataset", status );
  }
  if (next.index == SMF__BADIDX) {
    msgOutif( MSG__VERB, " ","Unable to find any following dataset", status );
  }

  /* store return values */
  *previdx = prev.index;
  *nextidx = next.index;

}
コード例 #12
0
ファイル: smf_grp_related.c プロジェクト: dt888/starlink
void smf_grp_related( const Grp *igrp, const size_t grpsize,
                      const int grouping, const int checksubinst,
                      double maxlen_s, double *srate_maxlen,
                      AstKeyMap *keymap, dim_t *maxconcatlen,
                      dim_t *maxfilelen, smfGroup **group,
                      Grp **basegrp, dim_t *pad, int *status ) {

  /* Local variables */
  size_t *chunk=NULL;         /* Array of flags for continuous chunks */
  dim_t * chunklen = NULL;    /* Length of continuous chunk */
  size_t currentindex = 0;    /* Counter */
  char cwave[10];             /* String containing wavelength */
  smfData *data = NULL;       /* Current smfData */
  double downsampscale=0;     /* Angular scale downsampling size */
  double downsampfreq=0;      /* Target downsampling frequency */
  AstKeyMap * grouped = NULL; /* Primary AstKeyMap for grouping */
  size_t i;                   /* Loop counter for index into Grp */
  int isFFT=0;                /* Set if data are 4d FFT */
  size_t j;                   /* Loop counter */
  int *keepchunk=NULL;        /* Flag for chunks that will be kept */
  dim_t maxconcat=0;          /* Longest continuous chunk length */
  dim_t maxflen=0;            /* Max file length in time steps */
  dim_t maxlen=0;             /* Maximum concat length in samples */
  int maxlen_scaled=0;        /* Set once maxlen has been scaled, if needed */
  dim_t maxpad=0;             /* Maximum padding neeed for any input file */
  size_t maxrelated = 0;      /* Keep track of max number of related items */
  size_t *new_chunk=NULL;     /* keeper chunks associated with subgroups */
  dim_t *new_tlen=NULL;       /* tlens for new_subgroup */
  size_t ngroups = 0;         /* Counter for subgroups to be stored */
  size_t nkeep = 0;           /* Number of chunks to keep */
  dim_t * piecelen = NULL;    /* Length of single file */
  smf_subinst_t refsubinst;   /* Subinst of first file */
  size_t **subgroups = NULL;  /* Array containing index arrays to parent Grp */
  smf_subinst_t subinst;      /* Subinst of current file */

  if ( *status != SAI__OK ) return;

  if( maxlen_s < 0 ) {
    *status = SAI__ERROR;
    errRep( "", FUNC_NAME ": maxlen_s cannot be < 0!", status );
    return;
  }

  /* Get downsampling parameters */

  if( keymap ) {
    smf_get_cleanpar( keymap, 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, NULL, NULL, NULL, &downsampscale, &downsampfreq,
                      NULL, NULL, NULL, NULL, status );

    if( downsampscale && downsampfreq ) {
      *status = SAI__ERROR;
      errRep( "", FUNC_NAME ": both downsampscale and downsampfreq are set",
              status );
      return;
    }
  }

  /* Initialize refcwave */
  refsubinst = SMF__SUBINST_NONE;

  /* Loop over files in input Grp: remember Grps are indexed from 1 */
  grouped = astKeyMap( "SortBy=KeyUp" );
  for (i=1; i<=grpsize; i++) {
    char newkey[128];
    char dateobs[81];
    char subarray[10];
    size_t nrelated = 0;
    AstKeyMap * filemap = NULL;
    AstKeyMap * indexmap = NULL;

    /* First step: open file and harvest metadata */
    smf_open_file( NULL, igrp, i, "READ", SMF__NOCREATE_DATA, &data, status );
    if (*status != SAI__OK) break;

    if( i==1 ) {
      isFFT = smf_isfft( data, NULL, NULL, NULL, NULL, NULL, status );
    } else if( smf_isfft(data, NULL, NULL, NULL, NULL, NULL, status) != isFFT ){
      *status = SAI__ERROR;
      errRep( "", FUNC_NAME
              ": mixture of time-series and FFT data encountered!",
              status );
      break;
    }

    /* If maxlen has not been set, do it here */
    if( !maxlen && maxlen_s && data->hdr->steptime) {
      maxlen = (dim_t) (maxlen_s / data->hdr->steptime );
    }

    /* Return srate_maxlen if requested: may want to know this number
       even if maxlen_s is not set. Only calculate once, although it
       gets overwritten once later if down-sampling. */

    if( (i==1) && srate_maxlen && data->hdr->steptime ) {
      *srate_maxlen = 1. / (double) data->hdr->steptime;
    }


    /* If requested check to see if we are mixing wavelengths */
    if( checksubinst ) {
      if( refsubinst == SMF__SUBINST_NONE ) {
        refsubinst = smf_calc_subinst( data->hdr, status );
      }

      subinst = smf_calc_subinst( data->hdr, status );

      if( subinst != refsubinst ) {
        const char *refsubstr = smf_subinst_str( refsubinst, status );
        const char *substr = smf_subinst_str( subinst, status );

        *status = SAI__ERROR;
        smf_smfFile_msg( data->file, "FILE", 1, "<unknown>" );
        msgSetc( "REFSUB", refsubstr );
        msgSetc( "SUB", substr );
        errRep( "", FUNC_NAME
                ": ^FILE uses sub-instrument ^SUB which doesn't match "
                "reference ^REFSUB", status );
      }
    }

    /* Want to form a key that will be unique for a particular subscan
       We know that DATE-OBS will be set for SCUBA-2 files and be the same
       for a single set. Prefix by wavelength if we are grouping by wavelength.
     */
    newkey[0] = '\0';

    smf_find_subarray( data->hdr, subarray, sizeof(subarray), NULL, status );

    if( grouping == 1 ) {
      /* Group different wavelengths separately */
      smf_fits_getS( data->hdr, "WAVELEN", cwave, sizeof(cwave), status);
      one_strlcat( newkey, cwave, sizeof(newkey), status );
      one_strlcat( newkey, "_", sizeof(newkey), status );
    }

    if( grouping == 2 ) {
      /* Group different subarrays separately */
      one_strlcat( newkey, subarray, sizeof(newkey), status );
    }

    smf_fits_getS( data->hdr, "DATE-OBS", dateobs, sizeof(dateobs), status );
    one_strlcat( newkey, dateobs, sizeof(newkey), status );

    /* Include the dimentionality of the time series in the primary key
       so that we do not end up doing something confusing like relating
       a truncated file with a full length file */
    if (*status == SAI__OK) {
      dim_t dims[3];
      char formatted[32];
      smf_get_dims( data, &dims[0], &dims[1], NULL, &dims[2], NULL, NULL, NULL,
                    status );
      sprintf(formatted, "_%" DIM_T_FMT "_%" DIM_T_FMT "_%" DIM_T_FMT, dims[0], dims[1], dims[2]);
      one_strlcat( newkey, formatted, sizeof(newkey), status );
    }

    /* May want to read the dimensionality of the file outside of loop
       so that we can compare values when storing in the keymap */

    /* Now we want to create a keymap based on this key */
    if (!astMapGet0A( grouped, newkey, &filemap ) ) {
      int itemp = 0;
      double steptime = data->hdr->steptime;
      dim_t ntslice = 0;
      dim_t thispad;              /* Padding neeed for current input file */

      filemap = astKeyMap( " " );
      astMapPut0A( grouped, newkey, filemap, NULL );

      /* Fill up filemap with general information on this file */
      smf_find_seqcount( data->hdr, &itemp, status );
      astMapPut0I( filemap, "SEQCOUNT", itemp, NULL );

      smf_fits_getI( data->hdr, "NSUBSCAN", &itemp, status );
      astMapPut0I( filemap, "NSUBSCAN", itemp, NULL );

      /* Number of time slices */
      smf_get_dims( data, NULL, NULL, NULL, &ntslice, NULL, NULL, NULL,
                    status );

      /* Find length of down-sampled data, new steptime and maxlen */
      if( (downsampscale || downsampfreq) && data->hdr && (*status==SAI__OK) ) {
        double scalelen;

        if( downsampscale ) {
          if( data->hdr->scanvel != VAL__BADD ) {
             double oldscale = steptime * data->hdr->scanvel;
             scalelen = oldscale / downsampscale;
          } else if( *status == SAI__OK ) {
             *status = SAI__ERROR;
            scalelen = VAL__BADD;
            smf_smfFile_msg( data->file, "FILE", 1, "" );
            errRep( "", FUNC_NAME ": can't resample ^FILE because it has "
                    "unknown scan velocity", status );
          }
        } else {
          if( steptime ) {
            double oldsampfreq = 1./steptime;
            scalelen = downsampfreq / oldsampfreq;
          } else {
            *status = SAI__ERROR;
            scalelen = VAL__BADD;
            smf_smfFile_msg( data->file, "FILE", 1, "" );
            errRep( "", FUNC_NAME ": can't resample ^FILE because it has "
                    "unknown sample rate", status );
          }
        }

        /* only down-sample if it will be a reasonable factor */
        if( (*status==SAI__OK) && (scalelen <= SMF__DOWNSAMPLIMIT) ) {
          smf_smfFile_msg(data->file, "FILE", 1, "" );
          msgOutiff( MSG__VERB, "", FUNC_NAME
                     ": will down-sample file ^FILE from %5.1lf Hz to "
                     "%5.1lf Hz", status, (1./steptime), (scalelen/steptime) );

          ntslice = round(ntslice * scalelen);

          /* If maxlen has been requested, and we have not already worked
             out a scaled version (just uses the sample rates for the first
             file... should be close enough -- the alternative is a 2-pass
             system). */

          if( !maxlen_scaled ) {
            maxlen = round(maxlen*scalelen);
            maxlen_scaled = 1;
            msgOutiff( MSG__VERB, "", FUNC_NAME
                       ": requested maxlen %g seconds = %" DIM_T_FMT " down-sampled "
                       "time-slices", status, maxlen_s, maxlen );

            /* Return updated srate_maxlen for down-sampling if requested */
            if( srate_maxlen ) {
              *srate_maxlen = scalelen/steptime;
            }
          }
        }
      }

      /* Check that an individual file is too long (we assume related
         files are all the same) */
      if( maxlen && (ntslice > maxlen) && *status == SAI__OK) {
        *status = SAI__ERROR;
        msgSeti("NTSLICE",ntslice);
        msgSeti("MAXLEN",maxlen);
        smf_smfFile_msg( data->file, "FILE", 1, "" );
        errRep(FUNC_NAME,
               "Number of time steps in file ^FILE time exceeds maximum "
               "(^NTSLICE>^MAXLEN)", status);
      }

      /* Scaled values of ntslice and maximum length */
      astMapPut0I( filemap, "NTSLICE", ntslice, NULL );

      /* Work out the padding needed for this file including downsampling. */
      if( keymap ) {
        thispad = smf_get_padding( keymap, 0, data->hdr, VAL__BADD, status );
        if( thispad > maxpad ) maxpad = thispad;
      } else {
        thispad = 0;
      }
      astMapPut0I( filemap, "PADDING", thispad, NULL );

      /* Update maxflen */
      if( ntslice > maxflen ) {
        maxflen = ntslice;
      }

      /* Store OBSID or OBSIDSS depending on whether we are grouping by wavelength */
      if (grouping) {
        astMapPut0C( filemap, "OBSID", data->hdr->obsidss, NULL );
      } else {
        char obsid[81];
        smf_getobsidss( data->hdr->fitshdr, obsid, sizeof(obsid), NULL, 0, status );
        astMapPut0C( filemap, "OBSID", obsid, NULL );
      }
    }

    /* Store the file index in another keymap indexed by subarray */
    if ( !astMapGet0A( filemap, "GRPINDICES", &indexmap ) ) {
      indexmap = astKeyMap( "SortBy=KeyUp" );
      astMapPut0A( filemap, "GRPINDICES", indexmap, NULL );
    }

    astMapPut0I( indexmap, subarray, i, NULL );

    /* Need to track the largest number of related subarrays in a single slot */
    nrelated = astMapSize( indexmap );
    if (nrelated > maxrelated) maxrelated = nrelated;

    /* Free resources */
    filemap = astAnnul( filemap );
    indexmap = astAnnul( indexmap );
    smf_close_file( NULL, &data, status );
  }

  /* We now know how many groups there are */
  ngroups = astMapSize( grouped );

  /* Sort out chunking. The items are sorted by date and then by wavelength.
     We define a continuous chunk if it has the same OBSID, the same SEQCOUNT
     and NSUBSCAN increments by one from the previous entry.

     Also count number of related items in each slot.
   */
  if (*status == SAI__OK) {
    typedef struct { /* somewhere to store the values easily */
      char obsid[81];
      char related[81];  /* for concatenated subarrays */
      int nsubscan;
      int seqcount;
    } smfCompareSeq;
    smfCompareSeq current;
    smfCompareSeq previous;
    dim_t totlen = 0;
    size_t thischunk;

    /* Get the chunk flags and also store the size of the chunk */
    chunk = astCalloc( ngroups, sizeof(*chunk) );
    chunklen = astCalloc( ngroups, sizeof(*chunklen) );
    piecelen = astCalloc( ngroups, sizeof(*piecelen) );

    thischunk = 0;  /* The current chunk */
    for (i=0; i<ngroups; i++) {
      AstKeyMap * thismap = NULL;
      AstKeyMap * grpindices = NULL;
      const char * tempstr = NULL;
      int thistlen = 0;
      size_t nsubarrays = 0;

      /* Get the keymap entry for this slot */
      astMapGet0A( grouped, astMapKey(grouped, i), &thismap );

      /* Get info for length limits */
      astMapGet0I( thismap, "NTSLICE", &thistlen );
      piecelen[i] = thistlen;

      if (isFFT) {
        /* Never concatenate FFT data */
        thismap = astAnnul(thismap);
        chunk[i] = i;
        chunklen[i] = thistlen;
        continue;
      }

      /* Get indices information and retrieve the sub-instrument names
         in sort order to concatenate for comparison. We only store in
         a continuous chunk if we have the same subarrays for the whole
         chunk. */
      astMapGet0A( thismap, "GRPINDICES", &grpindices );
      nsubarrays = astMapSize( grpindices );
      (current.related)[0] = '\0';
      for (j = 0; j < nsubarrays; j++ ) {
        one_strlcat( current.related, astMapKey(grpindices, j), sizeof(current.related), status );
      }
      grpindices = astAnnul( grpindices );

      /* Fill in the current struct */
      astMapGet0I( thismap, "SEQCOUNT", &(current.seqcount) );
      astMapGet0I( thismap, "NSUBSCAN", &(current.nsubscan) );
      astMapGet0C( thismap, "OBSID", &tempstr );
      one_strlcpy( current.obsid, tempstr, sizeof(current.obsid), status );

      /* First chunk is special, else compare */
      if (i == 0) {
        totlen = thistlen;
      } else {
        if (  ( current.seqcount == previous.seqcount  ) &&
              ( current.nsubscan - previous.nsubscan == 1 ) &&
              ( strcmp( current.obsid, previous.obsid ) == 0 ) &&
              ( strcmp( current.related, previous.related ) == 0 ) ) {
          /* continuous - check length */
          totlen += thistlen;
          if ( maxlen && totlen > maxlen ) {
            thischunk++;
            totlen = thistlen; /* reset length */
          } else {
            /* Continuous */
          }
        } else {
          /* discontinuity */
          thischunk++;
          totlen = thistlen;  /* Update length of current chunk */
        }
      }

      chunklen[thischunk] = totlen;
      chunk[i] = thischunk;
      memcpy( &previous, &current, sizeof(current) );

      thismap = astAnnul( thismap );
    }
  }

  /* Decide if we are keeping a chunk by looking at the length. */
  maxconcat = 0;
  nkeep = 0;
  keepchunk = astMalloc( ngroups*sizeof(*keepchunk) );
  for (i=0; i<ngroups; i++) {
    size_t thischunk;

    thischunk = chunk[i];
    if ( chunklen[thischunk] < SMF__MINCHUNKSAMP ) {
      /* Warning message */
      msgSeti("LEN",chunklen[thischunk]);
      msgSeti("MIN",SMF__MINCHUNKSAMP);
      msgOut( " ", "SMF_GRP_RELATED: ignoring short chunk (^LEN<^MIN)",
              status);
      keepchunk[i] = 0;
    } else {
      keepchunk[i] = 1;
      if (maxconcat < chunklen[thischunk]) maxconcat = chunklen[thischunk];
      nkeep++;
    }

  }

  /* If no useful chunks generate an error */
  if( (*status==SAI__OK) && (!nkeep) ) {
    *status = SAI__ERROR;
    errRep( "", FUNC_NAME ": No useful chunks.", status );
    goto CLEANUP;
  }

  /* Allocate a subgroup array of the right size and fill it. They keymap
     is sorted by date (and wavelength) so we can always index into it by using
     indices from the subgroup. */
  subgroups = astCalloc( nkeep, sizeof(*subgroups) );
  new_chunk = astCalloc( nkeep, sizeof(*new_chunk) );
  new_tlen  = astCalloc( nkeep, sizeof(*new_tlen) );

  currentindex = 0;
  for (i=0;i<ngroups;i++) {
    AstKeyMap * thismap = NULL;
    AstKeyMap * grpindices = NULL;
    size_t nsubarrays = 0;
    size_t *indices = astCalloc( maxrelated, sizeof(*indices) );

    /* skip if we are dropping this chunk */
    if (!keepchunk[i]) continue;

    /* Get the keymap entry for this slot */
    astMapGet0A( grouped, astMapKey(grouped, i), &thismap );

    /* Get the indices keymap */
    astMapGet0A( thismap, "GRPINDICES", &grpindices );
    nsubarrays = astMapSize( grpindices );
    for (j=0; j<nsubarrays; j++) {
      int myindex;
      astMapGet0I( grpindices, astMapKey(grpindices, j), &myindex );
      indices[j] = myindex;
    }
    grpindices = astAnnul( grpindices );
    thismap = astAnnul( thismap );

    subgroups[currentindex] = indices;
    new_chunk[currentindex] = chunk[i];
    new_tlen[currentindex]  = piecelen[i];
    currentindex++;

  }

  /* Create the smfGroup */
  *group = smf_construct_smfGroup( igrp, subgroups, new_chunk, new_tlen,
                                   nkeep, maxrelated, 0, status );

  /* Return maxfilelen if requested */
  if( maxfilelen ) {
    *maxfilelen = maxflen;
  }

  /* Return maxconcatlen if requested */
  if( maxconcatlen ) {
    *maxconcatlen = maxconcat;
  }

  /* Create a base group for output files if required */
  /* Create a base group of filenames */
  if (*status == SAI__OK && basegrp ) {
    *basegrp = smf_grp_new( (*group)->grp, "Base Group", status );

    /* Loop over time chunks */
    for( i=0; (*status==SAI__OK)&&(i<(*group)->ngroups); i++ ) {
      size_t idx;
      /* Check for new continuous chunk */
      if( i==0 || ( (*group)->chunk[i] != (*group)->chunk[i-1]) ) {
        /* Loop over subarray */
        for( idx=0; idx<(*group)->nrelated; idx++ ) {
          size_t grpindex = (*group)->subgroups[i][idx];
          if ( grpindex > 0 ) {
            ndgCpsup( (*group)->grp, grpindex, *basegrp, status );
          }
        }
      }
    }
  }

 CLEANUP:
  keepchunk = astFree( keepchunk );
  chunk = astFree( chunk );
  chunklen = astFree( chunklen );
  piecelen = astFree( piecelen );
  grouped = astAnnul( grouped );

  if( *status != SAI__OK ) {
    /* free the group */
    if (basegrp && *basegrp) grpDelet( basegrp, status );
    if (group && *group) {
      smf_close_smfGroup( group, status );
    } else {
      /* have to clean up manually */
      new_chunk = astFree( new_chunk );
      new_tlen = astFree( new_tlen );
      if( subgroups ) {
        size_t isub;
        for( isub=0; isub<nkeep; isub++ ) {
          subgroups[isub] = astFree( subgroups[isub] );
        }
        subgroups = astFree( subgroups );
      }
    }
  }

  /* Return the maximum padding if required. */
  if( pad ) *pad = maxpad;
}
コード例 #13
0
void smf_dream_calcweights( smfData *data, const Grp *ogrp, const int index,
                            const double gridstep, const int ngrid,
                            const int *gridminmax, int gridpts[][2],
                            int *status) {

  /* Local Variables */
  int conv_shape = CONV__SINCTAP;/* Code for convolution function */
  double conv_sig = 1.0;        /* Convolution function parameter */
  smfDream *dream = NULL;       /* DREAM parameters obtained from input data file */
  char filename[GRP__SZNAM+1];  /* Input filename, derived from GRP */
  double *gridwts = NULL;       /* Pointer to array of grid weights */
  int gridwtsdim[DREAM__MXGRID];/* Dimensions of grid weights array*/
  smfHead *hdr = NULL;          /* Header for input data */
  double *invmat = NULL;        /* Pointer to inverted matrix */
  int invmatdim;                /* Size of inverted matrix */
  int jigext[4] = {-1, 1, -1, 1}; /* Extents in the X, Y directions of the
                                     jiggle pattern */
  int nbol;                     /* Total number of bolometers */
  int nbolx;                    /* Number of bolometers in X direction */
  int nboly;                    /* Number of bolometers in Y direction */
  int nframes;                  /* Number of timeslices in input data */
  int nsampcycle;               /* Number of samples in a jiggle cycle */
  char *pname = NULL;           /* Pointer to filename string */
  int *qual = NULL;             /* True/false `quality' array (not NDF quality) */
  int qualdim[2];               /* Dimensions of quality array */
  int smu_move = 8;             /* Code for SMU motion*/
  double smu_offset = 0.0;      /* SMU timing offset in ms */
  char subarray[SUB__MAXNAM+1]; /* Name of subarray */
  double tsamp;                 /* Sample/step time in seconds */
  int tvert;                    /* Time between vertices in ms (aka leg length) */
  int windext[4];               /* Size of the window for constructing a DREAM image */

  if ( *status != SAI__OK) return;

  /* Check it's 3-d time series */
  if ( data->ndims == 3) {
    nframes = (data->dims)[2];

    /* Check we have a DREAM observation */
    hdr = data->hdr;
    if ( hdr->obsmode == SMF__OBS_DREAM ) {
      /* OK we have DREAM data */
      dream = data->dream;
      /* Read DREAM parameters from input file */
      smf_find_subarray( hdr, subarray, sizeof(subarray), NULL, status );
      tsamp = hdr->steptime;

      /* Convert steptime into millisec */
      tsamp *= 1000.0;
      nsampcycle = dream->nsampcycle;
      tvert = tsamp*nsampcycle/(dream->nvert);

      msgSeti("I",index);
      msgOutif(MSG__VERB," ", "Beginning weights calculation for file ^I: this will take some time (~5-10 mins)", status);

      /* Some useful shortcuts. Maybe. */
      nbolx = (data->dims)[0];
      nboly = (data->dims)[1];
      nbol = nbolx * nboly;

      /* Allocate quality array */
      qualdim[0] = nbolx;
      qualdim[1] = nboly;
      qual = astCalloc( qualdim[0]*qualdim[1], sizeof(int) );


      sc2math_calcmapwt( subarray, nbolx, nboly,
                         qual, conv_shape, conv_sig, gridstep,
                         dream->nvert, tvert, tsamp,
                         dream->jigvert, dream->jigscal, dream->jigscal, smu_move,
                         smu_offset, ngrid, gridpts, &(gridwtsdim[0]), &gridwts,
                         &invmatdim, &invmat, status);

      /* Dummy definition of window - this must be derived somehow TBD */
      windext[0] = 0;
      windext[1] = (data->dims)[0] - 1;
      windext[2] = 0;
      windext[3] = (data->dims)[1] - 1;

      /* Obtain filename to write weights into */
      pname = filename;
      grpGet( ogrp, index, 1, &pname, SMF_PATH_MAX, status);
      if ( *status != SAI__OK ) {
        errRep(FUNC_NAME, "Unable to retrieve file name in which to store weights solution", status);
      }

      /* Store DREAM weights in output file */
      sc2store_cremapwts ( pname, windext, gridminmax, gridstep, jigext,
                           dream->jigscal, gridwtsdim, gridwts, invmatdim, invmat,
                           qualdim, qual, status );

    } else {
      msgSeti("I", index);
      msgOutif(MSG__VERB," ",
               "Input file ^I is not a DREAM observation - ignoring", status);
    }
  } else {
    if ( *status == SAI__OK ) {
      *status = SAI__ERROR;
      errRep(FUNC_NAME, "Data must be in timeseries format to calculate DREAM weights", status);
    }
  }
}