示例#1
0
 def __init__(self, title, measlist=[]):
     self.title = title
     self.instruments = InstrumentList(*RemoteInstrument.instances)
     self.manager = Manager()
     self.output = self.manager.dict()
     self.plots = []
     self.figs = []
     self._data = pd.DataFrame()
     self.measurement = Measurement(self.instruments, measlist)
     self.datacollector = DataCollector(self.measurement.pipe[1], self.output, self.title)
     self._user_interrupt = False
示例#2
0
 def run(self):
     if self.measurement.measlist is []:
         raise NameError('Measurement is not defined.')
     if 'measure' not in [meas['type'] for meas in self.measurement.measlist]:
         print('Warning: No \'measure\' command found.')
     if self.measurement.pid is not None:
         measlist = self.measurement.measlist
         self.measurement = Measurement(self.instruments,
                                         measlist)
         if self.datacollector.is_alive():
             self.datacollector.terminate()
         self.datacollector = DataCollector(self.measurement.pipe[1],
                                             self.output,
                                             self.title)
     if not self.datacollector.is_alive():
         self.datacollector.start()
     if not self.measurement.is_alive():
         self.measurement.start()
示例#3
0
class Experiment():
    '''
    Basic experiment class. This class creates the measurement, plot and data collector. It runs the measurement in a separate process, which drops datapoints in a queue.
    The datacollector, also in a separate process, is a daemon that collects all these datapoints in a Data (pd.Dataframe-like) object and saves the data periodically on-disk.
    It also drops the latest Data instance in a pipe for live plotting in the main thread.
    '''
    def __init__(self, title, measlist=[]):
        self.title = title
        self.instruments = InstrumentList(*RemoteInstrument.instances)
        self.manager = Manager()
        self.output = self.manager.dict()
        self.plots = []
        self.figs = []
        self._data = pd.DataFrame()
        self.measurement = Measurement(self.instruments, measlist)
        self.datacollector = DataCollector(self.measurement.pipe[1], self.output, self.title)
        self._user_interrupt = False
    
    @property
    def data(self):
        if 'data' in self.output.keys():
            if hasattr(self, '_data'):
                del self._data
            gc.collect()
            self._data = Data(**self.output)
        return self._data

    def new_file(self):
        '''Create new data file'''
        self.output.clear()
    
    @property
    def running(self):
        try:
            running = self.measurement.is_alive() and (not self._user_interrupt)
            if not running:
                if len(self.plots)>0:
                    if self.plots[0]['type'] is not 'pcolor':
                        display.clear_output(wait=True)
            return running
        except KeyboardInterrupt:
            return False

    @running.setter
    def running(self, value):
        if value is False:
            self.measurement.terminate()
            self.measurement.end_measurement()
    
    def wait_and_get_title(self, timeout=10, tsleep=0):
        '''Wait for data file to fill and return title.'''
        while self.data.empty:
            time.sleep(0.01)
            tsleep+=.01
            if tsleep>timeout:
                raise Exception('Timeout for graph: no data received.')
        title = '%s_%s' %(self._data.stamp, self._data.title)
        return title

    def plot_live(self, *args, **kwargs):
        self.clear_plot()
        self.plot(*args, **kwargs)
        try:
            while self.running:
                self.update_plot()
        except KeyboardInterrupt:
            pass
    
    def plot(self, *args, **kwargs):
        kwargs['title'] = self.wait_and_get_title()
        ax = self.data.plot(*args, **kwargs)
        self.plots.append({'type': 'plot', 'args': args, 'kwargs': kwargs, 'ax': ax})
        if ax.get_figure() not in self.figs:
            self.figs.append(ax.get_figure())
        self._user_interrupt = False

    def clear_plot(self):
        for fig in self.figs:
            fig.clf()
            pl.close()
        self.figs = []
        self.plots = []
        gc.collect()

    def update_plot(self):
        try:
            loop = asyncio.get_event_loop()
            tasks = []
            self.data
            for plot in self.plots:
                ax = plot['ax']
                if plot['type']=='plot':
                    x,y = plot['args'][0], plot['args'][1]
                    if type(y) == str:
                        y = [y]
                    for yname,line in zip(y,ax.lines):
                        tasks.append(asyncio.ensure_future(self.update_line(ax, line, x, yname)))
                if plot['type']=='pcolor':
                    x,y,z = plot['x'], plot['y'], plot['z']
                    tasks.append(asyncio.ensure_future(self.update_pcolor(ax, x, y, z)))
            loop.run_until_complete(asyncio.wait(tasks))
            
            display.clear_output(wait=True)
            display.display(*self.figs)
            time.sleep(0.1)
        except KeyboardInterrupt:
            loop.run_until_complete(asyncio.wait(tasks))
            display.clear_output(wait=True)
            display.display(*self.figs)
            self._user_interrupt = True
    
    def pcolor(self, xname, yname, zname, *args, **kwargs):
        title = self.wait_and_get_title()
        x,y,z = self._data[xname], self._data[yname], self._data[zname]
        shape = (len(y.unique()), len(x.unique()))
        diff = shape[0]*shape[1] - len(z)
        Z = np.concatenate((z.values, np.zeros(diff))).reshape(shape)
        df = pd.DataFrame(Z, index=y.unique(), columns=x.unique())
        ax = sns.heatmap(df)
        pl.title(title)
        pl.xlabel(xname)
        pl.ylabel(yname)
        ax.invert_yaxis()
        pl.plt.show()
        self.plots.append({'type': 'pcolor', 'x':xname, 'y':yname, 'z':zname, 'args':args, 'kwargs':kwargs, 'ax':ax})
        if ax.get_figure() not in self.figs:
            self.figs.append(ax.get_figure())
    
    @asyncio.coroutine
    def update_pcolor(self, ax, xname, yname, zname):
        x,y,z = self._data[xname], self._data[yname], self._data[zname]
        shape = (len(y.unique()), len(x.unique()))
        diff = shape[0]*shape[1] - len(z)
        Z = np.concatenate((z.values, np.zeros(diff))).reshape(shape)
        df = pd.DataFrame(Z, index=y.unique(), columns=x.unique())
        cbar_ax = ax.get_figure().axes[1]
        sns.heatmap(df, ax=ax, cbar_ax=cbar_ax)
        ax.set_xlabel(xname)
        ax.set_ylabel(yname)
        ax.invert_yaxis()
    
    @asyncio.coroutine
    def update_line(self, ax, hl, xname, yname):
        del hl._xorig, hl._yorig
        hl.set_xdata(self._data[xname])
        hl.set_ydata(self._data[yname])
        ax.relim()
        ax.autoscale()
        gc.collect()
    
    def set(self, **kwargs):
        self.measurement.set(**kwargs)

    def sweep(self, sweep_param, arr=[]):
        ins, param = re.split('\.', sweep_param)
        return Sweep(self, ins, param, arr)

    def do_while(self, clause):
        self.set(do_while = clause)
    
    def do(self, func, *args):
        self.set(do = (func, args))
    
    def measure(self, params=None):
        self.set(measure = params)
    
    def run(self):
        if self.measurement.measlist is []:
            raise NameError('Measurement is not defined.')
        if 'measure' not in [meas['type'] for meas in self.measurement.measlist]:
            print('Warning: No \'measure\' command found.')
        if self.measurement.pid is not None:
            measlist = self.measurement.measlist
            self.measurement = Measurement(self.instruments,
                                            measlist)
            if self.datacollector.is_alive():
                self.datacollector.terminate()
            self.datacollector = DataCollector(self.measurement.pipe[1],
                                                self.output,
                                                self.title)
        if not self.datacollector.is_alive():
            self.datacollector.start()
        if not self.measurement.is_alive():
            self.measurement.start()
    
    def __del__(self):
        self.manager.shutdown()
        if self.datacollector.is_alive():
            self.datacollector.terminate()
        self.datacollector.exitcode
        self.measurement.exitcode