def fill_in_summary(self, summaryfile): print('Loading {}'.format(summaryfile)) with fits.open(summaryfile, memmap=False) as hdul: header = hdul[0].header hdudict = dict(header.items()) self.ra = np.degrees(hdudict['RightAscension']) self.dec = np.degrees(hdudict['Declination']) self.restfreq = None if 'RESTFREQ1' in hdudict: self.resfreq = hdudict['RESTFREQ1'] try: self.date_obs = Time(hdudict['DATE-OBS']) except KeyError: self.date_obs = Time(hdudict['DATE']) try: self.obsid = int(hdudict['OBSID']) except (KeyError, ValueError): self.obsid = 9999 with fits.open(os.path.join(self.dirname, self.GROUPING), memmap=False) as grouphdul: groupheader = grouphdul[0].header groupdict = dict(groupheader.items()) for key in hdudict.keys(): if key in groupdict: groupheader[key] = hdudict[key] groupheader['RA'] = self.ra groupheader['DEC'] = self.dec groupheader['DATE-OBS'] = self.date_obs.value groupheader['MJD-OBS'] = self.date_obs.mjd groupheader['SCANNUM'] = self.obsid grouphdul.writeto('tmp.fits', overwrite=True) force_move_file('tmp.fits', os.path.join(self.dirname, self.GROUPING)) with fits.open(os.path.join(self.dirname, self.SCAN), memmap=False) as scanhdul: scanheader = reset_all_keywords(scanhdul[1].header) scandict = dict(scanheader.items()) for key in hdudict.keys(): if key[:5] in ['NAXIS', 'PGCOU', 'GCOUN']: continue if key in scandict: scanheader[key] = hdudict[key] # Todo: update with correct keywords scanheader['DATE-OBS'] = self.date_obs.value scanheader['MJD'] = self.date_obs.mjd scanheader['SCANNUM'] = self.obsid scanhdul.writeto('tmp.fits', overwrite=True) force_move_file('tmp.fits', os.path.join(self.dirname, self.SCAN))
def update_scan_info(self): info = \ get_observing_strategy_from_subscan_info(self.scan_info) with fits.open(os.path.join(self.dirname, self.SCAN), memmap=False) as scanhdul: scanheader = scanhdul[1].header # Todo: update with correct keywords scanheader['CTYPE'] = info.ctype scanheader['CTYPE1'] = 'RA---GLS' scanheader['CTYPE2'] = 'DEC--GLS' scanheader['CRVAL1'] = self.ra scanheader['CRVAL2'] = self.dec scanheader['BLONGOBJ'] = self.ra scanheader['BLATOBJ'] = self.dec scanheader['LONGOBJ'] = self.ra if not info.ctype[0] == 'A' else 0 scanheader['LATOBJ'] = self.dec if not info.ctype[0] == 'A' else 0 scanheader['EQUINOX'] = 2000. scanheader['GRPLC1'] = 'GROUPING.fits' scanheader['LST'] = self.lst scanheader['LATPOLE'] = 90. scanheader['LONPOLE'] = 0. scanheader['PATLONG'] = 0 scanheader['MOVEFRAM'] = False if info.ctype == 'ALON/ALAT': scanheader['WCSNAME'] = 'Absolute horizontal' scanheader['SCANTYPE'] = info.stype.upper() scanheader['SCANDIR'] = info.direction.upper() scanheader['SCANXVEL'] = info.scanvel scanheader['SCANTIME'] = info.scantime scanheader['SCANMODE'] = info.mode.upper() scanheader['SCANGEOM'] = info.geom.upper() scanheader['SCANLINE'] = 1 scanheader['SCANLEN'] = np.degrees(info.length) scanheader['SCANYSPC'] = np.degrees(info.sep[1]) scanheader['SCANXSPC'] = np.degrees(info.sep[0]) scanheader['SCANPAR1'] = -999 scanheader['SCANPAR2'] = -999 scanheader['ZIGZAG'] = info.zigzag scanheader['PHASE1'] = 'sig' scanheader['PHASE2'] = 'sig' scanheader['NOBS'] = info.nobs scanheader['NSUBS'] = info.nobs scanheader['WOBCYCLE'] = 0. scanheader['WOBDIR'] = 'NONE' scanheader['WOBMODE'] = 'NONE' scanheader['WOBPATT'] = 'NONE' scanhdul.writeto('tmp.fits', overwrite=True) force_move_file('tmp.fits', os.path.join(self.dirname, self.SCAN))
def add_febe(self, febe, feed_info, feed, meta, bands=None): if bands is None: bands = [1] polar = 'N' polar_code = polar[0] febe_name = febe + '-FEBEPAR.fits' with fits.open( os.path.join(self.template_dir, 'FLASH460L-XFFTS-FEBEPAR.fits'), memmap=False) as febe_template: febe_template[1].header = \ reset_all_keywords(febe_template[1].header) febedata = Table(febe_template[1].data) # FEBEFEED stores the total number of feeds for the receiver in # use. A receiver outputting two polarisations counts as two # feeds. For an array, count the total no. of pixels, even if # not all in use. febedata['USEBAND'] = np.array([bands]) febedata['NUSEFEED'] = np.array([[2]]) febedata['USEFEED'] = \ np.array([[feed * 2 + 1, feed * 2 + 2, feed * 2 + 1, feed * 2 + 2]]) febedata['BESECTS'] = np.array([[0]]) febedata['FEEDTYPE'] = np.array([[1, 2, 3, 4]]) febedata['POLTY'][:] = np.array([polar_code]) febedata['POLA'][:] = np.array([[0., 0.]]) new_hdu = fits.table_to_hdu(febedata) febe_template[1].data = new_hdu.data # TODO: fill in the information given in the subscan[ch] new_febe = os.path.join(self.dirname, febe_name) febe_template[1].header['DATE-OBS'] = self.date_obs.fits febe_template[1].header['FEBE'] = febe febe_template[1].header['FEBEFEED'] = self.nfeeds * 2 febe_template[1].header['NUSEBAND'] = max(bands) febe_template[1].header['NPHASES'] = 1 febe_template[1].header['SWTCHMOD'] = 'NONE' febe_template[1].header['SCANNUM'] = self.obsid if 'Q' in feed_info[feed][bands[0]].keys(): febe_template[1].header['FDTYPCOD'] = '1:L, 2:R, 3:Q, 4:U' else: febe_template[1].header['FDTYPCOD'] = '1:L, 2:R' febe_template.writeto('tmp.fits', overwrite=True) force_move_file('tmp.fits', new_febe) with fits.open(os.path.join(self.dirname, self.SCAN), memmap=False) as scan: newtable = Table(scan[1].data) if newtable['FEBE'][0].strip() == 'EMPTY': newtable['FEBE'][0] = febe else: newtable.add_row([febe]) new_hdu = fits.table_to_hdu(newtable) scan[1].data = new_hdu.data scanheader = scan[1].header scanheader['SITELONG'] = np.degrees(meta['SiteLongitude']) scanheader['SITELAT'] = np.degrees(meta['SiteLatitude']) scanheader['SITEELEV'] = meta['SiteHeight'] diameter = 64. if meta['site'].lower().strip() == 'srt' else 32. scanheader['DIAMETER'] = diameter scanheader['PROJID'] = meta['Project_Name'] scan.writeto('tmp.fits', overwrite=True) force_move_file('tmp.fits', os.path.join(self.dirname, self.SCAN)) return febe_name
def add_subscan(self, scanfile, detrend=False): print('Loading {}'.format(scanfile)) subscan = read_data_fitszilla(scanfile) subscan_info = get_subscan_info(subscan) self.scan_info.add_row(subscan_info[0]) time = Time(subscan['time'] * u.day, scale='utc', format='mjd') if self.date_obs.mjd > time[0].mjd: self.date_obs = time[0] if self.site is None: self.site = subscan.meta['site'] chans = get_chan_columns(subscan) combinations = classify_chan_columns(chans) if self.nfeeds is None: self.nfeeds = len(combinations.keys()) for feed in combinations: felabel = subscan.meta['receiver'] + '{}'.format(feed) febe = felabel + '-' + subscan.meta['backend'] datapar = os.path.join(self.template_dir, '1', 'FLASH460L-XFFTS-DATAPAR.fits') with fits.open(datapar, memmap=False) as subs_par_template: n = len(subscan) # ------------- Update DATAPAR -------------- subs_par_template[1] = \ _copy_hdu_and_adapt_length(subs_par_template[1], n) newtable = Table(subs_par_template[1].data) newtable['MJD'] = subscan['time'] newtable['LST'][:] = \ time.sidereal_time('apparent', locations[subscan.meta['site']].lon ).value if newtable['LST'][0] < self.lst: self.lst = newtable['LST'][0] newtable['INTEGTIM'][:] = \ subscan['Feed0_LCP'].meta['sample_rate'] newtable['RA'] = subscan['ra'].to(u.deg) newtable['DEC'] = subscan['dec'].to(u.deg) newtable['AZIMUTH'] = subscan['az'].to(u.deg) newtable['ELEVATIO'] = subscan['el'].to(u.deg) _, direction = scantype(subscan['ra'], subscan['dec'], el=subscan['el'], az=subscan['az']) direction_cut = \ direction.replace('<', '').replace('>', '').lower() if direction_cut in ['ra', 'dec']: baslon = subscan['ra'].to(u.deg) baslat = subscan['dec'].to(u.deg) yoff = baslat.value - self.dec # GLS projection xoff = \ (baslon.value - self.ra) newtable['LONGOFF'] = xoff * np.cos(np.radians(self.dec)) newtable['LATOFF'] = yoff elif direction_cut in ['el', 'az']: warnings.warn('AltAz projection not implemented properly') baslon, baslat = \ subscan['az'].to(u.deg), subscan['el'].to(u.deg) newtable['LONGOFF'] = 0 * u.deg newtable['LATOFF'] = 0 * u.deg else: raise ValueError('Unknown coordinates') newtable['CBASLONG'] = baslon newtable['CBASLAT'] = baslat newtable['BASLONG'] = baslon newtable['BASLAT'] = baslat newhdu = fits.table_to_hdu(newtable) subs_par_template[1].data = newhdu.data subs_par_template[1].header['DATE-OBS'] = \ time[0].fits.replace('(UTC)', '') subs_par_template[1].header['LST'] = newtable['LST'][0] subs_par_template[1].header['FEBE'] = febe subs_par_template[1].header['SCANDIR'] = \ format_direction(direction_cut).upper() subs_par_template[1].header['SCANNUM'] = self.obsid outdir = str(subscan.meta['SubScanID']) mkdir_p(os.path.join(self.dirname, outdir)) new_datapar = os.path.join(outdir, febe + '-DATAPAR.fits') subs_par_template.writeto('tmp.fits', overwrite=True) force_move_file('tmp.fits', os.path.join(self.dirname, new_datapar)) arraydata = os.path.join(self.template_dir, '1', 'FLASH460L-XFFTS-ARRAYDATA-1.fits') new_arraydata_rows = [] bands = list(combinations[feed].keys()) for baseband in combinations[feed]: nbands = np.max(bands) ch = list(combinations[feed][baseband].values())[0] packed_data = pack_data(subscan, combinations[feed][baseband], detrend=detrend) # ------------- Update ARRAYDATA ------------- with fits.open(arraydata, memmap=False) as subs_template: subs_template[1] = \ _copy_hdu_and_adapt_length(subs_template[1], n) new_header = \ reset_all_keywords(subs_template[1].header) new_header['SCANNUM'] = self.obsid new_header['SUBSNUM'] = subscan.meta['SubScanID'] new_header['DATE-OBS'] = self.date_obs.fits new_header['FEBE'] = febe new_header['BASEBAND'] = baseband new_header['NUSEBAND'] = nbands new_header['CHANNELS'] = subscan.meta['channels'] new_header['SKYFREQ'] = \ subscan[ch].meta['frequency'].to('Hz').value if self.restfreq is not None: new_header['RESTFREQ'] = self.restfreq else: new_header['RESTFREQ'] = new_header['SKYFREQ'] bandwidth = subscan[ch].meta['bandwidth'].to('Hz').value new_header['BANDWID'] = bandwidth new_header['FREQRES'] = bandwidth / new_header['CHANNELS'] # Todo: check sideband new_header['SIDEBAND'] = 'USB' # Todo: check all these strange keywords. These are # probably NOT the rest frequencies! new_header['1CRVL2F'] = new_header['RESTFREQ'] new_header['1CRVL2S'] = new_header['RESTFREQ'] for i in ['1CRPX2S', '1CRPX2R', '1CRPX2F', '1CRPX2J']: new_header[i] = (new_header['CHANNELS'] + 1) // 2 subs_template[1].header = new_header newtable = Table(subs_template[1].data) newtable['MJD'] = subscan['time'] newtable['DATA'] = packed_data newhdu = fits.table_to_hdu(newtable) subs_template[1].data = newhdu.data subname = febe + '-ARRAYDATA-{}.fits'.format(baseband) new_sub = \ os.path.join(outdir, subname) subs_template.writeto('tmp.fits', overwrite=True) new_arraydata_rows.append([2, new_sub, 'URL', 'ARRAYDATA-MBFITS', subscan.meta['SubScanID'], febe, baseband]) force_move_file('tmp.fits', os.path.join(self.dirname, new_sub)) # Finally, update GROUPING file with fits.open(os.path.join(self.dirname, self.GROUPING), memmap=False) as grouping: newtable = Table(grouping[1].data) if febe not in self.FEBE: nfebe = len(list(self.FEBE.keys())) new_febe = self.add_febe(febe, combinations, feed, subscan[ch].meta, bands=bands) grouping[0].header['FEBE{}'.format(nfebe)] = febe grouping[0].header['FREQ{}'.format(nfebe)] = \ subscan[ch].meta['frequency'].to('Hz').value grouping[0].header['BWID{}'.format(nfebe)] = \ subscan[ch].meta['bandwidth'].to('Hz').value grouping[0].header['LINE{}'.format(nfebe)] = '' newtable.add_row([2, new_febe, 'URL', 'FEBEPAR-MBFITS', -999, febe, -999]) self.FEBE[febe] = new_febe newtable.add_row([2, new_datapar, 'URL', 'DATAPAR-MBFITS', -999, febe, -999]) for row in new_arraydata_rows: newtable.add_row(row) new_hdu = fits.table_to_hdu(newtable) grouping[1].data = new_hdu.data grouping[0].header['INSTRUME'] = subscan[ch].meta['backend'] grouping[0].header['TELESCOP'] = self.site grouping.writeto('tmp.fits', overwrite=True) force_move_file('tmp.fits', os.path.join(self.dirname, self.GROUPING)) if self.test: break