void fts2_getmirrorpositions(smfData* data, double* positions, int* size, int* status) { if(*status != SAI__OK) { return; } char ftsMode[SZFITSTR]; size_t count = 0; /* Size */ HDSLoc* hdsLoc = NULL; /* Pointer to HDS location */ HDSLoc* hdsLocPos = NULL; /* Pointer to mirror positions */ smf_fits_getS(data->hdr, "FTS_MODE", ftsMode, sizeof(ftsMode), status); if(strncmp(ftsMode, "FSCAN", 5) == 0 ) { hdsLoc = smf_get_xloc(data, "JCMTSTATE", "EXT", "READ", 0, 0, status); datFind(hdsLoc, "FTS_POS", &hdsLocPos, status); datSize(hdsLocPos, &count, status); datGetVD(hdsLocPos, count, positions, &count, status); *size = (int) count; } else if(strncmp(ftsMode, "STEPINT", 7) == 0 ) { *status = SAI__ERROR; errRep(FUNC_NAME, "STEPINT mode is NOT supported!", status); } else { *status = SAI__ERROR; errRep(FUNC_NAME, "Unknown Scan Mode is found!", status); } if(hdsLoc) { datAnnul(&hdsLoc, status); } if(hdsLocPos) { datAnnul(&hdsLocPos, status); } }
void smf_calc_mapcoord( ThrWorkForce *wf, AstKeyMap *config, smfData *data, AstFrameSet *outfset, int moving, int *lbnd_out, int *ubnd_out, fts2Port fts_port, int flags, int *status ) { /* Local Variables */ AstSkyFrame *abskyfrm = NULL;/* Output SkyFrame (always absolute) */ AstMapping *bolo2map=NULL; /* Combined mapping bolo->map coordinates */ int bndndf=NDF__NOID; /* NDF identifier for map bounds */ void *data_pntr[1]; /* Array of pointers to mapped arrays in ndf */ int *data_index; /* Mapped DATA_ARRAY part of NDF */ int docalc=1; /* If set calculate the LUT */ int doextension=0; /* Try to write LUT to MAPCOORD extension */ smfFile *file=NULL; /* smfFile pointer */ AstObject *fstemp = NULL; /* AstObject version of outfset */ int ii; /* loop counter */ int indf_lat = NDF__NOID; /* Identifier for NDF to receive lat values */ int indf_lon = NDF__NOID; /* Identifier for NDF to receive lon values */ smfCalcMapcoordData *job_data=NULL; /* Array of job */ int lbnd[1]; /* Pixel bounds for 1d pointing array */ int lbnd_old[2]; /* Pixel bounds for existing LUT */ int lbnd_temp[1]; /* Bounds for bounds NDF component */ int lutndf=NDF__NOID; /* NDF identifier for coordinates */ AstMapping *map2sky_old=NULL;/* Existing mapping map->celestial coord. */ HDSLoc *mapcoordloc=NULL; /* HDS locator to the MAPCOORD extension */ int nw; /* Number of worker threads */ AstFrameSet *oldfset=NULL; /* Pointer to existing WCS info */ AstSkyFrame *oskyfrm = NULL; /* SkyFrame from the output WCS Frameset */ smfCalcMapcoordData *pdata=NULL; /* Pointer to job data */ double *lat_ptr = NULL; /* Pointer to array to receive lat values */ double *lon_ptr = NULL; /* Pointer to array to receive lon values */ int ubnd[1]; /* Pixel bounds for 1d pointing array */ int ubnd_old[2]; /* Pixel bounds for existing LUT */ int ubnd_temp[1]; /* Bounds for bounds NDF component */ int *lut = NULL; /* The lookup table */ dim_t nbolo=0; /* Number of bolometers */ dim_t ntslice=0; /* Number of time slices */ int nmap; /* Number of mapped elements */ AstMapping *sky2map=NULL; /* Mapping celestial->map coordinates */ size_t step; /* step size for dividing up work */ AstCmpMap *testcmpmap=NULL; /* Combined forward/inverse mapping */ AstMapping *testsimpmap=NULL;/* Simplified testcmpmap */ double *theta = NULL; /* Scan direction at each time slice */ int tstep; /* Time slices between full Mapping calculations */ int exportlonlat; /* Dump longitude and latitude values? */ /* Main routine */ if (*status != SAI__OK) return; /* How many threads do we get to play with */ nw = wf ? wf->nworker : 1; /* Initialize bounds to avoid compiler warnings */ lbnd_old[0] = 0; lbnd_old[1] = 0; ubnd_old[0] = 0; ubnd_old[1] = 0; /* Check for pre-existing LUT and de-allocate it. This will only waste time if the MAPCOORD extension is found to be valid and it has to be re-loaded from disk. */ smf_close_mapcoord( data, status ); /* Assert ICD data order */ smf_dataOrder( data, 1, status ); /* Get the data dimensions */ smf_get_dims( data, NULL, NULL, &nbolo, &ntslice, NULL, NULL, NULL, status ); /* If SMF__NOCREATE_FILE is not set, and file associated with an NDF, map a new MAPCOORD extension (or verify an existing one) */ if( !(flags & SMF__NOCREATE_FILE) && data->file ) { doextension = 1; } else { doextension = 0; docalc = 1; } /* Create / check for existing MAPCOORD extension */ if( doextension ) { file = data->file; /* Check type of file before proceeding */ if( file->isSc2store ) { *status = SAI__ERROR; errRep(FUNC_NAME, "File was opened by sc2store library (raw data?)", status); } if( !file->isTstream ) { *status = SAI__ERROR; errRep(FUNC_NAME, "File does not contain time stream data",status); } /* Get HDS locator to the MAPCOORD extension */ mapcoordloc = smf_get_xloc( data, "MAPCOORD", "MAP_PROJECTION", "UPDATE", 0, 0, status ); /* Obtain NDF identifier/placeholder for LUT in MAPCOORD extension*/ lbnd[0] = 0; ubnd[0] = nbolo*ntslice-1; lutndf = smf_get_ndfid( mapcoordloc, "LUT", "UPDATE", "UNKNOWN", "_INTEGER", 1, lbnd, ubnd, status ); if( *status == SAI__OK ) { /* store the NDF identifier */ file->mapcoordid = lutndf; /* Create sky to output grid mapping using the base coordinates to get the coordinates of the tangent point if it hasn't been done yet. */ sky2map = astGetMapping( outfset, AST__CURRENT, AST__BASE ); } /* Before mapping the LUT, first check for existing WCS information and LBND/UBND for the output map. If they are already correct don't bother re-calculating the LUT! */ if( *status == SAI__OK ) { /* Try reading in the WCS information */ kpg1Wread( mapcoordloc, "WCS", &fstemp, status ); oldfset = (AstFrameSet*)fstemp; if( *status == SAI__OK ) { /* Check that the old and new mappings are the same by checking that combining one with the inverse of the other reduces to a UnitMap. */ map2sky_old = astGetMapping( oldfset, AST__BASE, AST__CURRENT ); testcmpmap = astCmpMap( map2sky_old, sky2map, 1, " " ); testsimpmap = astSimplify( testcmpmap ); if( astIsAUnitMap( testsimpmap ) ) { /* The mappings are the same, now just check the pixel bounds in the output map */ lbnd_temp[0] = 1; ubnd_temp[0] = 2; bndndf = smf_get_ndfid( mapcoordloc, "LBND", "READ", "UNKNOWN", "_INTEGER", 1, lbnd_temp, ubnd_temp, status ); if( *status == SAI__OK ) { ndfMap( bndndf, "DATA", "_INTEGER", "READ", data_pntr, &nmap, status ); data_index = data_pntr[0]; if( *status == SAI__OK ) { lbnd_old[0] = data_index[0]; lbnd_old[1] = data_index[1]; } ndfAnnul( &bndndf, status ); } bndndf = smf_get_ndfid( mapcoordloc, "UBND", "READ", "UNKNOWN", "_INTEGER", 1, lbnd_temp, ubnd_temp, status ); if( *status == SAI__OK ) { ndfMap( bndndf, "DATA", "_INTEGER", "READ", data_pntr, &nmap, status ); data_index = data_pntr[0]; if( *status == SAI__OK ) { ubnd_old[0] = data_index[0]; ubnd_old[1] = data_index[1]; } ndfAnnul( &bndndf, status ); } if( *status == SAI__OK ) { /* If we get this far finally do the bounds check! */ if( (lbnd_old[0] == lbnd_out[0]) && (lbnd_old[1] == lbnd_out[1]) && (ubnd_old[0] == ubnd_out[0]) && (ubnd_old[1] == ubnd_out[1]) ) { docalc = 0; /* We don't have to re-calculate the LUT */ msgOutif(MSG__VERB," ",FUNC_NAME ": Existing LUT OK", status); } } } /* Bad status / AST errors at this point due to problems with MAPCOORD. Annul and continue calculating new MAPCOORD extension. */ astClearStatus; errAnnul(status); } else { /* Bad status due to non-existence of MAPCOORD. Annul and continue */ errAnnul(status); } } } /* If we need to calculate the LUT do it here */ if( docalc && (*status == SAI__OK) ) { msgOutif(MSG__VERB," ", FUNC_NAME ": Calculate new LUT", status); /* Get the increment in time slices between full Mapping calculations. The Mapping for intermediate time slices will be approximated. */ dim_t dimval; smf_get_nsamp( config, "TSTEP", data, &dimval, status ); tstep = dimval; /* Get space for the LUT */ if( doextension ) { /* Map the LUT array */ ndfMap( lutndf, "DATA", "_INTEGER", "WRITE", data_pntr, &nmap, status ); data_index = data_pntr[0]; if( *status == SAI__OK ) { lut = data_index; } else { errRep( FUNC_NAME, "Unable to map LUT in MAPCOORD extension", status); } } else { /* alloc the LUT and THETA arrays */ lut = astMalloc( (nbolo*ntslice)*sizeof(*(data->lut)) ); theta = astMalloc( ntslice*sizeof(*(data->theta)) ); } /* Retrieve the sky2map mapping from the output frameset (actually map2sky) */ oskyfrm = astGetFrame( outfset, AST__CURRENT ); sky2map = astGetMapping( outfset, AST__BASE, AST__CURRENT ); /* If the longitude and latitude is being dumped, create new NDFs to hold them, and map them. */ if( config ) { astMapGet0I( config, "EXPORTLONLAT", &exportlonlat ); if( exportlonlat ) { lon_ptr = smf1_calc_mapcoord1( data, nbolo, ntslice, oskyfrm, &indf_lon, 1, status ); lat_ptr = smf1_calc_mapcoord1( data, nbolo, ntslice, oskyfrm, &indf_lat, 2, status ); } } /* Invert the mapping to get Output SKY to output map coordinates */ astInvert( sky2map ); /* Create a SkyFrame in absolute coordinates */ abskyfrm = astCopy( oskyfrm ); astClear( abskyfrm, "SkyRefIs" ); astClear( abskyfrm, "SkyRef(1)" ); astClear( abskyfrm, "SkyRef(2)" ); if( *status == SAI__OK ) { /* --- Begin parellelized portion ------------------------------------ */ /* Start a new job context. Each call to thrWait within this context will wait until all jobs created within the context have completed. Jobs created in higher contexts are ignored by thrWait. */ thrBeginJobContext( wf, status ); /* Allocate job data for threads */ job_data = astCalloc( nw, sizeof(*job_data) ); if( *status == SAI__OK ) { /* Set up job data, and start calculating pointing for blocks of time slices in different threads */ if( nw > (int) ntslice ) { step = 1; } else { step = ntslice/nw; } for( ii=0; (*status==SAI__OK)&&(ii<nw); ii++ ) { pdata = job_data + ii; /* Blocks of time slices */ pdata->t1 = ii*step; pdata->t2 = (ii+1)*step-1; /* Ensure that the last thread picks up any left-over tslices */ if( (ii==(nw-1)) && (pdata->t1<(ntslice-1)) ) { pdata->t2=ntslice-1; } pdata->ijob = -1; pdata->lut = lut; pdata->theta = theta; pdata->lbnd_out = lbnd_out; pdata->moving = moving; pdata->ubnd_out = ubnd_out; pdata->tstep = tstep; pdata->lat_ptr = lat_ptr; pdata->lon_ptr = lon_ptr; pdata->fts_port = fts_port; /* Make deep copies of AST objects and unlock them so that each thread can then lock them for their own exclusive use */ pdata->abskyfrm = astCopy( abskyfrm ); astUnlock( pdata->abskyfrm, 1 ); pdata->sky2map = astCopy( sky2map ); astUnlock( pdata->sky2map, 1 ); /* Similarly, make a copy of the smfData, including only the header information which each thread will need in order to make calls to smf_rebin_totmap */ pdata->data = smf_deepcopy_smfData( data, 0, SMF__NOCREATE_FILE | SMF__NOCREATE_DA | SMF__NOCREATE_FTS | SMF__NOCREATE_DATA | SMF__NOCREATE_VARIANCE | SMF__NOCREATE_QUALITY, 0, 0, status ); smf_lock_data( pdata->data, 0, status ); } for( ii=0; ii<nw; ii++ ) { /* Submit the job */ pdata = job_data + ii; pdata->ijob = thrAddJob( wf, THR__REPORT_JOB, pdata, smfCalcMapcoordPar, 0, NULL, status ); } /* Wait until all of the jobs submitted within the current job context have completed */ thrWait( wf, status ); } /* End the current job context. */ thrEndJobContext( wf, status ); /* --- End parellelized portion -------------------------------------- */ /* Set the lut pointer in data to the buffer */ data->lut = lut; data->theta = theta; /* Write the WCS for the projection to the extension */ if( doextension ) { kpg1Wwrt( (AstObject*)outfset, "WCS", mapcoordloc, status ); /* Write the pixel bounds for the map to the extension */ lbnd_temp[0] = 1; /* Don't get confused! Bounds for NDF that will */ ubnd_temp[0] = 2; /* contain the bounds for the output 2d map! */ bndndf = smf_get_ndfid( mapcoordloc, "LBND", "UPDATE", "UNKNOWN", "_INTEGER", 1, lbnd_temp, ubnd_temp, status ); ndfMap( bndndf, "DATA", "_INTEGER", "WRITE", data_pntr, &nmap, status ); data_index = data_pntr[0]; if( *status == SAI__OK ) { data_index[0] = lbnd_out[0]; data_index[1] = lbnd_out[1]; } else { errRep( FUNC_NAME, "Unable to map LBND in MAPCOORD extension", status); } ndfAnnul( &bndndf, status ); bndndf = smf_get_ndfid( mapcoordloc, "UBND", "UPDATE", "UNKNOWN", "_INTEGER", 1, lbnd_temp, ubnd_temp, status ); ndfMap( bndndf, "DATA", "_INTEGER", "WRITE", data_pntr, &nmap, status ); data_index = data_pntr[0]; if( *status == SAI__OK ) { data_index[0] = ubnd_out[0]; data_index[1] = ubnd_out[1]; } else { errRep( FUNC_NAME, "Unable to map UBND in MAPCOORD extension", status); } ndfAnnul( &bndndf, status ); } } } /* Clean Up */ if( testsimpmap ) testsimpmap = astAnnul( testsimpmap ); if( testcmpmap ) testcmpmap = astAnnul( testcmpmap ); if( map2sky_old ) map2sky_old = astAnnul( map2sky_old ); if( oldfset ) oldfset = astAnnul( oldfset ); if (sky2map) sky2map = astAnnul( sky2map ); if (bolo2map) bolo2map = astAnnul( bolo2map ); if( abskyfrm ) abskyfrm = astAnnul( abskyfrm ); if( oskyfrm ) oskyfrm = astAnnul( oskyfrm ); if( mapcoordloc ) datAnnul( &mapcoordloc, status ); if( indf_lat != NDF__NOID ) ndfAnnul( &indf_lat, status ); if( indf_lon != NDF__NOID ) ndfAnnul( &indf_lon, status ); /* If we get this far, docalc=0, and status is OK, there must be a good LUT in there already. Map it so that it is accessible to the caller; "UPDATE" so that the caller can modify it if desired. */ if( (*status == SAI__OK) && (docalc == 0) ) { smf_open_mapcoord( data, "UPDATE", status ); } /* Clean up job data */ if( job_data ) { for( ii=0; (*status==SAI__OK)&&(ii<nw); ii++ ) { pdata = job_data + ii; if( pdata->data ) { smf_lock_data( pdata->data, 1, status ); smf_close_file( &(pdata->data), status ); } astLock( pdata->abskyfrm, 0 ); pdata->abskyfrm = astAnnul( pdata->abskyfrm ); astLock( pdata->sky2map, 0 ); pdata->sky2map = astAnnul( pdata->sky2map ); } job_data = astFree( job_data ); } }
HDSLoc * smf_get_smurfloc( const smfData * data, const char * accmode, int * status ) { if (*status != SAI__OK) return NULL; return smf_get_xloc( data, SMURF__EXTNAME, SMURF__EXTTYPE, accmode, 0, 0, status ); }
void smf_calc_stareimage( smfData *data, const int naver, int *status) { double *avdata = NULL; /* Pointer to averaged data */ int dims[2]; /* Dimensions of the stored image */ smfHead *hdr; /* Header information */ int j; /* Loop counter */ size_t npts; /* Number of points in the averaged data */ int numaver; /* Number of samples to average */ int numimages; /* Number of output STARE images */ int numsamples; /* Number of time slices (samples) */ int remainder; /* Remainder from dividing no of timeslices by number of frames to average */ HDSLoc *scu2redloc = NULL; /* Locator to SCU2RED extension */ double steptime; /* Step time per sample, sec */ double *zero = NULL; /* Bolometer zero points */ if ( *status != SAI__OK ) return; /* Check we have time-series data */ if ( data->ndims != 3) { *status = SAI__ERROR; errRep(FUNC_NAME, "File does not contain time series data - unable to process", status); return; } /* Check we have flatfielded data */ if ( !smf_history_check( data, "smf_flatfield", status) ) { if ( *status == SAI__OK ) { *status = SAI__ERROR; errRep(FUNC_NAME, "Data have not been flatfielded ", status); return; } } /* Do we have STARE data? */ hdr = data->hdr; if ( hdr->obsmode == SMF__OBS_STARE ) { msgOutif(MSG__VERB," ", "Processing STARE data", status); if (smf_history_check( data, "smf_calc_stareimage", status) ) { msgOut(" ", "File contains STARE data which has already been processed: proceeding but this WILL OVERWRITE any STARE images already written into the SCU2RED extension", status); } /* Number of output STARE images */ numsamples = (data->dims)[2]; /* If naver < 0 then re-calculate to give 1-second images */ if ( naver < 0 ) { smf_fits_getD(hdr, "STEPTIME", &steptime, status); numaver = 1.0 / steptime; } else if ( naver > numsamples ) { msgOutif(MSG__NORM, "", "Warning: NAVER exceeds the number of samples - will average entire time stream to create a single image", status); numaver = numsamples; } else { numaver = naver; } numimages = numsamples / numaver; /* Warn user if the number to average is not a factor of the number of time slices */ remainder = numsamples % numaver; if ( remainder != 0 ) { msgSeti("R", remainder); msgSeti("N", numaver); msgSeti("T", numsamples); msgOutif(MSG__NORM, "", "Warning: NAVER (^N) is not a factor of the number of time slices (^T): final ^R samples will not be included in an image", status); } /* Helpful info for the user */ msgSeti("N",numimages); if ( numimages == 1 ) { msgSetc("IM","image"); } else { msgSetc("IM","images"); } msgOutif( MSG__VERB, "", "Calculating ^N STARE ^IM", status ); /* Obtain a locator for the extension where for the images will be stored */ scu2redloc = smf_get_xloc(data, "SCU2RED", "SCUBA2_MAP_ARR", "WRITE", 0, NULL, status); /* Set the dimensions of the output images - they are all the same so they can be safely set outside the loop below */ dims[0] = (data->dims)[0]; dims[1] = (data->dims)[1]; /* Loop over the number of output images */ for ( j=0; j<numimages; j++) { /* Average the time stream data over the desired interval */ smf_average_dataD( data, j*numaver, numaver, 1, &avdata, &npts, status ); /* Store the averaged data as an image */ smf_store_image( data, scu2redloc, j, 2, dims, numaver, 0, 0, avdata, NULL, status); avdata = astFree( avdata ); zero = astFree( zero ); } /* Add a history entry if everything's OK */ smf_history_add(data, "smf_calc_stareimage", status ); /* Release SCU2RED locator */ datAnnul( &scu2redloc, status ); } else { msgOutif(MSG__NORM," ", "Input file is not a STARE observation - ignoring", status); } }