def __init__(self, title, procedure, analyse=(lambda x: x)): self.title = title self.procedure = procedure self.measlist = [] self.port = 5888 self.plots = [] self.figs = [] self._data = [] self.analyse = analyse self._data_timeout = 10 config = get_config() set_mpl_rcparams(config) if 'Logging' in config._sections.keys(): self.scribe = setup_logging(log, **config._sections['Logging']) else: self.scribe = console_log(log) self.scribe.start() self.filename = create_filename(self.title) log.info("Using data file: %s" % self.filename) self.results = Results(self.procedure, self.filename) log.info("Set up Results") self.worker = Worker(self.results, self.scribe.queue, logging.DEBUG) log.info("Create worker")
scribe = console_log(log, level=logging.DEBUG) scribe.start() filename = tempfile.mktemp() log.info("Using data file: %s" % filename) procedure = TestProcedure() procedure.iterations = 200 procedure.delay = 0.1 log.info("Set up TestProcedure with %d iterations" % procedure.iterations) results = Results(procedure, filename) log.info("Set up Results") plotter = Plotter(results) plotter.start() worker = Worker(results, scribe.queue, log_level=logging.DEBUG) log.info("Created worker for TestProcedure") log.info("Starting worker...") worker.start() log.info("Joining with the worker in at most 20 min") worker.join(60*20) log.info("Waiting for Plotter to close") plotter.wait_for_close() log.info("Plotter closed") log.info("Stopping the logging") scribe.stop()
scribe = console_log(log, level=logging.DEBUG) scribe.start() filename = tempfile.mktemp() log.info("Using data file: %s" % filename) procedure = TestProcedure() procedure.iterations = 200 procedure.delay = 0.1 log.info("Set up TestProcedure with %d iterations" % procedure.iterations) results = Results(procedure, filename) log.info("Set up Results") plotter = Plotter(results) plotter.start() worker = Worker(results, scribe.queue, log_level=logging.DEBUG) log.info("Created worker for TestProcedure") log.info("Starting worker...") worker.start() log.info("Joining with the worker in at most 20 min") worker.join(60 * 20) log.info("Waiting for Plotter to close") plotter.wait_for_close() log.info("Plotter closed") log.info("Stopping the logging") scribe.stop()
class Experiment(object): """ Class which starts logging and creates/runs the results and worker processes. .. code-block:: python procedure = Procedure() experiment = Experiment(title, procedure) experiment.start() experiment.plot_live('x', 'y', style='.-') for a multi-subplot graph: import pylab as pl ax1 = pl.subplot(121) experiment.plot('x','y',ax=ax1) ax2 = pl.subplot(122) experiment.plot('x','z',ax=ax2) experiment.plot_live() :var value: The value of the parameter :param title: The experiment title :param procedure: The procedure object :param analyse: Post-analysis function, which takes a pandas dataframe as input and returns it with added (analysed) columns. The analysed results are accessible via experiment.data, as opposed to experiment.results.data for the 'raw' data. :param _data_timeout: Time limit for how long live plotting should wait for datapoints. """ def __init__(self, title, procedure, analyse=(lambda x: x)): self.title = title self.procedure = procedure self.measlist = [] self.port = 5888 self.plots = [] self.figs = [] self._data = [] self.analyse = analyse self._data_timeout = 10 config = get_config() set_mpl_rcparams(config) if 'Logging' in config._sections.keys(): self.scribe = setup_logging(log, **config._sections['Logging']) else: self.scribe = console_log(log) self.scribe.start() self.filename = create_filename(self.title) log.info("Using data file: %s" % self.filename) self.results = Results(self.procedure, self.filename) log.info("Set up Results") self.worker = Worker(self.results, self.scribe.queue, logging.DEBUG) log.info("Create worker") def start(self): """Start the worker""" log.info("Starting worker...") self.worker.start() @property def data(self): """Data property which returns analysed data, if an analyse function is defined, otherwise returns the raw data.""" self._data = self.analyse(self.results.data.copy()) return self._data def wait_for_data(self): """Wait for the data attribute to fill with datapoints.""" t = time.time() while self.data.empty: time.sleep(.1) if (time.time() - t) > self._data_timeout: log.warning('Timeout, no data received for liveplot') return False return True def plot_live(self, *args, **kwargs): """Live plotting loop for jupyter notebook, which automatically updates (an) in-line matplotlib graph(s). Will create a new plot as specified by input arguments, or will update (an) existing plot(s).""" if self.wait_for_data(): if not (self.plots): self.plot(*args, **kwargs) while not self.worker.should_stop(): self.update_plot() display.clear_output(wait=True) if self.worker.is_alive(): self.worker.terminate() self.scribe.stop() def plot(self, *args, **kwargs): """Plot the results from the experiment.data pandas dataframe. Store the plots in a plots list attribute.""" if self.wait_for_data(): kwargs['title'] = self.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): """Clear the figures and plot lists.""" for fig in self.figs: fig.clf() pl.close() self.figs = [] self.plots = [] gc.collect() def update_plot(self): """Update the plots in the plots list with new data from the experiment.data pandas dataframe.""" try: 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): self.update_line(ax, line, x, yname) if plot['type'] == 'pcolor': x, y, z = plot['x'], plot['y'], plot['z'] update_pcolor(ax, x, y, z) display.clear_output(wait=True) display.display(*self.figs) time.sleep(0.1) except KeyboardInterrupt: display.clear_output(wait=True) display.display(*self.figs) self._user_interrupt = True def pcolor(self, xname, yname, zname, *args, **kwargs): """Plot the results from the experiment.data pandas dataframe in a pcolor graph. Store the plots in a plots list attribute.""" title = self.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()) def update_pcolor(self, ax, xname, yname, zname): """Update a pcolor graph with new data.""" 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() def update_line(self, ax, hl, xname, yname): """Update a line in a matplotlib graph with new data.""" del hl._xorig, hl._yorig hl.set_xdata(self._data[xname]) hl.set_ydata(self._data[yname]) ax.relim() ax.autoscale() gc.collect() def __del__(self): self.scribe.stop() if self.worker.is_alive(): self.worker.recorder_queue.put(None) self.worker.monitor_queue.put(None) self.worker.stop()
'Reverse Current Dark': abs(trace_data_dark[i, 0]), 'Timestamp Dark': trace_data_dark[i, 1], 'Status Dark': trace_data_dark[i, 2], 'Reverse Voltage Light': abs(trace_data_light[i, 3]), 'Reverse Current Light': abs(trace_data_light[i, 0]), 'Timestamp Light': trace_data_light[i, 1], 'Status Light': trace_data_light[i, 2] }) for i in range(n_samples) ] log.info("Current data emitted") log.info("Turning off light source") self.power_supply.enabled = "OFF" log.info("Waiting for 30sec in between test.") sleep(30) if __name__ == "__main__": console_log(log, level=logging.DEBUG) procedure = IVSweepProcedure() procedure.polarity = "Anode" # procedure.step = 1 data_filename = 'example.csv' results = Results(procedure, data_filename) worker = Worker(results) worker.start() worker.join(timeout=3600) # wait at most 1 hr (3600 sec)
class Experiment(): """ Class which starts logging and creates/runs the results and worker processes. .. code-block:: python procedure = Procedure() experiment = Experiment(title, procedure) experiment.start() experiment.plot_live('x', 'y', style='.-') for a multi-subplot graph: import pylab as pl ax1 = pl.subplot(121) experiment.plot('x','y',ax=ax1) ax2 = pl.subplot(122) experiment.plot('x','z',ax=ax2) experiment.plot_live() :var value: The value of the parameter :param title: The experiment title :param procedure: The procedure object :param analyse: Post-analysis function, which takes a pandas dataframe as input and returns it with added (analysed) columns. The analysed results are accessible via experiment.data, as opposed to experiment.results.data for the 'raw' data. :param _data_timeout: Time limit for how long live plotting should wait for datapoints. """ def __init__(self, title, procedure, analyse=(lambda x: x)): self.title = title self.procedure = procedure self.measlist = [] self.port = 5888 self.plots = [] self.figs = [] self._data = [] self.analyse = analyse self._data_timeout = 10 config = get_config() set_mpl_rcparams(config) if 'Logging' in config._sections.keys(): self.scribe = setup_logging(log, **config._sections['Logging']) else: self.scribe = console_log(log) self.scribe.start() self.filename = create_filename(self.title) log.info("Using data file: %s" % self.filename) self.results = Results(self.procedure, self.filename) log.info("Set up Results") self.worker = Worker(self.results, self.scribe.queue, logging.DEBUG) log.info("Create worker") def start(self): """Start the worker""" log.info("Starting worker...") self.worker.start() @property def data(self): """Data property which returns analysed data, if an analyse function is defined, otherwise returns the raw data.""" self._data = self.analyse(self.results.data.copy()) return self._data def wait_for_data(self): """Wait for the data attribute to fill with datapoints.""" t=time.time() while self.data.empty: time.sleep(.1) if (time.time()-t)>self._data_timeout: log.warning('Timeout, no data received for liveplot') return False return True def plot_live(self, *args, **kwargs): """Live plotting loop for jupyter notebook, which automatically updates (an) in-line matplotlib graph(s). Will create a new plot as specified by input arguments, or will update (an) existing plot(s).""" if self.wait_for_data(): if not(self.plots): self.plot(*args, **kwargs) while not self.worker.should_stop(): self.update_plot() display.clear_output(wait=True) if self.worker.is_alive(): self.worker.terminate() self.scribe.stop() def plot(self, *args, **kwargs): """Plot the results from the experiment.data pandas dataframe. Store the plots in a plots list attribute.""" if self.wait_for_data(): kwargs['title'] = self.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): """Clear the figures and plot lists.""" for fig in self.figs: fig.clf() pl.close() self.figs = [] self.plots = [] gc.collect() def update_plot(self): """Update the plots in the plots list with new data from the experiment.data pandas dataframe.""" try: 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): self.update_line(ax, line, x, yname) if plot['type']=='pcolor': x,y,z = plot['x'], plot['y'], plot['z'] update_pcolor(ax, x, y, z) display.clear_output(wait=True) display.display(*self.figs) time.sleep(0.1) except KeyboardInterrupt: display.clear_output(wait=True) display.display(*self.figs) self._user_interrupt = True def pcolor(self, xname, yname, zname, *args, **kwargs): """Plot the results from the experiment.data pandas dataframe in a pcolor graph. Store the plots in a plots list attribute.""" title = self.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()) def update_pcolor(self, ax, xname, yname, zname): """Update a pcolor graph with new data.""" 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() def update_line(self, ax, hl, xname, yname): """Update a line in a matplotlib graph with new data.""" del hl._xorig, hl._yorig hl.set_xdata(self._data[xname]) hl.set_ydata(self._data[yname]) ax.relim() ax.autoscale() gc.collect() def __del__(self): self.scribe.stop() if self.worker.is_alive(): self.worker.recorder_queue.put(None) self.worker.monitor_queue.put(None) self.worker.stop()
sleep(self.delay) if self.should_stop(): log.warning("Caught the stop flag in the procedure") break if __name__ == "__main__": console_log(log) log.info("Constructing a RandomProcedure") procedure = Measuringproc() procedure.iterations = 10000 data_filename = 'measured.csv' log.info("Constructing the Results with a data file: %s" % data_filename) results = Results(procedure, data_filename) log.info("Constructing the Plotter") plotter = Plotter(results) plotter.start() log.info("Started the Plotter") log.info("Constructing the Worker") worker = Worker(results) worker.start() log.info("Started the Worker") log.info("Joining with the worker in at most 1 hr") # worker.join(timeout=3600) # wait at most 1 hr (3600 sec) log.info("Finished the measurement")