def load_archive(file, tscrunch=False): ar = Archive(file, verbose=False) if tscrunch: ar.tscrunch(nsubint=4) #ar.imshow() name = ar.getName() mjd = int(ar.getMJD()) fe = ar.getFrontend() nbin = ar.getNbin() data = ar.getData().reshape((ar.getNchan() * ar.getNsubint(), nbin)) return name, mjd, fe, nbin, data
class Cal(): def __init__(self, file, cont_name, cont_fits_dir, verbose=False): self.file = file self.cont_name = cont_name self.cont_fits_dir = cont_fits_dir self.verbose = verbose # Change these to match filename format... self.obs_num = self.file[-14:-10] self.num = self.file[-9:-5] self.ar = Archive(self.file, prepare=True, verbose=self.verbose) self.mjd = self.ar.getMJD() self.fe = self.ar.getFrontend() def get_onoff_data(self, tolerance=1): try: dat = np.genfromtxt("../logs/on_off.log", dtype='str') on, off, frontend, date, n = dat[:, 0], dat[:, 1], dat[:, 2], dat[:, 3], dat[:, 4] except OSError: on, off, frontend, date, n = [], [], [], [], [] l = [] # Get accurate co-ordinates for source pos, params = flux.find_source_params_f2(self.cont_name) m_coordinates = SkyCoord(f"{pos[0]} {pos[1]}", unit=(unit.hourangle, unit.degree)) for f in sorted(os.listdir(self.cont_fits_dir)): continuum_file = os.path.join(self.cont_fits_dir, f) try: fe, mjd, cont_ra, cont_dec = u.find_fe_mjd_ra_dec( continuum_file, "CAL") except Exception: continue obs_num = continuum_file[-9:-5] # Get co-ordinates from FITS file in correct units coords = SkyCoord(f"{cont_ra} {cont_dec}", unit=(unit.hourangle, unit.degree)) # Enter bizarre Henryk mind space (but tell me it doesn't work) l.append({ 'MJD': mjd, 'ON': None, 'OFF': None, 'FE': fe, 'NUM': obs_num }) # Determine if co-ordinates signify ON or OFF source observation. Tolerance in arcminutes. if m_coordinates.separation(coords) <= (tolerance * unit.arcmin): mode = 'ON' else: mode = 'OFF' # Set the filename to the correct flag in the dictionary for dict in l: if (dict['MJD'] == mjd) and (dict['FE'] == fe) and ( dict['NUM'] == obs_num) and (dict[mode] is None): dict[mode] = f # Delete the excess rows that got created for dict in reversed(l): if (dict['ON'] is None) or (dict['OFF'] is None): l.remove(dict) for d in l: on.append(d['ON']) off.append(d['OFF']) frontend.append(d['FE']) date.append(d['MJD']) n.append(d['NUM']) if self.verbose: print("Saving to logs/on_off.log") with open("../logs/on_off.log", "w") as f: data = np.array([on, off, frontend, date, n]).T np.savetxt(f, data, fmt="%s") # Returns everything as iterables return on, off, frontend, date, n def closest_continuum2psrcal(self, mjd_tol=400): try: dat = np.genfromtxt("../logs/psrcal2continuum.log", dtype='str') p, c_on, c_off, m, c_m, fronts = dat[:, 0], dat[:, 1], dat[:, 2], dat[:, 3], dat[:, 4], dat[:, 5] except OSError: # Then make the table on, off, frontend, date, _ = self.get_onoff_data(tolerance=1) p, c_on, c_off, m, c_m, fronts = [], [], [], [], [], [] for psr_cal in sorted(os.listdir(os.getcwd())): mjd_list = [] try: psr_fe, psr_mjd = u.find_fe_mjd(psr_cal, "CAL") except OSError: continue if (psr_mjd == -1) or (psr_fe == -1): continue # Compare psr_cal file with continuum files for cont_on, cont_off, cont_fe, cont_mjd in zip( on, off, frontend, date): if cont_fe == psr_fe: delta_mjd = abs(int(cont_mjd) - psr_mjd) if all(elem > delta_mjd for elem in mjd_list): mjd_list.append(delta_mjd) if delta_mjd < mjd_tol: continuum_on = str( os.path.join(self.cont_fits_dir, cont_on)) continuum_off = str( os.path.join(self.cont_fits_dir, cont_off)) if psr_cal in p: pind = p.index(psr_cal) if delta_mjd < abs( int(c_m[pind]) - psr_mjd): p[pind] = psr_cal else: p.append(psr_cal) m.append(psr_mjd) c_m.append(cont_mjd) c_on.append(continuum_on) c_off.append(continuum_off) fronts.append(psr_fe) else: continuum_on, continuum_off = None, None if self.verbose: print("Saving to logs/psrcal2continuum.log") with open("../logs/psrcal2continuum.log", "w") as f: data = np.array([p, c_on, c_off, m, c_m, fronts]).T np.savetxt(f, data, fmt="%s") return p, c_on, c_off, m, c_m, fronts def jpc(self, G=11.0, **kwargs): psr_cal, cont_on, cont_off, psr_mjd, cont_mjd, fe = self.closest_continuum2psrcal( ) freq = self.ar.freq[0] inds = [i for i, n in enumerate(psr_mjd) if int(n) == int(self.mjd)] ind = None for i in inds: if fe[i] == self.fe: ind = i psr_ar = Archive(psr_cal[ind], prepare=False, verbose=False) cont_on_ar = Archive(cont_on[ind], prepare=False, verbose=False) cont_off_ar = Archive(cont_off[ind], prepare=False, verbose=False) cal_arc_list = [] np.set_printoptions(threshold=sys.maxsize) for ar in [psr_ar, cont_on_ar, cont_off_ar]: ar.tscrunch() fr = ar.freq[0] data = ar.getData() print(data.shape) # The following commented lines are for when certain frequencies are missing if (ar is cont_on_ar) or (ar is cont_off_ar): # if self.fe == '430': # data = np.delete( data, slice(48, 56), 1 ) # fr = np.delete( fr, slice(48, 56), 0 ) if self.fe == 'lbw': # #data = np.delete( data, slice(0, 64), 1 ) #fr = np.delete( fr, slice(0, 64), 0 ) #data = np.delete( data, slice(192, 256), 1 ) #fr = np.delete( fr, slice(192, 256), 0 ) data = np.delete(data, slice(256, 320), 1) fr = np.delete(fr, slice(256, 320), 0) #data = np.delete( data, slice(320, 384), 1 ) #fr = np.delete( fr, slice(320, 384), 0 ) #print(fr) # if self.fe == '430': # for i in range(8): # data = np.insert( data, 48, np.zeros((2048)), axis = 1 ) # fr = np.insert( fr, 48, np.linspace( 455.0, 467.5, 8, endpoint = False ), 0 ) # elif self.fe == 'lbw': # for i in range(64): # data = np.insert( data, 384, np.zeros((2048)), axis = 1 ) # fr = np.insert( fr, 384, np.linspace( 1180.0, 1080.0, 64, endpoint = False ), 0 ) cal_arc_list.append({ 'ARC': ar, 'DATA': data, 'FREQS': fr, 'S_DUTY': ar.getValue('CAL_PHS'), 'DUTY': ar.getValue('CAL_DCYC'), 'BW': ar.getBandwidth() }) cal_fluxes = flux.get_fluxes(freq / 1000, self.cont_name, **kwargs) # Sometimes the calibration happens the opposite way, in which case this would be H, L L, H = self._prepare_calibration(cal_arc_list) F_ON = (H[1] / L[1]) - 1 F_OFF = (H[2] / L[2]) - 1 C0 = cal_fluxes / ((1 / F_ON) - (1 / F_OFF)) T_sys = C0 / F_OFF F_cal = (T_sys * F_OFF) / G F_cal = np.nan_to_num(F_cal, nan=0.0) # Plots F_cal if first file in series (for checking purposes) if self.num == '0001': for f in F_cal: plt.plot(f) plt.show() Fa, Fb = interpolate.interp1d( cal_arc_list[1]['FREQS'], F_cal[0], kind='cubic', fill_value='extrapolate'), interpolate.interp1d( cal_arc_list[2]['FREQS'], F_cal[1], kind='cubic', fill_value='extrapolate') Fcr, Fci = interpolate.interp1d( cal_arc_list[1]['FREQS'], F_cal[2], kind='cubic', fill_value='extrapolate'), interpolate.interp1d( cal_arc_list[2]['FREQS'], F_cal[3], kind='cubic', fill_value='extrapolate') aa = Fa(cal_arc_list[0]['FREQS']) / (H[0][0] - L[0][0]) bb = Fb(cal_arc_list[0]['FREQS']) / (H[0][1] - L[0][1]) cr = Fcr(cal_arc_list[0]['FREQS']) / (H[0][2] - L[0][2]) ci = Fci(cal_arc_list[0]['FREQS']) / (H[0][3] - L[0][3]) with open( f"../cal/{self.ar.getName()}_{self.fe}_{int(psr_mjd[ind])}_{self.obs_num}_{self.num}.cal", "w") as f: data = np.array([freq, aa, bb, cr, ci]).T np.savetxt(f, data) return freq, aa, bb, cr, ci def _prepare_calibration(self, archive_list, r_err=8): H = [] L = [] for dict in archive_list: all_high_means = [] all_low_means = [] for pol in dict['DATA']: high_means = [] low_means = [] for i, channel in enumerate(pol): start_bin = math.floor(len(channel) * dict['S_DUTY']) mid_bin = math.floor( len(channel) * (dict['S_DUTY'] + dict['DUTY'])) end_bin = mid_bin + (math.floor( len(channel) * dict['DUTY'])) bin_params = [start_bin, mid_bin, end_bin] low_mean = np.mean(channel[bin_params[0]:bin_params[1]]) high_mean = np.mean(channel[bin_params[1]:bin_params[2]]) low_mean = round(low_mean, r_err) high_mean = round(high_mean, r_err) high_means.append(high_mean) low_means.append(low_mean) all_high_means.append(high_means) all_low_means.append(low_means) H.append(all_high_means) L.append(all_low_means) H = np.array(H) L = np.array(L) return H, L