diff --git a/dstatInterface/dstat_comm.py b/dstatInterface/dstat_comm.py index 1f8105338f9693fc9b2d78182aac2c54f3051040..86da75e5ddfc9056fc33749e9a7f8ff002f0ad0e 100644 --- a/dstatInterface/dstat_comm.py +++ b/dstatInterface/dstat_comm.py @@ -14,27 +14,29 @@ class delayedSerial(serial.Serial): #overrides normal serial write so that chara time.sleep(.001) class dataCapture(mp.Process): - def __init__(self, ser_instance, pipe): + def __init__(self, ser_instance, pipe, size): mp.Process.__init__(self) + self.size = size self.serial = ser_instance self.recv_p, self.send_p = pipe def run(self): - sys.stdout.write('[%s] running ... process id: %s\n' - % (self.name, os.getpid())) + scan = 0 while True: for line in self.serial: if line.startswith('B'): - self.send_p.send(self.serial.read(size=6))#uint16 + int32 + self.send_p.send((scan,self.serial.read(size=self.size))) elif line.lstrip().startswith("no"): self.serial.flushInput() self.send_p.close() #causes EOF at other end of pipe print "closed" break - + + elif line.lstrip().startswith('S'): + scan += 1 break class SerialDevices: @@ -98,21 +100,15 @@ class Experiment: self.data_handler() #Will be overridden by experiment classes to deal with more complicated data self.data_postprocessing() - -# self.plot.updateline(self, 0) -# self.plot.redraw() - print "pipe closed" self.main_pipe.close() self.ser.close() def data_handler(self): recv_p, send_p = mp.Pipe(duplex=False) - capture_proc = dataCapture(self.ser, (recv_p, send_p)) + capture_proc = dataCapture(self.ser, (recv_p, send_p), self.databytes) capture_proc.start() send_p.close() #pipe won't trip EOFError unless all connections are closed - - updatetime = 0 while True: try: @@ -120,16 +116,11 @@ class Experiment: if self.main_pipe.recv() == 'a': self.ser.write('a') return - - voltage, current = struct.unpack('<Hl', recv_p.recv()) #uint16 + int32 + + scan, data = recv_p.recv() + voltage, current = struct.unpack('<Hl', data) #uint16 + int32 #(line, [data]) self.main_pipe.send((0, [(voltage-32768)*3000./65536, current*(1.5/self.gain/8388607)])) -# self.data[0].append((voltage-32768)*3000./65536) -# self.data[1].append(current*(1.5/self.gain/8388607)) -# if ((time.time() - updatetime) > .2): -# self.plot.updateline(self, 0) -# self.plot.redraw() -# updatetime = float(time.time()) except EOFError: print "empty" @@ -139,7 +130,8 @@ class Experiment: pass class chronoamp(Experiment): - def __init__(self, parameters, view_parameters, plot_instance, databuffer_instance): + def __init__(self, parameters, view_parameters, plot_instance, databuffer_instance, main_pipe): + self.main_pipe = main_pipe self.parameters = parameters self.view_parameters = view_parameters self.plot = plot_instance @@ -149,6 +141,7 @@ class chronoamp(Experiment): self.ylabel = "Current (A)" self.data = [[],[]] self.datalength = 2 + self.databytes = 8 self.xmin = 0 self.xmax = 0 @@ -168,30 +161,26 @@ class chronoamp(Experiment): self.commands[2] += " " def data_handler(self): #overrides inherited method to not convert x axis - while True: - for line in self.ser: - if line.startswith('B'): - inputdata = self.ser.read(size=8) #2*uint16 + int32 - seconds, milliseconds, current = struct.unpack('<HHl', inputdata) - - self.data[0].append(seconds+milliseconds/1000.) - self.data[1].append(current*(1.5/self.gain/8388607)) - - self.plot.updateline(self, 0) - - if self.update: - if self.updatecounter == self.updatelimit: - self.plot.redraw() - self.updatecounter = 0 - - else: - self.updatecounter +=1 + recv_p, send_p = mp.Pipe(duplex=False) + + capture_proc = dataCapture(self.ser, (recv_p, send_p), self.databytes) + capture_proc.start() + send_p.close() #pipe won't trip EOFError unless all connections are closed - elif line.lstrip().startswith("no"): - self.ser.flushInput() - break + while True: + try: + if self.main_pipe.poll(): + if self.main_pipe.recv() == 'a': + self.ser.write('a') + return + scan, data = recv_p.recv() + seconds, milliseconds, current = struct.unpack('<HHl', data) #2*uint16 + int32 + #(line, [data]) + self.main_pipe.send((0, [seconds+milliseconds/1000., current*(1.5/self.gain/8388607)])) - break + except EOFError: + print "empty" + break class lsv_exp(Experiment): def __init__(self, parameters, view_parameters, plot_instance, databuffer_instance, send_pipe): @@ -206,6 +195,7 @@ class lsv_exp(Experiment): self.ylabel = "Current (A)" self.data = [[],[]] self.datalength = 2 + self.databytes = 6 #uint16 + int32 self.xmin = self.parameters['start'] self.xmax = self.parameters['stop'] @@ -228,7 +218,8 @@ class lsv_exp(Experiment): self.commands[2] += " " class cv_exp(Experiment): - def __init__(self, parameters, view_parameters, plot_instance, databuffer_instance): + def __init__(self, parameters, view_parameters, plot_instance, databuffer_instance, main_pipe): + self.main_pipe = main_pipe self.parameters = parameters self.view_parameters = view_parameters self.plot = plot_instance @@ -239,6 +230,7 @@ class cv_exp(Experiment): self.ylabel = "Current (A)" self.data = [[],[]] #Will have to alter data_handler to add new lists as needed self.datalength = 2 * self.parameters['scans'] #x and y for each scan + self.databytes = 6 #uint16 + int32 self.xmin = self.parameters['v1'] self.xmax = self.parameters['v2'] @@ -265,48 +257,31 @@ class cv_exp(Experiment): self.commands[2] += " " def data_handler(self): - scan = 0 + recv_p, send_p = mp.Pipe(duplex=False) + + capture_proc = dataCapture(self.ser, (recv_p, send_p), self.databytes) + capture_proc.start() + send_p.close() #pipe won't trip EOFError unless all connections are closed while True: - for line in self.ser: - if line.startswith('B'): - inputdata = self.ser.read(size=6) #uint16 + int32 - voltage, current = struct.unpack('<Hl', inputdata) - - self.data[2*scan].append((voltage-32768)*3000./65536) - self.data[2*scan+1].append(current*(1.5/self.gain/8388607)) - - self.plot.updateline(self, scan) - - if self.update: - if self.updatecounter == self.updatelimit: - self.plot.redraw() - self.updatecounter = 0 - - else: - self.updatecounter +=1 - - elif line.lstrip().startswith("no"): - self.ser.flushInput() - break - - elif line.lstrip().startswith('S'): - self.plot.redraw() - self.plot.addline() - self.data.append([]) - self.data.append([]) - scan += 1 - - elif line.lstrip().startswith('D'): - self.data.pop() - self.data.pop() #instrument signals with S after each cycle, so last one will be blank, D singals end of experiment - self.plot.clearline(scan) - self.plot.redraw() - - break + try: + if self.main_pipe.poll(): + if self.main_pipe.recv() == 'a': + self.ser.write('a') + return + + scan, data = recv_p.recv() + voltage, current = struct.unpack('<Hl', data) #uint16 + int32 + #(line, [data]) + self.main_pipe.send((scan, [(voltage-32768)*3000./65536, current*(1.5/self.gain/8388607)])) + + except EOFError: + print "empty" + break class swv_exp(Experiment): - def __init__(self, parameters, view_parameters, plot_instance, databuffer_instance): + def __init__(self, parameters, view_parameters, plot_instance, databuffer_instance, main_pipe): + self.main_pipe = main_pipe self.parameters = parameters self.view_parameters = view_parameters self.plot = plot_instance @@ -317,6 +292,7 @@ class swv_exp(Experiment): self.ylabel = "Current (A)" self.data = [[],[]] #only difference stored here self.datalength = 2 * self.parameters['scans'] + self.databytes = 10 self.xmin = self.parameters['start'] self.xmax = self.parameters['stop'] @@ -347,49 +323,24 @@ class swv_exp(Experiment): self.commands[2] += " " def data_handler(self): - scan = 0 - - while True: - for line in self.ser: - if line.startswith('B'): - inputdata = self.ser.read(size=10) #uint16 + 2*int32 - voltage, forward, reverse = struct.unpack('<Hll', inputdata) - - self.data[2*scan].append((voltage-32768)*3000./65536) - self.data[2*scan+1].append((forward-reverse)*(1.5/self.gain/8388607)) - self.data_extra[2*scan].append(forward*(1.5/self.gain/8388607)) - self.data_extra[2*scan+1].append(reverse*(1.5/self.gain/8388607)) - - self.plot.updateline(self, scan) #displays only difference current, but forward and reverse stored - - if self.update: - if self.updatecounter == self.updatelimit: - self.plot.redraw() - self.updatecounter = 0 - - else: - self.updatecounter +=1 - - elif line.lstrip().startswith("no"): - self.ser.flushInput() - break + recv_p, send_p = mp.Pipe(duplex=False) - elif line.lstrip().startswith('S'): - self.plot.redraw() - self.plot.addline() - self.data.append([]) - self.data.append([]) - self.data_extra.append([]) - self.data_extra.append([]) - scan += 1 + capture_proc = dataCapture(self.ser, (recv_p, send_p), self.databytes) + capture_proc.start() + send_p.close() #pipe won't trip EOFError unless all connections are closed + + while True: + try: + if self.main_pipe.poll(): + if self.main_pipe.recv() == 'a': + self.ser.write('a') + return - elif line.lstrip().startswith('D'): - self.data.pop() - self.data.pop() #instrument signals with S after each cycle, so last one will be blank, D singals end of experiment - self.data_extra.pop() - self.data_extra.pop() - self.plot.clearline(scan) - self.plot.redraw() + scan, data = recv_p.recv() + voltage, forward, reverse = struct.unpack('<Hll', data) #uint16 + int32 + #(line, [data]) + self.main_pipe.send((scan, [(voltage-32768)*3000./65536, (forward-reverse)*(1.5/self.gain/8388607), forward*(1.5/self.gain/8388607), reverse*(1.5/self.gain/8388607)])) - break - + except EOFError: + print "empty" + break diff --git a/dstatInterface/interface_test.py b/dstatInterface/interface_test.py index 31926e10c63aa6d69b3d479fd19e5663b0e1d3e8..67945c4da9effb290495cc0f29aa6bdf5c44b88e 100644 --- a/dstatInterface/interface_test.py +++ b/dstatInterface/interface_test.py @@ -199,6 +199,10 @@ class main: view_parameters['update'] = self.plotint_checkbox.get_active() view_parameters['updatelimit'] = int(self.updatelimit_adj.get_value()) + self.line = 0 + self.lastline = 0 + self.lastdataline = 0 + self.spinner.start() self.statusbar.remove_all(self.error_context_id) @@ -210,8 +214,16 @@ class main: if not parameters['potential']: raise InputError(parameters['potential'],"Step table is empty") - self.current_exp = comm.chronoamp(parameters, view_parameters, self.plot, self.rawbuffer) - self.current_exp.run(self.serial_liststore.get_value(self.serial_combobox.get_active_iter(), 0)) + self.recv_p, self.send_p = multiprocessing.Pipe(duplex=True) + self.current_exp = comm.chronoamp(parameters, view_parameters, self.plot, self.rawbuffer, self.send_p) + + self.p = multiprocessing.Process(target=self.current_exp.run, args=(self.serial_liststore.get_value(self.serial_combobox.get_active_iter(), 0), )) + self.p.start() + + self.send_p.close() #need to close this copy of connection object for EOF signal to work + + self.plot_proc = gobject.timeout_add(200, self.experiment_running_plot) + gobject.idle_add(self.experiment_running) elif selection == 1: #LSV parameters['clean_mV'] = int(self.lsv.clean_mV.get_text()) @@ -239,12 +251,8 @@ class main: raise InputError(parameters['slope'],"Slope parameter exceeds hardware limits.") if parameters['start'] == parameters['stop']: raise InputError(parameters['start'],"Start cannot equal Stop.") - -# self.current_exp.run(self.serial_liststore.get_value(self.serial_combobox.get_active_iter(), 0)) - self.line = 0 self.recv_p, self.send_p = multiprocessing.Pipe(duplex=True) - self.current_exp = comm.lsv_exp(parameters, view_parameters, self.plot, self.rawbuffer, self.send_p) self.p = multiprocessing.Process(target=self.current_exp.run, args=(self.serial_liststore.get_value(self.serial_combobox.get_active_iter(), 0), )) @@ -288,9 +296,17 @@ class main: if parameters['v1'] == parameters['v2']: raise InputError(parameters['v1'],"Vertex 1 cannot equal Vertex 2.") - self.current_exp = comm.cv_exp(parameters, view_parameters, self.plot, self.rawbuffer) - self.current_exp.run(self.serial_liststore.get_value(self.serial_combobox.get_active_iter(), 0)) - + self.recv_p, self.send_p = multiprocessing.Pipe(duplex=True) + self.current_exp = comm.cv_exp(parameters, view_parameters, self.plot, self.rawbuffer, self.send_p) + + self.p = multiprocessing.Process(target=self.current_exp.run, args=(self.serial_liststore.get_value(self.serial_combobox.get_active_iter(), 0), )) + self.p.start() + + self.send_p.close() + + self.plot_proc = gobject.timeout_add(200, self.experiment_running_plot) + gobject.idle_add(self.experiment_running) + elif selection == 3: #SWV parameters['clean_mV'] = int(self.swv.clean_mV.get_text()) parameters['clean_s'] = int(self.swv.clean_s.get_text()) @@ -330,10 +346,18 @@ class main: raise InputError(parameters['freq'], "Frequency parameter outside limits.") if parameters['start'] == parameters['stop']: raise InputError(parameters['start'],"Start cannot equal Stop.") - - self.current_exp = comm.swv_exp(parameters, view_parameters, self.plot, self.rawbuffer) - self.current_exp.run(self.serial_liststore.get_value(self.serial_combobox.get_active_iter(), 0)) + self.recv_p, self.send_p = multiprocessing.Pipe(duplex=True) + self.current_exp = comm.swv_exp(parameters, view_parameters, self.plot, self.rawbuffer, self.send_p) + + self.p = multiprocessing.Process(target=self.current_exp.run, args=(self.serial_liststore.get_value(self.serial_combobox.get_active_iter(), 0), )) + self.p.start() + + self.send_p.close() + + self.plot_proc = gobject.timeout_add(200, self.experiment_running_plot) + gobject.idle_add(self.experiment_running) + else: self.statusbar.push(self.error_context_id, "Experiment not yet implemented.") @@ -358,14 +382,25 @@ class main: if self.recv_p.poll(): self.line, data = self.recv_p.recv() print self.line, data - for i in range(len(data)): - self.current_exp.data[self.line+i].append(data[i]) + if self.line > self.lastdataline: + self.current_exp.data += [[],[]] + if len(data) > 2: + self.current_exp.data_extra += [[],[]] + self.lastdataline = self.line + for i in range(2): + self.current_exp.data[2*self.line+i].append(data[i]) + if len(data) > 2: + self.current_exp.data_extra[2*self.line+i].append(data[i]) return True except EOFError: self.experiment_done() return False def experiment_running_plot(self): + if self.line > self.lastline: + self.plot.addline() + self.plot.updateline(self.current_exp, self.lastline) #make sure all of last line is added + self.lastline = self.line self.plot.updateline(self.current_exp, self.line) self.plot.redraw() return True