def set_fem_attn(level=3, ant_str='ant1-15'): ''' Read current power and attenuation values in FEMs, and set the attenuation such that the power level will be as close to "level" as possible. ''' accini = stf.rd_ACCfile() acc = {'host': accini['host'], 'scdport': accini['scdport']} ant_list = ant_str2list(ant_str) if ant_list is None: return 'Bad antenna list' accini = stf.rd_ACCfile() hatn1 = np.zeros((10, 15), dtype='int') vatn1 = np.zeros((10, 15), dtype='int') hatn2 = np.zeros((10, 15), dtype='int') vatn2 = np.zeros((10, 15), dtype='int') hpwr = np.zeros((10, 15), dtype='float') vpwr = np.zeros((10, 15), dtype='float') # Read 10 instances of attenuation and power, and take the median to avoid # glitches for i in range(10): # Read the frontend attenuations and powers for each antenna data, msg = stf.get_stateframe(accini) for iant in range(15): fem = accini['sf']['Antenna'][iant]['Frontend']['FEM'] hatn1[i, iant] = stf.extract(data, fem['HPol']['Attenuation']['First']) vatn1[i, iant] = stf.extract(data, fem['VPol']['Attenuation']['First']) hatn2[i, iant] = stf.extract(data, fem['HPol']['Attenuation']['Second']) vatn2[i, iant] = stf.extract(data, fem['VPol']['Attenuation']['Second']) hpwr[i, iant] = stf.extract(data, fem['HPol']['Power']) vpwr[i, iant] = stf.extract(data, fem['VPol']['Power']) time.sleep(1) hatn1 = np.median(hatn1, 0).astype('int') vatn1 = np.median(vatn1, 0).astype('int') hatn2 = np.median(hatn2, 0).astype('int') vatn2 = np.median(vatn2, 0).astype('int') hpwr = np.median(hpwr, 0) vpwr = np.median(vpwr, 0) hatn2 = np.clip(hatn2 - (level - hpwr).astype('int'), 0, 31) vatn2 = np.clip(vatn2 - (level - vpwr).astype('int'), 0, 31) # Send attenuation commands to each antenna in ant_list for iant in ant_list: hatn = str(hatn1[iant]) + ' ' + str( hatn2[iant]) + ' ant' + str(iant + 1) vatn = str(vatn1[iant]) + ' ' + str( vatn2[iant]) + ' ant' + str(iant + 1) send_cmds(['HATTN ' + hatn, 'VATTN ' + vatn], acc) return 'Success'
def set_dcm_attn(roach_list,fem_level=5,nd_state='on',adc_nom=25,ant_list='ant1-13',do_plot=False): ''' Set the FEM attenuation to the given value, switch ND state to the given state and cycle through the IF bands, and find the optimum DCM attenuation needed to attain the given ADC level. Returns the corresponding DCM table ''' import copy accini = stf.rd_ACCfile() acc = {'host': accini['host'], 'scdport':accini['scdport']} # Switch noise diode to requested state if nd_state == 'on': send_cmds(['ND-ON '+ant_list],acc) else: send_cmds(['ND-OFF '+ant_list],acc) # Set FEM power level to requested level if set_fem_attn(fem_level,ant_list) == 'Failure': return time.sleep(5) dcm_table = np.zeros((34,32), dtype='int') # Set DCM state to standard values send_cmds(['DCMAUTO-OFF '+ant_list],acc) time.sleep(1) send_cmds(['DCMATTN 12 12 '+ant_list],acc) time.sleep(1) # Cycle through bands to get ADC levels for band in range(34): # Start with nominal DCM attenuation #send_cmds(['DCMATTN 12 12 '+ant_list],acc) #time.sleep(1) print 'Band:',band+1 acc_tune(band+1,acc) time.sleep(5) errstr = chk_lo1a(accini,band) if errstr != 'No error': print errstr return None # Go through ROACH list for i,ro in enumerate(roach_list): # Get ADC levels at nominal setting dcm_base = np.array([12,12,12,12],dtype='int') r.adc_levels([ro]) # Calculate new attenuation to achieve nominal level ch_atn = np.clip(((20*np.log10(ro.adc_levels/adc_nom)+dcm_base + 1)/2).astype('int')*2,0,30) # Set new attenuation levels (twice, for good measure, and check result # send_cmds(['DCMATTN '+str(ch_atn[0])+' '+str(ch_atn[1])+' ant'+str(ro.ants[0])],acc) # time.sleep(1) # send_cmds(['DCMATTN '+str(ch_atn[0])+' '+str(ch_atn[1])+' ant'+str(ro.ants[0])],acc) # time.sleep(1) # send_cmds(['DCMATTN '+str(ch_atn[2])+' '+str(ch_atn[3])+' ant'+str(ro.ants[1])],acc) # time.sleep(1) # send_cmds(['DCMATTN '+str(ch_atn[2])+' '+str(ch_atn[3])+' ant'+str(ro.ants[1])],acc) # time.sleep(1) # r.adc_levels([ro]) # ch_atn2 = np.clip(((20*np.log10(ro.adc_levels/adc_nom)+ch_atn + 1)/2).astype('int')*2,0,30) # print ' ',ro.roach_ip[:6],'Attn:',ch_atn,'Check:',ch_atn2 print ' ',ro.roach_ip[:6],'Attn:',ch_atn dcm_table[band,np.array(((ro.ants[0]-1)*2,(ro.ants[0]-1)*2+1,(ro.ants[1]-1)*2,(ro.ants[1]-1)*2+1))] = copy.copy(ch_atn) return dcm_table
def acc_tune(band): import time, socket, stateframe if type(band) is int: fsqfile = "BAND" + str(band) + ".FSQ" elif type(band) is str: if band.lower() == "solar.fsq" or band.lower() == "pcal.fsq": fsqfile = band.lower() else: print "Error: Unknown band", band return try: accini = stateframe.rd_ACCfile() except: print "Error: Could not access ACC." return cmds = ["FSEQ-OFF", "FSEQ-INIT", "WAIT", "FSEQ-FILE " + fsqfile.lower(), "FSEQ-ON"] for cmd in cmds: print "Command:", cmd s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.connect((accini["host"], accini["scdport"])) s.send(cmd) time.sleep(0.01) s.close() except: print "Error: Could not send command", cmd, " to ACC." return
def sf_log_temp(): accini = stateframe.rd_ACCfile() f = open('/tmp/stateframe.log','rb') nrecs = os.path.getsize('/tmp/stateframe.log')/accini['binsize']/10 # t1fem = zeros(nrecs) # t1tec = zeros(nrecs) # t7fem = zeros(nrecs) # t7tec = zeros(nrecs) # t8fem = zeros(nrecs) # t8tec = zeros(nrecs) # tair = zeros(nrecs) for i in range(nrecs): try: data = f.read(accini['binsize']*10) except: break keys, template, fmt = cp.deepcopy(accini['xml']) sf = decode_xml_data(data, keys, template, fmt) plot(i,sf['Antenna'][0]['Frontend']['FEM']['Temperature'],'b.') plot(i,sf['Antenna'][0]['Frontend']['TEC']['Temperature'],'r.') plot(i,sf['Antenna'][6]['Frontend']['FEM']['Temperature'],'g.') plot(i,sf['Antenna'][6]['Frontend']['TEC']['Temperature'],'.',color='orange') # plot(i,sf['Antenna'][7]['Frontend']['FEM']['Temperature'],'.',color='yellow') plot(i,sf['Antenna'][7]['Frontend']['TEC']['Temperature'],'.',color='yellow') plot(i,(sf['Schedule']['Data']['Weather']['Temperature'] - 32)*5./9,'k.')
def __init__(self): '''Create the user interface and initialize it ''' self.root = Tk() self.cmd_list = [] self.ptr = -1 global title title = 'Command box' self.root.wm_title(title) fmain = Frame(self.root) fmain.pack() # fmain = Frame() # self.nb.add(fmain,text='Main') #self.B3 = Button(text="Raw Command", command=self.send_cmd) #self.B3.pack( side = RIGHT) #command = StringVar() #self.E3 = Entry(textvariable = command) rawlabel = Label(fmain,text='Raw Command:') rawlabel.pack(side=LEFT) E3 = Entry(fmain, width=35) E3.pack( side = LEFT, expand=True, fill=X) E3.bind('<Return>',self.send_cmd) E3.bind('<Up>',self.up) E3.bind('<Down>',self.down) self.accini = stateframe.rd_ACCfile()
def __init__(self): '''Create the user interface and initialize it ''' self.root = Tk() self.cmd_list = [] self.ptr = -1 global title title = 'Command box' self.root.wm_title(title) fmain = Frame(self.root) fmain.pack() # fmain = Frame() # self.nb.add(fmain,text='Main') #self.B3 = Button(text="Raw Command", command=self.send_cmd) #self.B3.pack( side = RIGHT) #command = StringVar() #self.E3 = Entry(textvariable = command) rawlabel = Label(fmain, text='Raw Command:') rawlabel.pack(side=LEFT) E3 = Entry(fmain, width=35) E3.pack(side=LEFT, expand=True, fill=X) E3.bind('<Return>', self.send_cmd) E3.bind('<Up>', self.up) E3.bind('<Down>', self.down) self.accini = stateframe.rd_ACCfile()
def acc_tune(band): import time, socket, stateframe if type(band) is int: fsqfile = 'BAND' + str(band) + '.FSQ' elif type(band) is str: if band.lower() == 'solar.fsq' or band.lower() == 'pcal.fsq': fsqfile = band.lower() else: print 'Error: Unknown band', band return try: accini = stateframe.rd_ACCfile() except: print 'Error: Could not access ACC.' return cmds = [ 'FSEQ-OFF', 'FSEQ-INIT', 'WAIT', 'FSEQ-FILE ' + fsqfile.lower(), 'FSEQ-ON' ] for cmd in cmds: print 'Command:', cmd s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.connect((accini['host'], accini['scdport'])) s.send(cmd) time.sleep(0.01) s.close() except: print 'Error: Could not send command', cmd, ' to ACC.' return
def DCM_master_attn_cal(roach_list,ant_list='ant1-15'): ''' Perform a sequence of FEM settings, using ADC levels to deduce optimum DCM attenuation settings for all 34 bands and return the master table DCM attenuation lines. TAKES ABOUT 5 MINUTES TO COMPLETE roach_list a set of ROACH objects created with roach.py ant_list a list of antennas in the form of a string, e.g. "ant1-5 ant7" on which to adjust FEMs Default is all antennas, and an empty string means all antennas in current subarray. Returns DCM_lines list of strings, one for each band ''' accini = stf.rd_ACCfile() acc = {'host': accini['host'], 'scdport':accini['scdport']} n = len(roach_list) adc_ndon = np.zeros((34,n,4),dtype='float') # Set DCM state to standard values send_cmds(['DCMAUTO-OFF '+ant_list,'DCMATTN 12 12 '+ant_list],acc) # Set FEM attenuations to nominal send_cmds(['FEMATTN 0 '+ant_list],acc) # Cycle through bands to get "nd-on" ADC levels send_cmds(['ND-ON '+ant_list],acc) for band in range(34): acc_tune(band+1,acc) time.sleep(3) r.adc_levels(roach_list) for i,ro in enumerate(roach_list): adc_ndon[band,i] = ro.adc_levels send_cmds(['ND-OFF '+ant_list],acc) DCM_lines = make_DCM_table(roach_list,adc_ndon,dcm_base=12,adc_nom=30) return DCM_lines
def acc2sql(): ''' This is just a test version to read the stateframe once a second from the ACC and send it to the SQL server. A more complete version of this is implemented in schedule.py for "production" work. ''' # Get stateframe structure and version accini = stateframe.rd_ACCfile() sf_version = accini['version'] brange, outlist = sfdef(accini['sf']) with pyodbc.connect("DRIVER={FreeTDS};SERVER=192.168.24.106,1433; \ DATABASE=eOVSA06;UID=aaa;PWD=I@bsbn2w;") as cnxn: cursor = cnxn.cursor() lineno = 0 while 1: lineno += 1 data, msg = stateframe.get_stateframe(accini) version = stateframe.extract(data,['d',8]) if version == sf_version: bufout = transmogrify(data, brange) try: cursor.execute('insert into fBin (Bin) values (?)',pyodbc.Binary(bufout)) print 'Record '+str(lineno)+' successfully written\r', cnxn.commit() except: # An exception could be an error, or just that the entry was already inserted pass else: print 'Error: Incompatible version in stateframe.' break time.sleep(1)
def adc_cal(roach_list,ant_list='ant1-15',do_plot=False): ''' Perform a sequence of FEM settings, using ADC levels to deduce optimum DCM attenuation settings for all 34 bands. This can also reveal problems in FEM or DCM hardware. TAKES ABOUT 17 MINUTES TO COMPLETE roach_list a set of ROACH objects created with roach.py ant_list a list of antennas in the form of a string, e.g. "ant1-5 ant7" on which to adjust FEMs Default is all antennas, and an empty string means all antennas in current subarray. do_plot if True, makes a summary plot of results Returns numpy arrays : adc_nosig[34, nroach, 4] (no-signal ADC levels) adc_ndoff[34, nroach, 4] (ADC levels for ND-OFF) adc_ndon [34, nroach, 4] (ADC levels for ND-ON) ''' accini = stf.rd_ACCfile() acc = {'host': accini['host'], 'scdport':accini['scdport']} n = len(roach_list) adc_nosig = np.zeros((34,n,4),dtype='float') adc_ndoff = np.zeros((34,n,4),dtype='float') adc_ndon = np.zeros((34,n,4),dtype='float') # Set DCM state to standard values send_cmds(['DCMAUTO-OFF '+ant_list,'DCMATTN 12 12 '+ant_list],acc) # Set FEM attenuations to maximum send_cmds(['FEMATTN 15 '+ant_list],acc) # Cycle through bands to get "zero-input" ADC levels for band in range(34): acc_tune(band+1,acc) time.sleep(3) # Go through roaches and find optimum ADC levels for i,ro in enumerate(roach_list): r.adc_levels([ro]) adc_nosig[band,i] = ro.adc_levels # Set FEM attenuations to nominal send_cmds(['FEMATTN 0 '+ant_list],acc) # Cycle through bands to get "nd-on" ADC levels send_cmds(['ND-ON '+ant_list],acc) for band in range(34): acc_tune(band+1,acc) time.sleep(3) r.adc_levels(roach_list) for i,ro in enumerate(roach_list): adc_ndon[band,i] = ro.adc_levels # Cycle through bands to get "nd-off" ADC levels send_cmds(['ND-OFF '+ant_list],acc) for band in range(34): acc_tune(band+1,acc) time.sleep(3) r.adc_levels(roach_list) for i,ro in enumerate(roach_list): adc_ndoff[band,i] = ro.adc_levels if do_plot: plot_adc_cal(roach_list, adc_nosig, adc_ndoff, adc_ndon) return adc_nosig, adc_ndoff, adc_ndon
def set_fem_attn(level=3,ant_str='ant1-15'): ''' Read current power and attenuation values in FEMs, and set the attenuation such that the power level will be as close to "level" as possible. ''' accini = stf.rd_ACCfile() acc = {'host': accini['host'], 'scdport':accini['scdport']} ant_list = ant_str2list(ant_str) if ant_list is None: return 'Bad antenna list' accini = stf.rd_ACCfile() hatn1 = np.zeros((10,15),dtype='int') vatn1 = np.zeros((10,15),dtype='int') hatn2 = np.zeros((10,15),dtype='int') vatn2 = np.zeros((10,15),dtype='int') hpwr = np.zeros((10,15),dtype='float') vpwr = np.zeros((10,15),dtype='float') # Read 10 instances of attenuation and power, and take the median to avoid # glitches for i in range(10): # Read the frontend attenuations and powers for each antenna data, msg = stf.get_stateframe(accini) for iant in range(15): fem = accini['sf']['Antenna'][iant]['Frontend']['FEM'] hatn1[i,iant] = stf.extract(data,fem['HPol']['Attenuation']['First']) vatn1[i,iant] = stf.extract(data,fem['VPol']['Attenuation']['First']) hatn2[i,iant] = stf.extract(data,fem['HPol']['Attenuation']['Second']) vatn2[i,iant] = stf.extract(data,fem['VPol']['Attenuation']['Second']) hpwr[i,iant] = stf.extract(data,fem['HPol']['Power']) vpwr[i,iant] = stf.extract(data,fem['VPol']['Power']) time.sleep(1) hatn1 = np.median(hatn1,0).astype('int') vatn1 = np.median(vatn1,0).astype('int') hatn2 = np.median(hatn2,0).astype('int') vatn2 = np.median(vatn2,0).astype('int') hpwr = np.median(hpwr,0) vpwr = np.median(vpwr,0) hatn2 = np.clip(hatn2 - (level - hpwr).astype('int'),0,31) vatn2 = np.clip(vatn2 - (level - vpwr).astype('int'),0,31) # Send attenuation commands to each antenna in ant_list for iant in ant_list: hatn = str(hatn1[iant])+' '+str(hatn2[iant])+' ant'+str(iant+1) vatn = str(vatn1[iant])+' '+str(vatn2[iant])+' ant'+str(iant+1) send_cmds(['HATTN '+hatn,'VATTN '+vatn],acc) return 'Success'
def rd_sfdef(sf=None): ''' Create initial list of dictionaries representing each variable in the given dictionary sf. This routine works with either a stateframe dictionary or a scan_header dictionary. However, if sf is not given, sf is obtained from the current stateframe version, and that only works for the stateframe. ''' if sf is None: accini = stateframe.rd_ACCfile() sf = accini['sf'] mylist = walk_keys(sf,'Stateframe') return mylist
def fseq_is_running(fseqfile, accini=None): ''' Check current stateframe to see if the given sequence file is running. Returns True if so, False otherwise ''' import stateframe as stf if accini is None: accini = stf.rd_ACCfile() # Make sure this sequence is actually running, or start it if not buf, msg = stf.get_stateframe(accini) if msg != 'No Error': print 'Error reading stateframe.' return None fseq = stf.extract(buf, accini['sf']['LODM']['LO1A']['FSeqFile']) fseq = fseq.strip('\x00') # strip nulls from name result = fseq == fseqfile and stf.extract( buf, accini['sf']['LODM']['LO1A']['SweepStatus']) == 8 return result
def params2ants(indict_list): ''' Send params_new values from indict_list (output of multi_mountcal) to antennas indict_list[i]['ant'] gives the antenna to send information to indict_list[i]['params_new'] contains the parameters to send ''' import calibration as cal import stateframe as stf accini = stf.rd_ACCfile() acc = {'host': accini['host'], 'scdport': accini['scdport']} for indict in indict_list: ant = str(indict['ant']) for i in range(9): cmd = 'pointingcoefficient' + str(i + 1) + ' ' + str( indict['params_new'][i]) + ' ant' + ant cal.send_cmds([cmd], acc) print 'Coefficients for ant', ant, 'sent.' if int(ant) in [1, 2, 3, 4, 5, 6, 7, 8, 12, 14]: print 'Antenna', ant, 'controller must be rebooted before parameters take effect.'
def send_cmds(cmds): ''' 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, stateframe try: accini = stateframe.rd_ACCfile() except: print 'Error: Could not access ACC.' return for cmd in cmds: print 'Command:',cmd s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.connect((accini['host'],accini['scdport'])) s.send(cmd) time.sleep(0.01) s.close() except: print 'Error: Could not send command',cmd,' to ACC.' return
def send_cmds(cmds, acc=None): ''' 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 if acc is None: accini = stf.rd_ACCfile() acc = {'host': accini['host'], 'scdport': accini['scdport']} 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
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 old_version_test(sflog=None,sfxml=None,outbinfile=None,outtabfile=None): ''' Read stateframe log files of older versions and create output file of rearranged binary data, and corresponding stateframedef table as text file. sflog = file name of stateframe log to read sfxml = file name of corresponding XML file outbinfile = file name of output binary data file outtabfile = file name of output table text file ''' if sfxml: sf, version = rxml.xml_ptrs(sfxml) else: sf = None version = 0.0 if sflog: try: f = open(sflog,'rb') except: print 'Could not open file',sflog,'-- Exiting.' return # Get binary size and check version number data = f.read(100) if stateframe.extract(data,['d',8]) != version: print 'Stateframe log file version does not match XML version. -- Exiting' return recsize = stateframe.extract(data,sf['Binsize']) f.close() else: # No log file specified, so we will try to read directly from ACC once per second # Read one as a test and get its version number # Read from ACC accini = stateframe.rd_ACCfile() data, msg = stateframe.get_stateframe(accini) version = stateframe.extract(data,['d',8]) # Parse the stateframe dictionary and generate the brange and outlist dicts brange, outlist = sfdef(sf) # Calculate the startbytes in the list -- modifies outlist in place startbyte(outlist) stdout = sys.stdout # Save current stdout if outtabfile: # Write the table info to the given file name -- just sets stdout to the file, # writes it, and resets stdout try: sys.stdout = open(outtabfile,'w') except: print 'Could not redirect STDOUT to',outtabfile,' -- Will print to screen' sys.stdout = stdout outlist2table(outlist,version) sys.stdout = stdout # Reset to standard stdout if outbinfile: try: g = open(outbinfile,'wb') except: print 'Could not open file',outbinfile,'for writing. -- Exiting.' return if sflog: # Read from log file f = open(sflog,'rb') while 1: # Read and rearrange 1000 records try: indata = f.read(recsize) outdata = transmogrify(indata,brange) g.write(outdata) except: f.close() g.close() return else: # Read from ACC accini = stateframe.rd_ACCfile() for i in range(60): # Read from ACC and rearrange 60 records -- takes 1 min indata, msg = stateframe.get_stateframe(accini) outdata = transmogrify(indata,brange) g.write(outdata) time.sleep(1) g.close() return
def DCM_master_attn_cal(fseqfile=None, dcmattn=None, update=False): ''' New version of this command, which uses the power values in the 10gbe packet headers instead of the very slow measurement of the ADC levels themselves. This version only takes about 8 s! If update is True, it writes the results to the SQL database. Returns the DCM_master_table in the form of lines of text strings, with labels (handy for viewing). ''' import pcapture2 as p import dbutil as db import cal_header as ch import stateframe as stf bandlist = fseqfile2bandlist(fseqfile) if bandlist is None: print 'Must specify a frequency sequence.' return None # Make sure this sequence is actually running, or start it if not accini = stf.rd_ACCfile() if not fseq_is_running(fseqfile, accini): # Sequence is not running, so send ACC commands to start it send_cmds(['FSEQ-OFF'], accini) send_cmds(['FSEQ-INIT'], accini) send_cmds(['FSEQ-FILE ' + fseqfile], accini) send_cmds(['FSEQ-ON'], accini) bandlist2dcmtable(bandlist, toACC=True) time.sleep(3) if not fseq_is_running(fseqfile, accini): print 'Frequency sequence could not be started.' return None else: print 'Successfully started frequency sequence.' send_cmds(['dcmtable dcm.txt'], accini) send_cmds(['dcmauto-on'], accini) pwr = np.zeros((50, 8, 4), 'int') # Capture on eth2 interface command = 'tcpdump -i eth2 -c 155000 -w /home/user/Python/dcm2.pcap -s 1000' p.sendcmd(command) # Capture on eth3 interface command = 'tcpdump -i eth3 -c 155000 -w /home/user/Python/dcm3.pcap -s 1000' p.sendcmd(command) headers = p.list_header('/home/user/Python/dcm2.pcap') for line in headers: try: j, id, p1, p2, p3, p4 = np.array(map( int, line.split()))[[0, 3, 6, 7, 8, 9]] pwr[j, id] = (p1, p2, p3, p4) except: # This is to skip the non-data header lines in the list pass headers = p.list_header('/home/user/Python/dcm3.pcap') for line in headers: try: j, id, p1, p2, p3, p4 = np.array(map( int, line.split()))[[0, 3, 6, 7, 8, 9]] pwr[j, id] = (p1, p2, p3, p4) except: # This is to skip the non-data header lines in the list pass # Reshape to (slot, nant, npol) pwr.shape = (50, 16, 2) # # Read current frequency sequence from database # cursor = db.get_cursor() # query = 'select top 50 FSeqList from hV37_vD50 order by Timestamp desc' # fseq, msg = db.do_query(cursor, query) # if msg == 'Success': # fseqlist = fseq['FSeqList'][::-1] # Reverse the order # bandlist = ((np.array(fseqlist)-0.44)*2).astype(int) # cursor.close() if dcmattn is None: # Read current DCM_master_table from database xml, buf = ch.read_cal(2) orig_table = stf.extract(buf, xml['Attenuation']) else: # DCM attenuation is set to a constant value so create a table of such values. orig_table = np.zeros((34, 30)) + dcmattn orig_table[:, 26:] = 0 # Order pwr values according to bandlist, taking median of any repeated values new_pwr = np.zeros((34, 16, 2)) for i in range(34): idx, = np.where(bandlist - 1 == i) if len(idx) > 0: new_pwr[i] = np.median(pwr[idx], 0) new_pwr.shape = (34, 32) # Now determine the change in attenuation needed to achieve a target # value of 1600. Eliminate last two entries, corresponding to Ant16 attn = np.log10(new_pwr[:, :-2] / 1600.) * 10. new_table = (np.clip(orig_table + attn, 0, 30) / 2).astype(int) * 2 DCMlines = [] DCMlines.append( '# Ant1 Ant2 Ant3 Ant4 Ant5 Ant6 Ant7 Ant8 Ant9 Ant10 Ant11 Ant12 Ant13 Ant14 Ant15' ) DCMlines.append( '# X Y X Y X Y X Y X Y X Y X Y X Y X Y X Y X Y X Y X Y X Y X Y' ) DCMlines.append( '# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----' ) for band in range(1, 35): DCMlines.append( '{:2} : {:2} {:2} {:2} {:2} {:2} {:2} {:2} {:2} {:2} {:2} {:2} {:2} {:2} {:2} {:2} {:2} {:2} {:2} {:2} {:2} {:2} {:2} {:2} {:2} {:2} {:2} {:2} {:2} {:2} {:2}' .format(band, *new_table[band - 1])) if update: msg = ch.dcm_master_table2sql(DCMlines) if msg: print 'Success' else: print 'Error writing table to SQL database!' return DCMlines
def sfdef(sf=None): ''' Main routine to generate a dictionary list representing the stateframedef table (outlist) for either a stateframe or a scan_header dictionary, and a dictionary list of rearrangements to the binary data, brange. If sf is omitted, the current stateframe.xml file is used generate it. ''' # helper routines list_sort, sub_list, and rd_sfdef def list_sort(mylist,key): ''' Given a key whose value is numerical, sort the list of dictionaries mylist according to the key and return the new list of dictionaries ''' val = [] newlist = [] for d in mylist: val.append(d[key]) idx = numpy.array(val).argsort() for i in idx: newlist += [mylist[i]] return newlist def sub_list(mylist): ''' Given a sorted list of dictionaries mylist, separate them into lists of a given dimension. NB: entries with dimension greater than 50 are ignored and will NOT appear in the RDBMS ''' dim = mylist[0]['dimension'] lists = [] sublist = [] for d in mylist: if d['dimension'] == dim: sublist += [d] elif d['dimension'] > 50: # Skip any entries with dimension > 50 pass else: lists += [sublist] sublist = [d] dim = d['dimension'] lists += [sublist] return lists def rd_sfdef(sf): ''' Create initial list of dictionaries representing each variable in the given dictionary sf. This routine works with either a stateframe dictionary or a scan_header dictionary. However, if sf is not given, sf is obtained from the current stateframe version, and that only works for the stateframe. ''' mylist = walk_keys(sf,'Stateframe') return mylist if sf is None: accini = stateframe.rd_ACCfile() sf = accini['sf'] # This is something needed if the dictionary is a stateframe--will fail # gracefully and skip this if the dictionary is a scan header try: # This is a major breaking of the scheme, but the Parser string in the Antenna # array requires special handling: for ant in range(15): # For each antenna, add an entry to the stateframe representing the Command string size # located 4 bytes before the Command string t,loc = sf['Antenna'][ant]['Parser']['Command'] # Get Command string location sf['Antenna'][ant]['Parser'].update({'Command_Size':['i',loc-4]}) # Insert another entry pointing to 4 bytes before except KeyError: # The dictionary is probably a scan header pass # First parse the XML file to get a list of dictionaries for # stateframedef SQL table mylist = rd_sfdef(sf) # Sort the list of dictionaries by dimension newlist = list_sort(mylist,'dimension') # Separate sorted list into separate lists according to dimension lists = sub_list(newlist) brange = [] outlist = [] # Loop over separated lists for alist in lists: # Sort the list according to startbyte slist = list_sort(alist,'startbyte') outlist += slist # Step through ordered list to look for gaps, and make map of # start and end bytes for contiguous byte ranges sbyte = slist[0]['startbyte'] for i,item in enumerate(slist[:-1]): if len(item['pytype']) > 1 and item['datatype'] != 'string': # Case of "in-place" non-string array ebyte = item['startbyte']+item['fieldbytes']*item['dimension'] else: ebyte = item['startbyte']+item['fieldbytes'] if ebyte != slist[i+1]['startbyte']: # There is a gap between this and next item, but this might # be due to dimensionality of this section. Add bytes for # dimensionality and check again. if len(item['pytype']) > 1 and item['datatype'] != 'string': # Case of "in-place" non-string array -- do nothing pass else: ebyte = (ebyte - sbyte)*item['dimension'] + sbyte if ebyte != slist[i+1]['startbyte']: # This is indeed a gap, so save byte range and start a # new byte range brange.append({'sbyte':sbyte,'ebyte':ebyte}) sbyte = slist[i+1]['startbyte'] item = slist[-1] ebyte = item['startbyte']+item['fieldbytes'] # Take care of dimensionality of last item if len(item['pytype']) > 1: ebyte = (ebyte - item['startbyte'])*item['dimension'] + item['startbyte'] #print '5:',sbyte, (ebyte-slist[-1]['startbyte'])/slist[-1]['dimension'] + slist[-1]['startbyte'], slist[-1]['dimension'] else: ebyte = (ebyte - sbyte)*item['dimension'] + sbyte #print '5:',sbyte, (ebyte-sbyte)/slist[-1]['dimension'] + sbyte, slist[-1]['dimension'] brange.append({'sbyte':sbyte,'ebyte':ebyte}) # At this point, we should have a complete map of the ordered byte # ranges into original binary data, in variable brange. return brange, outlist