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