void smf_write_flagmap( ThrWorkForce *wf, smf_qual_t mask, smfArray *lut, smfArray *qua,
                        smfDIMMData *dat, const Grp *flagrootgrp,
                        size_t contchunk, const int *lbnd_out,
                        const int *ubnd_out, AstFrameSet *outfset,
                        int *status ) {

  AstFrameSet *tfset;          /* Temporary FrameSet pointer */
  Grp *mgrp=NULL;               /* Temporary group for map names */
  char *pname=NULL;             /* Poiner to name */
  char name[GRP__SZNAM+1];      /* Buffer for storing names */
  char tempstr[20];             /* Temporary string */
  char tmpname[GRP__SZNAM+1];   /* temp name buffer */
  dim_t nbolo;                  /* Number of bolometers */
  dim_t ntslice;                /* Number of time slices */
  double shift[ 1 ];            /* Shift from GRID to bit number */
  int *flagmap=NULL;            /* pointer to flagmap data */
  int *lut_data=NULL;           /* Pointer to DATA component of lut */
  int ibit;                     /* Quality bit number */
  int lbnd3d[3];                /* Lower bounds for 3D output */
  int npix;                     /* Number of pixels per plane */
  int target;                   /* Target value for incrementing pixel count */
  int ubnd3d[3];                /* Upper bounds for 3D output */
  size_t bstride;               /* Bolometer stride */
  size_t i;                     /* loop counter */
  size_t idx=0;                 /* index within subgroup */
  size_t ii;                    /* array offset index */
  size_t j;                     /* loop counter */
  size_t tstride;               /* Time stride */
  smfData *mapdata=NULL;        /* smfData for new map */
  smf_qual_t *qua_data=NULL;    /* Pointer to DATA component of qua */

  if( *status != SAI__OK ) return;

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

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

  sprintf(tempstr, "CH%02zd", contchunk);
  one_strlcat( name, tempstr, sizeof(name), status );
  mgrp = grpNew( "flagmap", status );
  grpPut1( mgrp, name, 0, status );

  msgOutf( "", "*** Writing flagmap %s", status, name );

  /* If a non-zero mask value wassupplied, the flagmap is 2-dimensional
     and each pixel value counts the number of samples flagged by any of
     the qualities included in the mask. */
  if( mask ) {

     smf_open_newfile( wf, mgrp, 1, SMF__INTEGER, 2, lbnd_out, ubnd_out, 0, &mapdata,
                       status);
     flagmap = mapdata->pntr[0];

     /* Loop over subgroup index (subarray) */
     for( idx=0; (idx<qua->ndat)&&(*status==SAI__OK); idx++ ) {

          smf_get_dims( qua->sdata[idx], NULL, NULL, &nbolo, &ntslice,
                        NULL, &bstride, &tstride, status );
          qua_data = (qua->sdata[idx]->pntr)[0];
          lut_data = (lut->sdata[idx]->pntr)[0];

          /* Loop over bolometer and time slice and create map */
          for( i=0; i<nbolo; i++ ) {
            /* Skip bolometers only if SMF__Q_BADB is set both in the
               data and the mask */
            if( !(qua_data[i*bstride] & mask & SMF__Q_BADB) ) {
              for( j=0; j<ntslice; j++ ) {
                ii = i*bstride + j*tstride;
                if( (qua_data[ii] & mask) && (lut_data[ii] != VAL__BADI) ) {
                  flagmap[lut_data[ii]]++;
                }
              }
            }
          }
        }

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

  /* If the mask is zero, the flagmap is 3-dimensional and contains a
     plane for each quality bit, plus an additional plane (plane 1)
     containing the number of unflagged samples in each pixel. */
  } else {
     lbnd3d[ 0 ] = lbnd_out[ 0 ];
     lbnd3d[ 1 ] = lbnd_out[ 1 ];
     lbnd3d[ 2 ] = -1;
     ubnd3d[ 0 ] = ubnd_out[ 0 ];
     ubnd3d[ 1 ] = ubnd_out[ 1 ];
     ubnd3d[ 2 ] = SMF__NQBITS_TSERIES - 1;

     smf_open_newfile( wf, mgrp, 1, SMF__INTEGER, 3, lbnd3d, ubnd3d, 0,
                       &mapdata, status);
     flagmap = mapdata->pntr[0];

     /* No. of pixels in one plane */
     npix = ( ubnd3d[ 1 ] - lbnd3d[ 1 ] + 1 )*( ubnd3d[ 0 ] - lbnd3d[ 0 ] + 1 );

     /* Loop over each quality bit (-1 == "no flags"). */
     for( ibit = -1; ibit < SMF__NQBITS_TSERIES; ibit++ ) {

        /* The test of each sample is performed by checking if the
           sample's quality value ANDed with "mask" is equal to "target".
           This is requires since ibit==-1 (i.e. "count all samples that
           have no flags set") requires a different logic to the other
           ibit values. */
        if( ibit == -1 ) {
           mask = SMF__Q_GOOD;
           target = 0;
        } else {
           mask = BIT_TO_VAL(ibit);
           target = mask;
        }

        /* Loop over subgroup index (subarray) */
        for( idx=0; (idx<qua->ndat)&&(*status==SAI__OK); idx++ ) {

           smf_get_dims( qua->sdata[idx], NULL, NULL, &nbolo, &ntslice,
                           NULL, &bstride, &tstride, status );
           qua_data = (qua->sdata[idx]->pntr)[0];
           lut_data = (lut->sdata[idx]->pntr)[0];

           /* Loop over bolometer and time slice and create map */
           for( i=0; i<nbolo; i++ ) {

              /* Skip bolometers only if SMF__Q_BADB is set both in the
                 data and the mask */
              for( j=0; j<ntslice; j++ ) {
                 ii = i*bstride + j*tstride;
                 if( ( (qua_data[ii] & mask) == target ) &&
                     (lut_data[ii] != VAL__BADI) ) {
                   flagmap[lut_data[ii]]++;
                 }
              }
           }
        }

        /* Move the pointer on to th enext plane. */
        flagmap += npix;

     /* Next quality bit. */
     }

     /* Take a copy of the supplied FrameSet so we do not modify it. */
     tfset = astCopy( outfset );

     /* Set atributes for moving target if necessary. */
     smf_set_moving( (AstFrame *) tfset, NULL, status );

     /* Modify the WCS FrameSet so that the base and current Frames are
        3-dimensional. The current Frame is expanded by adding in a simple
        1D Frame representing quality bit, and the base Frame is expanded
        by adding in a 3rd GRID axis. Other Frames are left unchanged.
        The quality bit Frame and the new GRID axis are connected using
        a ShiftMap that gives the right zero-based bit numbers (which
        also correspond to PIXEL indices). */
     shift[ 0 ] = -2.0;
     atlAddWcsAxis( tfset, (AstMapping *) astShiftMap( 1, shift, " " ),
                    astFrame( 1, "Label(1)=Quality bit,Domain=QUALITY" ),
                    NULL, NULL, status );

     /* Store the FrameSet in the 3D NDF. */
     ndfPtwcs( tfset, mapdata->file->ndfid, status );

     tfset = astAnnul( tfset );
  }

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

}
Exemple #2
0
void smf_write_itermap( ThrWorkForce *wf, const double *map, const double *mapvar,
                        const smf_qual_t *mapqua, dim_t msize,
                        const Grp *iterrootgrp, size_t contchunk, int iter,
                        const int *lbnd_out, const int *ubnd_out,
                        AstFrameSet *outfset, const smfHead *hdr,
                        const smfArray *qua, int *status ) {

  int flags;                  /* Flags indicating required NDF components */
  Grp *mgrp=NULL;             /* Temporary group to hold map name */
  smfData *imapdata=NULL;     /* smfData for this iteration map */
  char name[GRP__SZNAM+1];    /* Buffer for storing name */
  char *pname=NULL;           /* Poiner to name */
  char tmpname[GRP__SZNAM+1]; /* temp name buffer */
  char tempstr[20];

  if( *status != SAI__OK ) return;

  if( !map || !mapvar || !iterrootgrp || !lbnd_out || !ubnd_out || !outfset ) {
    *status = SAI__ERROR;
    errRep( "", FUNC_NAME ": NULL inputs supplied", status );
    return;
  }

  if( hdr && !qua ) {
    *status = SAI__ERROR;
    errRep( "", FUNC_NAME ": hdr supplied but qua is NULL", status );
    return;
  }

  /* Create a name for this iteration map, take into
     account the chunk number. Only required if we are
     using a single output container. */

  pname = tmpname;
  grpGet( iterrootgrp, 1, 1, &pname, sizeof(tmpname), status );
  one_strlcpy( name, tmpname, sizeof(name), status );
  one_strlcat( name, ".", sizeof(name), status );

  /* Continuous chunk number */
  sprintf(tempstr, "CH%02zd", contchunk);
  one_strlcat( name, tempstr, sizeof(name), status );

  /* Iteration number */
  sprintf( tempstr, "I%03i", iter+1 );
  one_strlcat( name, tempstr, sizeof(name), status );
  mgrp = grpNew( "itermap", status );
  grpPut1( mgrp, name, 0, status );

  msgOutf( "", "*** Writing map from this iteration to %s", status,
           name );

  flags = SMF__MAP_VAR;
  if( mapqua ) flags |= SMF__MAP_QUAL;

  smf_open_newfile ( wf, mgrp, 1, SMF__DOUBLE, 2, lbnd_out,
                     ubnd_out, flags, &imapdata, status);

  /* Copy over the signal and variance maps */
  if( *status == SAI__OK ) {
    memcpy( imapdata->pntr[0], map, msize*sizeof(*map) );
    memcpy( imapdata->pntr[1], mapvar, msize*sizeof(*mapvar) );
    if( mapqua ) memcpy( imapdata->qual, mapqua, msize*sizeof(*mapqua) );
  }

  /* Write out a FITS header */
  if( (*status == SAI__OK) && hdr && hdr->allState ) {
    AstFitsChan *fitschan=NULL;
    JCMTState *allState = hdr->allState;
    char *obsidss=NULL;
    char obsidssbuf[SZFITSTR];
    double iter_nboloeff;
    size_t nmap;
    size_t ngood_tslices;
    dim_t ntslice;                /* Number of time slices */

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

    obsidss = smf_getobsidss( hdr->fitshdr,
                              NULL, 0, obsidssbuf,
                              sizeof(obsidssbuf), status );
    if( obsidss ) {
      atlPtfts( fitschan, "OBSIDSS", obsidss,
                "Unique observation subsys identifier", status );
    }
    atlPtfti( fitschan, "SEQSTART", allState[0].rts_num,
              "RTS index number of first frame", status );

    ntslice = hdr->nframes;

    atlPtfti( fitschan, "SEQEND", allState[ntslice-1].rts_num,
              "RTS index number of last frame", status );

    /* calculate the effective number of bolometers for this
       iteration */
    smf_qualstats_model( wf, SMF__QFAM_TSERIES, 1, qua, NULL, NULL, &nmap,
                         NULL, NULL, &ngood_tslices, NULL, NULL, status );

    iter_nboloeff = (double)nmap / (double)ngood_tslices;
    atlPtftd( fitschan, "NBOLOEFF", iter_nboloeff,
              "Effective bolometer count", status );

    kpgPtfts( imapdata->file->ndfid, fitschan, status );

    if( fitschan ) fitschan = astAnnul( fitschan );
  }

  /* Write WCS (protecting the pointer dereference) */
  smf_set_moving(outfset,NULL,status);
  if (*status == SAI__OK && imapdata) {
    ndfPtwcs( outfset, imapdata->file->ndfid, status );
  }

  /* Clean up */
  if( mgrp ) grpDelet( &mgrp, status );
  smf_close_file( wf, &imapdata, status );
}
void smf_write_shortmap( ThrWorkForce *wf, int shortmap, smfArray *res,
                         smfArray *lut, smfArray *qua, smfDIMMData *dat,
                         dim_t msize, const Grp *shortrootgrp, size_t contchunk,
                         int varmapmethod, const int *lbnd_out,
                         const int *ubnd_out, AstFrameSet *outfset,
                         int *status ) {

  dim_t dsize;                  /* Size of data arrays in containers */
  size_t i;                     /* loop counter */
  size_t idx=0;                 /* index within subgroup */
  size_t istart;                /* First useful timeslice */
  size_t iend;                  /* Last useful timeslice */
  int *lut_data=NULL;           /* Pointer to DATA component of lut */
  char name[GRP__SZNAM+1];      /* Buffer for storing names */
  size_t nshort=0;              /* Number of short maps */
  dim_t ntslice;                /* Number of time slices */
  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 */
  size_t sc;                    /* Short map counter */
  double *shortmapweight=NULL;  /* buffer for shotmap weights */
  double *shortmapweightsq=NULL;/* buffer for shotmap weights squared */
  int *shorthitsmap=NULL;       /* buffer for shotmap hits */
  size_t shortstart;            /* first time slice of short map */
  size_t shortend;              /* last time slice of short map */
  size_t tstride;               /* Time stride */

  if( *status != SAI__OK ) return;

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

  if( !res || !res->sdata || !res->sdata[idx] || !res->sdata[idx]->hdr ||
      !res->sdata[idx]->hdr->allState ) {
    *status = SAI__ERROR;
    errRep( "", FUNC_NAME ": RES does not contain JCMTState", status );
    return;
  }

  /* Allocate space for the arrays */
  shortmapweight = astMalloc( msize*sizeof(*shortmapweight) );
  shortmapweightsq = astMalloc( msize*sizeof(*shortmapweightsq) );
  shorthitsmap = astMalloc( msize*sizeof(*shorthitsmap) );

  /* Use first subarray to figure out time dimension. Get the
     useful start and end points of the time series, and then
     determine "nshort" -- the number of complete blocks of
     shortmap time slices in the useful range. */

  smf_get_dims( qua->sdata[0], NULL, NULL, NULL, &ntslice,
                NULL, NULL, &tstride, status );

  qua_data = (qua->sdata[0]->pntr)[0];
  smf_get_goodrange( qua_data, ntslice, tstride, SMF__Q_BOUND,
                     &istart, &iend, status );

  shortstart = istart;

  if( *status == SAI__OK ) {
    if( shortmap == -1 ) {
      nshort = res->sdata[idx]->hdr->allState[iend].tcs_index -
        res->sdata[idx]->hdr->allState[istart].tcs_index + 1;

      msgOutf( "", FUNC_NAME
               ": writing %zu short maps, once each time TCS_INDEX increments",
               status, nshort );
    } else {
      nshort = (iend-istart+1)/shortmap;

      if( nshort ) {
        msgOutf( "", FUNC_NAME
                 ": writing %zu short maps of length %i time slices.",
                 status, nshort, shortmap );
      } else {
        /* Generate warning message if requested short maps are too long*/
        msgOutf( "", FUNC_NAME
                 ": Warning! short maps of lengths %i requested, but "
                 "data only %zu time slices.", status, shortmap,
                 iend-istart+1 );
      }
    }
  }

  /* Loop over short maps */
  for( sc=0; (sc<nshort)&&(*status==SAI__OK); sc++ ) {

    Grp *mgrp=NULL;             /* Temporary group for map names */
    smfData *mapdata=NULL;      /* smfData for new map */
    char tempstr[20];           /* Temporary string */
    char tmpname[GRP__SZNAM+1]; /* temp name buffer */
    char thisshort[20];         /* name particular to this shortmap */

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

    /* Continuous chunk number */
    sprintf(tempstr, "CH%02zd", contchunk);
    one_strlcat( name, tempstr, sizeof(name), status );

    /* Shortmap number */
    sprintf( thisshort, "SH%06zu", sc );
    one_strlcat( name, thisshort, sizeof(name), status );
    mgrp = grpNew( "shortmap", status );
    grpPut1( mgrp, name, 0, status );

    msgOutf( "", "*** Writing short map (%zu / %zu) %s", status,
             sc+1, nshort, name );

    smf_open_newfile ( wf, mgrp, 1, SMF__DOUBLE, 2, lbnd_out,
                       ubnd_out, SMF__MAP_VAR, &mapdata,
                       status);

    /* Time slice indices for start and end of short map -- common to
       all subarrays */

    if( shortmap > 0) {
      /* Evenly-spaced shortmaps in time */
      shortstart = istart+sc*shortmap;
      shortend = istart+(sc+1)*shortmap-1;
    } else {
      /* One map each time TCS_INDEX increments -- just uses header
         for the first subarray */
      for(i=shortstart+1; (i<=iend) &&
            (res->sdata[0]->hdr->allState[i].tcs_index ==
             res->sdata[0]->hdr->allState[shortstart].tcs_index);
          i++ );
      shortend = i-1;
    }

    /* Bad status if we have invalid shortmap ranges. This might
       happen if there is ever a jump in TCS_INDEX for the shortmap=-1
       case since the total number of shortmaps is calculated simply
       as the difference between the first and final TCS indices. */

    if( !nshort || (iend<istart) || (iend>=ntslice) ) {
      *status = SAI__ERROR;
      errRepf( "", FUNC_NAME ": invalid shortmap range (%zu--%zu, ntslice=%zu)"
               "encountered", status, istart, iend, ntslice );
      break;
    }

    /* Loop over subgroup index (subarray) */
    for( idx=0; (idx<res->ndat)&&(*status==SAI__OK); idx++ ) {
      int rebinflag = 0;

      /* 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, NULL, &ntslice,
                    &dsize, NULL, &tstride, status );

      /* Rebin the data for this range of tslices. */
      if( idx == 0 ) {
        rebinflag |= AST__REBININIT;
      }

      if( idx == (res->ndat-1) ) {
        rebinflag |= AST__REBINEND;
      }

      smf_rebinmap1( NULL, res->sdata[idx],
                     dat->noi ? dat->noi[0]->sdata[idx] : NULL,
                     lut_data, shortstart, shortend, 1, NULL, 0,
                     SMF__Q_GOOD, varmapmethod,
                     rebinflag,
                     mapdata->pntr[0],
                     shortmapweight, shortmapweightsq, shorthitsmap,
                     mapdata->pntr[1], msize, NULL, status );

      /* Write out FITS header */
      if( (*status == SAI__OK) && res->sdata[idx]->hdr &&
          res->sdata[idx]->hdr->allState ) {
        AstFitsChan *fitschan=NULL;
        JCMTState *allState = res->sdata[idx]->hdr->allState;
        size_t midpnt = (shortstart + shortend) / 2;

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

        atlPtfti( fitschan, "SEQSTART", allState[shortstart].rts_num,
                  "RTS index number of first frame", status );
        atlPtfti( fitschan, "SEQEND", allState[shortend].rts_num,
                  "RTS index number of last frame", status);
        atlPtftd( fitschan, "MJD-AVG", allState[midpnt].rts_end,
                  "Average MJD of this map", status );
        atlPtfts( fitschan, "TIMESYS", "TAI", "Time system for MJD-AVG",
                  status );
        atlPtfti( fitschan, "TCSINDST", allState[shortstart].tcs_index,
                  "TCS index of first frame", status );
        atlPtfti( fitschan, "TCSINDEN", allState[shortend].tcs_index,
                  "TCS index of last frame", status );


        kpgPtfts( mapdata->file->ndfid, fitschan, status );

        if( fitschan ) fitschan = astAnnul( fitschan );
      }
    }

    /* Update shortstart in case we are counting steps in TCS_INDEX */
    shortstart = shortend+1;

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

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

  }

  /* Free up memory */
  shortmapweight = astFree( shortmapweight );
  shortmapweightsq = astFree( shortmapweightsq );
  shorthitsmap = astFree( shorthitsmap );

}
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 );

}
Exemple #5
0
void smurf_smurfcopy ( int * status ) {

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

  if (*status != SAI__OK) return;

  ndfBegin();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    }

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

  }

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

  ndfEnd(status);

}