def save_crio_ini(ant_str=None): ''' Copies crio.ini files from crios to a standard location appended with the current date. These files can be transferred back to the crio in case the crio file gets corrupted. ''' if ant_str is None: print "Error: No antenna list given." return 0 ants = ant_str2list(ant_str) crio = ['crio' + str(i + 1) for i in ants] userpass = '******' folder = "/home/sched/Dropbox/PythonCode/Current/crio_inis/" os.chdir(folder) datstr = Time.now().iso[:10] for c in crio: # Get crio.ini lines f = urllib2.urlopen('ftp://' + userpass + c + '.solar.pvt/ni-rt/startup/crio.ini', timeout=0.5) lines = f.readlines() f.close() # Write crio.ini lines to file f = open(c + '-' + datstr + '.ini', 'w') for line in lines: f.write(line) f.close() print 'crio.ini files copied from', crio
def inspect(files, vmin=0.1, vmax=10, ant_str='ant1-13', srcchk=True): ''' Given the list of filenames output by calIDB(), reads and displays a log-scaled median (over baselines) spectrogram for quick check. Input parameters allow the displayed spectrogram to be scaled (vmin & vmax, which both should be positive since the spectrogram is log-scaled), and the list of antennas to use for the median. The output is the original data (out) and the median spectrogram (not log scaled or clipped) obtained for baselines between 150 and 1000 nsec involving the antennas in ant_str. Note, the display for this routine is just for a quick sanity check to see if the entire timerange for the flare looks okay. The nicely formatted plot with background subtraction will be done using make_plot(). Inputs: files The list of calibrated IDB files (output of calIDB). No default. vmin, vmax The min and max values to use for the scaling of the quick look plot. Both should be positive since the plot is log-scaled. Default 0.1, 10 ant_str The standard string of antennas to use (see util.ant_str2list()). Default is all antennas 'ant1-13' srcchk Not often needed, if True this forces all of the files to have the same source name, which is generally desired. Files in the file list that have different source names are skipped. It can be set to False to override this behavior. Default is True. Outputs: out Standard output dictionary of read_idb, containing all of the data read from the files. This includes the list of times and frequencies, but also all of the other data from the files for convenience. spec The actual spectrogram data obtained from forming the median over the given antenna list, for baseline lengths 150-1000 nsec. This is not log-scaled or clipped. ''' out = ri.read_idb(files, srcchk=srcchk) times = Time(out['time'],format='jd') nt, = out['time'].shape blen = np.sqrt(out['uvw'][:,int(nt/2),0]**2 + out['uvw'][:,int(nt/2),1]**2) ants = ant_str2list(ant_str) idx = [] for k,i in enumerate(ants[:-1]): for j in ants[k+1:]: idx.append(ri.bl2ord[i,j]) idx = np.array(idx) good, = np.where(np.logical_and(blen[idx] > 150.,blen[idx] < 1000.)) spec = np.nanmedian(np.abs(out['x'][idx[good],0]),0) nf, nt = spec.shape plt.figure() plt.imshow(np.log10(np.clip(spec,vmin,vmax))) return out,spec
def combine_subtracted(out, bgidx=[100,110], vmin=0.1, vmax=10, ant_str='ant1-13'): # Recreate spec from out, after subtracting times = Time(out['time'],format='jd') nt, = out['time'].shape nf, = out['fghz'].shape blen = np.sqrt(out['uvw'][:,int(nt/2),0]**2 + out['uvw'][:,int(nt/2),1]**2) ants = ant_str2list(ant_str) idx = [] for k,i in enumerate(ants[:-1]): for j in ants[k+1:]: idx.append(ri.bl2ord[i,j]) idx = np.array(idx) good, = np.where(np.logical_and(blen[idx] > 150.,blen[idx] < 1000.)) bgd = np.nanmean(np.abs(out['x'][idx[good],0,:,120:130]),2).repeat(nt).reshape(len(idx[good]),nf,nt) spec = np.nanmean(np.abs(out['x'][idx[good],0])-bgd,0) return spec
def reload_crio_ini(ant_str=None): '''This function takes a standard string of antennnas and finds the newest version of the ini file for each crio and loads them via ftp to those crios. An example antenna string is as follows: "ant1-5 ant7 ant9-12" The function returns the number of crios that were successfully updated. Note that the function searches the /home/sched/Dropbox/PythonCode/Current/crio_inis/ for the most recent crio file. The files must have the format of crio##-yyyy-mm-dd.ini where ## is a one or two digit number denoting the crio, yyyy is the year, mm is the month and dd is the day of the ini file. ''' if ant_str is None: print "Error: No antenna list given." return 0 ants = ant_str2list(ant_str) crio = ['crio' + str(i + 1) for i in ants] folder = "/home/sched/Dropbox/PythonCode/Current/crio_inis/" os.chdir(folder) ncrio = 0 for c in crio: files = glob.glob(c + "-????-??-??.ini") if len(files) == 0: print "No files found for", c else: t = [] for f in files: t.append(Time(f[-14:-4], out_subfmt='date')) session = ftplib.FTP(c + '.solar.pvt', 'admin', 'observer') session.cwd("ni-rt/startup") f = open(files[t.index(max(t))], 'r') session.storbinary("STOR crio.ini", f) f.close() session.close() ncrio += 1 print "ini file written to", c print "crio.ini files written to", ncrio, "CRIOs" return ncrio
def graph(out, refcal=None, ant_str='ant1-13', bandplt=[5, 11, 17, 23], scanidx=None, pol=0, tformat='%H:%M'): '''Produce a figure showing phases and amplitudes of selected antennas, bands, and polarization. Optionally takes in time averaged 'refcal' (can be from refcal_anal() or sql database) to show the selected time range and plot the averaged phase and amplitudes''' # takes input from rd_refcal (out) date_format = mdates.DateFormatter(tformat) # make a color plot showing the phase # ri.summary_plot_pcal(out) if scanidx: scanlist = [out['scanlist'][i] for i in scanidx] tstlist = [out['tstlist'][i] for i in scanidx] tedlist = [out['tedlist'][i] for i in scanidx] bandnames = [out['bandnames'][i] for i in scanidx] vis = [out['vis'][i] for i in scanidx] times = [out['times'][i] for i in scanidx] else: scanlist = out['scanlist'] tstlist = out['tstlist'] tedlist = out['tedlist'] bandnames = out['bandnames'] vis = out['vis'] times = out['times'] nscan = len(scanlist) ant_list = ant_str2list(ant_str) nant = len(ant_list) bds0 = bandplt nband = len(bds0) f1, ax1 = plt.subplots(nant, nband, figsize=(12, 8)) f2, ax2 = plt.subplots(nant, nband, figsize=(12, 8)) for n, scan in enumerate(scanlist): ts = Time(times[n], format='jd').plot_date try: # make plots of phase and amp vs. time on all 34 bands for ant in ant_list: for b, bd in enumerate(bds0): ph_deg = np.angle(vis[n][ant, pol, bd - 1], deg=True) amp = np.abs(vis[n][ant, pol, bd - 1]) ax1[ant, b].plot_date(ts, ph_deg, '.', markersize=5) ax1[ant, b].xaxis.set_major_formatter(date_format) ax2[ant, b].plot_date(ts, amp, '.', markersize=5) ax2[ant, b].xaxis.set_major_formatter(date_format) ax1[ant, b].set_ylim([-180., 180.]) if ant == 0: ax1[ant, b].set_title('Band ' + str(bd)) ax2[ant, b].set_title('Band ' + str(bd)) if b == 0: ax1[ant, b].text(-0.4, 0.5, 'Ant ' + str(ant + 1), ha='center', va='center', transform=ax1[ant, b].transAxes, fontsize=10) ax2[ant, b].text(-0.4, 0.5, 'Ant ' + str(ant + 1), ha='center', va='center', transform=ax2[ant, b].transAxes, fontsize=10) else: ax1[ant, b].set_yticks([]) ax2[ant, b].set_yticks([]) except: print 'Failure in plotting scan: ', scan continue if refcal: for ant in ant_list: for b, bd in enumerate(bds0): phavg = np.degrees(refcal['pha'][ant, pol, bd - 1]) ampavg = refcal['amp'][ant, pol, bd - 1] flg = refcal['flag'][ant, pol, bd - 1] if flg == 0: if 't_bg' in refcal.keys(): bt = Time(refcal['t_bg'], format='jd').plot_date else: bt = Time(times[0][0], format='jd').plot_date if 't_ed' in refcal.keys(): et = Time(refcal['t_ed'], format='jd').plot_date else: et = Time(times[-1][-1], format='jd').plot_date ax1[ant, b].plot_date([bt, et], [phavg, phavg], '-r') ax1[ant, b].plot_date([bt, bt], [-200, 200], '--k') ax1[ant, b].plot_date([et, et], [-200, 200], '--k') ax2[ant, b].plot_date([bt, et], [ampavg, ampavg], '-r') ax2[ant, b].plot_date([bt, bt], [0, np.max(amp)], '--k') ax2[ant, b].plot_date([et, et], [0, np.max(amp)], '--k') ax1[ant, b].plot_date(refcal['timestamp'].plot_date, phavg, 'o') ax2[ant, b].plot_date(refcal['timestamp'].plot_date, ampavg, 'o')
def multi_mountcal(filename, ant_str=None): ''' Process an entire set of calpnt data ''' import coord_conv as cc from util import ant_str2list outdict = rd_calpnt(filename) indict_list = [] if ant_str: antlist = ant_str2list(ant_str) + 1 else: antlist = outdict['antlist'] for ant in antlist: #i = ant - 1 i, = np.where(np.array(outdict['antlist']) == ant)[ 0] # Index in outdict for specified ant if ant in [9, 10, 11, 13, 14]: # This is an equatorial mount mount = 'EQ' elif ant in [1, 2, 3, 4, 5, 6, 7, 8, 12]: # This is an azimuth-elevation mount mount = 'AZEL' # Reprocess coordinates, plus remove any -99 points good, = np.where( np.logical_and(outdict['dra'][i] > -90, outdict['ddec'][i] > -90)) npt = len(good) az = np.zeros(npt) el = np.zeros(npt) dxel = np.zeros(npt) d_el = np.zeros(npt) dra = outdict['dra'][i, good] ddec = outdict['ddec'][i, good] ra = outdict['ra'][good] dec = outdict['dec'][good] ha = outdict['ha'][good] times = outdict['time'][good] params_old = outdict['params_old'][:, i] # el_r = [] for k in range(npt): # Convert RA, Dec to Az, El, and dRA, dDec to dxel and d_el azk, elk = cc.radec2azel(ra[k], dec[k], times[k]) # Apply refraction correction (assumes elevation in degrees) # This is commented out, pending determination of whether refraction is already # accounted for in the measurements (I think it is...) #elk /= dtor # Convert to degrees #elp = elk+(1/60.)*(0.0019279 + 1.02/tan((elk + 10.3/(el+5.1))*dtor)) #elp *= dtor # Convert back to radians #el_r.append(elp) # Adjust coordinates (only needed for AZEL, but do for EQ, too for consistency) dxelk, d_elk = cc.dradec2dazel(ra[k], dec[k], times[k], dra[k] * dtor, ddec[k] * dtor) az[k] = azk el[k] = elk dxel[k] = dxelk / dtor d_el[k] = d_elk / dtor indict = { 'filename': outdict['filename'], 'ant': ant, 'dra': dra, 'ddec': ddec, 'dxel': dxel, 'd_el': d_el, 'ra': ra, 'dec': dec, 'ha': ha, 'az': az, 'el': el, 'mount': mount, 'times': times, 'params_old': params_old } # indict.update({'el_r':el_r}) # Refraction-corrected elevation indict = mntcal(indict) indict = checkfit(indict) indict_list.append(indict.copy()) return indict_list # Temporary
def sat_xy_corr(out0, out1, band=0, ant_str='ant1-13', doplot=True): ''' Analyze a pair of parallel and cross polarization calibration packet captures on a Geosat in K-band (bands 33, 34, 35, 36, 37) and return the X vs. Y delay phase corrections on all antennas 1-14. Required keyword: prtlist a list of 2 PRT filenames, the first being the parallel-feed scan, and the second being the crossed-feed scan. band the band index (0-4) corresponding to the above 5 bands Optional keyword: doplot True => plot the final result, False => no plot ''' import pcapture2 as p from util import bl2ord, ant_str2list if doplot: import matplotlib.pylab as plt antlist = ant_str2list(ant_str) nant = len(antlist) # out0 = p.rd_jspec(prtlist[0]) # Parallel scan # out1 = p.rd_jspec(prtlist[1]) # Perpendicular scan # Integrate over (10) repeated records for the desired band ph0 = np.angle(np.sum(out0['x'][:,:,:,10*band:10*(band+1)],3)) ph1 = np.angle(np.sum(out1['x'][:,:,:,10*band:10*(band+1)],3)) # Determine secular change in phase at the two times, relative to ant 1 for i in antlist: if i == antlist[0]: dp = np.zeros_like(ph0[0,0]) else: dp = lobe(ph1[bl2ord[antlist[0],i],0] - ph0[bl2ord[antlist[0],i],0]) ph0[bl2ord[i,13],2:] = lobe(ph1[bl2ord[i,13],2:]-dp) # Insert crossed-feed phases from ph1 into ph0, corrected for secular change ph0 = ph0[bl2ord[antlist,13]] # Now restrict to only baselines with ant 14 fstart = (band+32)*0.325 + 1.1 - 0.025 fghz = np.linspace(fstart,fstart+0.400,4096) nf = len(fghz) dph = np.zeros((nant+1,nf),np.float) # Determine xi_rot xi2 = ph0[:,2] - ph0[:,0] + ph0[:,3] - ph0[:,1] # This is 2 * xi, measured separately on each of 13 antennas xi_rot = lobe(np.unwrap(np.angle(np.sum(np.exp(1j*xi2),0)))/2.) # Very clever average does not suffer from wrapping issues #xi_rot = np.zeros_like(xi_rot) + np.pi/2. # *********** Zero out xi_rot for now **************** # Form differential delay phase from channels, and average them # dph14 = XY - XX - xi_rot and YY - YX + xi_rot dph14 = np.concatenate((lobe(ph0[:,2] - ph0[:,0] - xi_rot),lobe(ph0[:,1] - ph0[:,3] + xi_rot))) # 26 values for Ant 14 dph[nant] = np.angle(np.sum(np.exp(1j*dph14),0)) # Very clever average does not suffer from wrapping issues # dphi = XX - YX + xi_rot and XY - YY - xi_rot dphi = np.array((lobe(ph0[:,0] - ph0[:,3] + xi_rot),lobe(ph0[:,2] - ph0[:,1] - xi_rot))) # 2 values for Ant 14 dph[:nant] = np.angle(np.sum(np.exp(1j*dphi),0)) if doplot: figlabel = 'XY_Phase_'+str(band+33) if figlabel in plt.get_figlabels(): f = plt.figure(figlabel) ax = f.get_axes() else: f, ax = plt.subplots(4, 4, num=figlabel) ax.shape = (16,) for i in range(nant): ax[antlist[i]].plot(fghz,dphi[0,i],',') ax[antlist[i]].plot(fghz,dphi[1,i],',') ax[antlist[i]].plot(fghz,dph[i],'k,') ax[antlist[i]].set_title('Ant '+str(antlist[i]+1),fontsize=9) for i in range(2*nant): ax[13].plot(fghz,dph14[i],',') ax[13].set_title('Ant 14',fontsize=9) ax[13].plot(fghz,dph[nant],'k,') for i in range(14): ax[i].set_ylim(-4,4) f.suptitle('Multicolor: Measurements, Black: Final Results') ax[14].plot(fghz,xi_rot) for i in range(nant): ax[15].plot(fghz,xi2[i],',') # np.savez('/common/tmp/Feed_rotation/' + npzlist[0].split('/')[-1][:14] + '_delay_phase.npz', fghz=fghz, dph=dph, xi_rot=xi_rot) time = Time.now().lv xy_phase = {'antlist':antlist, 'timestamp':time, 'fghz':fghz, 'xyphase':dph, 'xi_rot':xi_rot, 'dphi':dphi, 'dph14':dph14} return xy_phase
def autocorrect(out, ant_str='ant1-13'): nt = len(out['time']) nf = len(out['fghz']) pfac1 = (out['p'][:, :, :, :-1] - out['p'][:, :, :, 1:]) / out['p'][:, :, :, :-1] trange = Time(out['time'][[0, -1]], format='jd') src_lev = gc.get_fem_level(trange) # Read FEM levels from SQL # Match times with data tidx = nearest_val_idx(out['time'], src_lev['times'].jd) # Find attenuation changes for ant in range(13): for pol in range(2): if pol == 0: lev = src_lev['hlev'][ant, tidx] else: lev = src_lev['vlev'][ant, tidx] jidx, = np.where(abs(lev[:-1] - lev[1:]) == 1) for freq in range(nf): idx, = np.where( np.logical_and( abs(pfac1[ant, pol, freq]) > 0.05, abs(pfac1[ant, pol, freq]) < 0.95)) for i in range(len(idx - 1)): if idx[i] in jidx or idx[i] in jidx - 1: out['p'][ant, pol, freq, idx[i] + 1:] /= (1 - pfac1[ant, pol, freq, idx[i]]) calfac = pc.get_calfac(trange[0]) tpcalfac = calfac['tpcalfac'] tpoffsun = calfac['tpoffsun'] hlev = src_lev['hlev'][:13, 0] vlev = src_lev['vlev'][:13, 0] attn_dict = ac.read_attncal(trange[0])[0] # Read GCAL attn from SQL attn = np.zeros((13, 2, nf)) for i in range(13): attn[i, 0] = attn_dict['attn'][hlev[i], 0, 0] attn[i, 1] = attn_dict['attn'][vlev[i], 0, 1] print 'Ant', i + 1, attn[i, 0, 20], attn[i, 1, 20] attnfac = 10**(attn / 10.) for i in range(13): print attnfac[i, 0, 20], attnfac[i, 1, 20] for i in range(nt): out['p'][:13, :, :, i] = (out['p'][:13, :, :, i] * attnfac - tpoffsun) * tpcalfac antlist = ant_str2list(ant_str) med = np.mean(np.median(out['p'][antlist], 0), 0) bg = np.median(med[:, 0:300], 1).repeat(nt).reshape(nf, nt) med -= bg pdata = np.log10(med) f, ax = plt.subplots(1, 1) vmax = np.median(np.nanmax(pdata, 1)) im = ax.pcolormesh(Time(out['time'], format='jd').plot_date, out['fghz'], pdata, vmin=1, vmax=vmax) plt.colorbar(im, ax=ax, label='Log Flux Density [sfu]') ax.xaxis_date() ax.xaxis.set_major_formatter(DateFormatter("%H:%M")) ax.set_ylim(out['fghz'][0], out['fghz'][-1]) ax.set_xlabel('Time [UT]') ax.set_ylabel('Frequency [GHz]') return out, med
def offsets2ants(t,xoff,yoff,ant_str=None): ''' Given a start time (Time object) and a list of offsets output by sp_offsets() for 13 antennas, convert to pointing coefficients (multiply by 10000), add to coefficients listed in stateframe, and send to the relevant antennas. The antennas to update are specified with ant_str (defaults to no antennas, for safety). ''' def send_cmds(cmds,acc): ''' Sends a series of commands to ACC. The sequence of commands is not checked for validity! cmds a list of strings, each of which must be a valid command ''' import socket for cmd in cmds: #print 'Command:',cmd s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.connect((acc['host'],acc['scdport'])) s.send(cmd) time.sleep(0.01) s.close() except: print 'Error: Could not send command',cmd,' to ACC.' return oldant = [8,9,10,12] if ant_str is None: print 'No antenna list specified, so there is nothing to do!' return try: timestamp = int(Time(t,format='mjd').lv) except: print 'Error interpreting time as Time() object' return from util import ant_str2list import dbutil as db import stateframe as stf accini = stf.rd_ACCfile() acc = {'host': accini['host'], 'scdport':accini['scdport']} antlist = ant_str2list(ant_str) if antlist is None: return cursor = db.get_cursor() # Read current stateframe data (as of 10 s ago) D15data = db.get_dbrecs(cursor,dimension=15,timestamp=timestamp,nrecs=1) p1_cur, = D15data['Ante_Cont_PointingCoefficient1'] p7_cur, = D15data['Ante_Cont_PointingCoefficient7'] for i in antlist: if i in oldant: # Change sign of RA offset to be HA, for old antennas (9, 10, 11 or 13) p1_inc = int(-xoff[i]*10000) else: p1_inc = int(xoff[i]*10000) p7_inc = int(yoff[i]*10000) p1_new = p1_cur[i] + p1_inc p7_new = p7_cur[i] + p7_inc print 'Updating P1 for Ant',i+1,'P1_old =',p1_cur[i],'P1_inc =',p1_inc,'P1_new =',p1_new cmd1 = 'pointingcoefficient1 '+str(p1_new)+' ant'+str(i+1) print 'Updating P7 for Ant',i+1,'P7_old =',p7_cur[i],'P7_inc =',p7_inc,'P7_new =',p7_new cmd7 = 'pointingcoefficient7 '+str(p7_new)+' ant'+str(i+1) print 'Commands to be sent:' print cmd1 print cmd7 send_cmds([cmd1],acc) send_cmds([cmd7],acc)
def autocorrect(out, ant_str='ant1-13', brange=[0, 300]): nt = len(out['time']) nf = len(out['fghz']) pfac1 = (out['p'][:, :, :, :-1] - out['p'][:, :, :, 1:]) / out['p'][:, :, :, :-1] trange = Time(out['time'][[0, -1]], format='jd') src_lev = gc.get_fem_level(trange) # Read FEM levels from SQL # Match times with data tidx = nearest_val_idx(out['time'], src_lev['times'].jd) # Find attenuation changes for ant in range(13): for pol in range(2): if pol == 0: lev = src_lev['hlev'][ant, tidx] else: lev = src_lev['vlev'][ant, tidx] jidx, = np.where(abs(lev[:-1] - lev[1:]) == 1) for freq in range(nf): idx, = np.where( np.logical_and( abs(pfac1[ant, pol, freq]) > 0.05, abs(pfac1[ant, pol, freq]) < 0.95)) for i in range(len(idx - 1)): if idx[i] in jidx or idx[i] in jidx - 1: out['p'][ant, pol, freq, idx[i] + 1:] /= (1 - pfac1[ant, pol, freq, idx[i]]) # Time of total power calibration is 20 UT on the date given tptime = Time(np.floor(trange[0].mjd) + 20. / 24., format='mjd') calfac = pc.get_calfac(tptime) tpcalfac = calfac['tpcalfac'] tpoffsun = calfac['tpoffsun'] hlev = src_lev['hlev'][:13, 0] vlev = src_lev['vlev'][:13, 0] attn_dict = ac.read_attncal(trange[0])[0] # Read GCAL attn from SQL attn = np.zeros((13, 2, nf)) for i in range(13): attn[i, 0] = attn_dict['attn'][hlev[i], 0, 0] attn[i, 1] = attn_dict['attn'][vlev[i], 0, 1] print 'Ant', i + 1, attn[i, 0, 20], attn[i, 1, 20] attnfac = 10**(attn / 10.) for i in range(13): print attnfac[i, 0, 20], attnfac[i, 1, 20] for i in range(nt): out['p'][:13, :, :, i] = (out['p'][:13, :, :, i] * attnfac - tpoffsun) * tpcalfac antlist = ant_str2list(ant_str) bg = np.zeros_like(out['p']) # Subtract background for each antenna/polarization for ant in antlist: for pol in range(2): bg[ant, pol] = np.median(out['p'][ant, pol, :, brange[0]:brange[1]], 1).repeat(nt).reshape(nf, nt) #out['p'][ant,pol] -= bg # Form median over antennas/pols med = np.mean(np.median((out['p'] - bg)[antlist], 0), 0) # Do background subtraction once more for good measure bgd = np.median(med[:, brange[0]:brange[1]], 1).repeat(nt).reshape(nf, nt) med -= bgd pdata = np.log10(med) f, ax = plt.subplots(1, 1) vmax = np.median(np.nanmax(pdata, 1)) im = ax.pcolormesh(Time(out['time'], format='jd').plot_date, out['fghz'], pdata, vmin=1, vmax=vmax) ax.axvspan(Time(out['time'][brange[0]], format='jd').plot_date, Time(out['time'][brange[1]], format='jd').plot_date, color='w', alpha=0.3) cbar = plt.colorbar(im, ax=ax) cbar.set_label('Log Flux Density [sfu]') ax.xaxis_date() ax.xaxis.set_major_formatter(DateFormatter("%H:%M")) ax.set_ylim(out['fghz'][0], out['fghz'][-1]) ax.set_xlabel('Time [UT]') ax.set_ylabel('Frequency [GHz]') return {'caldata': out, 'med_sub': med, 'bgd': bg}