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