def __init__( self, master=None, title=None, ): super(NetworkPlotTk, self).__init__(matplotlib_figure=matplotlib.figure.Figure(), ) if master is None: master = tk.Tk() master.withdraw() self.master = master #self.master.protocol("WM_DELETE_WINDOW", self.on_closing) # Create a Toplevel widget, which is a child of GUILoom # and contains plots, self.toplevel = tk.Toplevel(master) self.toplevel.wm_title(title) self.toplevel.protocol("WM_DELETE_WINDOW", self.on_closing) self.plot_idx_scale = None self.plot_idx_entry = None self.plot_idx_entry_var = tk.StringVar() self.plot_idx_entry_var.trace('w', self.plot_idx_entry_change) self.canvas = FigureCanvas(self.figure, master=self.toplevel, resize_callback=self.canvas_resize_callback) self.canvas.show() self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1) toolbar = NavigationToolbar(self.canvas, self.toplevel) toolbar.update() self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
class FFT_ROOT_WINDOW(Tk.Frame): """ This window displays the FFT of given data """ def __init__(self, waveforms, metadata, master=None): Tk.Frame.__init__(self, master) # hack to make work in python2 self.pack() self.figure = Figure(figsize=(8, 8), dpi=100) self.axs = [] for iPlot in range(16): self.axs.append(self.figure.add_subplot(4, 4, iPlot + 1)) self.canvas = FigureCanvas(self.figure, master=self) self.canvas.show() self.canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) self.toolbar = NaviationToolbar(self.canvas, self) self.toolbar.update() self.canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) self.draw_fft(waveforms, metadata) def draw_fft(self, waveforms, metadata): self.figure.suptitle("FFT for socket: {}, FE: {} ADC: {}".format( metadata['iChip'], metadata['feSerial'], metadata['adcSerial']), fontsize="large") for iChan in waveforms: ax = self.axs[iChan] waveform = waveforms[iChan] N = len(waveform) freqs = numpy.arange(N) / (N / 2.0) fft = numpy.fft.fft(waveform) freqs = freqs[1:N // 2] fft = fft[1:N // 2] fft = abs(fft * fft.conj()) ax.plot(freqs, fft) ax.set_title("Channel: {}".format(iChan)) if (fft > 0.).all(): ax.set_yscale('log') if iChan // 4 == 3: ax.set_xlabel("Frequency") if iChan % 4 == 0: ax.set_ylabel("Power")
class MainWindow: def __init__(self, master=None): self.frame = tkinter.Frame(master) self.frame.pack(padx=15,pady=15) self.fig = matplotlib.figure.Figure(figsize=(6, 4), dpi=100) self.ax = self.fig.add_subplot(111) self.ax.plot(np.linspace(0, 4), np.sin(np.linspace(0, 4))) self.canvas = FigureCanvas(self.fig, master=self.frame) self.canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1) self.mpl_toolbar = NavigationToolbar(self.canvas, master) self.mpl_toolbar.update() self.canvas._tkcanvas.pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)
class MainWindow: def __init__(self, master=None): self.frame = tkinter.Frame(master) self.frame.pack(padx=15, pady=15) self.fig = matplotlib.figure.Figure(figsize=(6, 4), dpi=100) self.ax = self.fig.add_subplot(111) self.ax.plot(np.linspace(0, 4), np.sin(np.linspace(0, 4))) self.canvas = FigureCanvas(self.fig, master=self.frame) self.canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1) self.mpl_toolbar = NavigationToolbar(self.canvas, master) self.mpl_toolbar.update() self.canvas._tkcanvas.pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)
def __init__(self, master=None, title=None, ): super(NetworkPlotTk, self).__init__( matplotlib_figure=matplotlib.figure.Figure(), ) if master is None: master = tk.Tk() master.withdraw() self.master = master #self.master.protocol("WM_DELETE_WINDOW", self.on_closing) # Create a Toplevel widget, which is a child of GUILoom # and contains plots, self.toplevel = tk.Toplevel(master) self.toplevel.wm_title(title) self.toplevel.protocol("WM_DELETE_WINDOW", self.on_closing) self.plot_idx_scale = None self.plot_idx_entry = None self.plot_idx_entry_var = tk.StringVar() self.plot_idx_entry_var.trace('w', self.plot_idx_entry_change) self.canvas = FigureCanvas( self.figure, master=self.toplevel, resize_callback=self.canvas_resize_callback ) self.canvas.show() self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1) toolbar = NavigationToolbar(self.canvas, self.toplevel) toolbar.update() self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
class TRACE_ALLCHAN_WINDOW(Tk.Frame): """ This window displays a live ADC redout """ def __init__(self, master=None, packedHighSpeed=False): self.maxtraces = 5 self.selChan = 0 Tk.Frame.__init__(self, master) # hack to make work in python2 self.pack() self.figure = Figure(figsize=(15, 7), dpi=100, facecolor='white') self.canvas = FigureCanvas(self.figure, master=self) self.canvas.show() self.canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) self.toolbar = NaviationToolbar(self.canvas, self) self.toolbar.update() self.canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) self.pauseButton = Tk.Button(self, text="Pause", command=self.pause) self.pauseButton.pack(side=Tk.LEFT) self.playButton = Tk.Button(self, text="Play", command=self.play, state=Tk.DISABLED) self.playButton.pack(side=Tk.LEFT) self.prevButton = Tk.Button(self, text="Previous Trace", command=self.prevTrace, state=Tk.DISABLED) self.prevButton.pack(side=Tk.LEFT) self.nextButton = Tk.Button(self, text="Next Trace", command=self.nextTrace, state=Tk.DISABLED) self.nextButton.pack(side=Tk.LEFT) self.packedHighSpeed = packedHighSpeed self.femb = None self.iTrace = -1 self.traces = [] self.timestamps = [] self.reset() def reset(self, iTrace=None): self.femb = FEMB_UDP() self.figure.clf() self.subgs = [None] * 16 self.ax = [None] * 16 self.plot = [None] * 16 # 4x4 grid, one cell per channel self.gs = gridspec.GridSpec(4, 4) self.gs.update(wspace=0.2, hspace=0.2) # 1 plots per channel for row in range(4): for col in range(4): self.subgs[col + 4 * row] = gridspec.GridSpecFromSubplotSpec( 1, 1, subplot_spec=self.gs[col + 4 * row], hspace=0.0) self.ax[col + 4 * row] = self.figure.add_subplot( self.subgs[col + 4 * row][0]) self.ax[col + 4 * row].tick_params(axis='x', colors='black', labelsize='medium') self.ax[col + 4 * row].tick_params(axis='y', colors='black', labelsize='smaller') if iTrace is None: self.ani = animation.FuncAnimation(self.figure, self.plotData, interval=1000, blit=True) else: self.plotData(0, iTrace) self.canvas.draw() def pause(self): self.ani.event_source.stop() self.reset(self.iTrace) self.pauseButton['state'] = Tk.DISABLED self.playButton['state'] = Tk.NORMAL self.prevButton['state'] = Tk.NORMAL self.nextButton['state'] = Tk.DISABLED def play(self): self.ani.event_source.start() self.pauseButton['state'] = Tk.NORMAL self.playButton['state'] = Tk.DISABLED self.prevButton['state'] = Tk.DISABLED self.nextButton['state'] = Tk.DISABLED def prevTrace(self): self.iTrace -= 1 self.reset(self.iTrace) if self.iTrace < 1: self.prevButton['state'] = Tk.DISABLED else: self.prevButton['state'] = Tk.NORMAL if self.iTrace >= len(self.traces) - 1: self.nextButton['state'] = Tk.DISABLED else: self.nextButton['state'] = Tk.NORMAL def nextTrace(self): self.iTrace += 1 self.reset(self.iTrace) if self.iTrace < 1: self.prevButton['state'] = Tk.DISABLED else: self.prevButton['state'] = Tk.NORMAL if self.iTrace >= len(self.traces) - 1: self.nextButton['state'] = Tk.DISABLED else: self.nextButton['state'] = Tk.NORMAL def plotData(self, iFrame, iTrace=None): for a in self.ax: a.cla() a.locator_params(tight=True, nbins=3) # In case no data, return an empty plot self.plot[0] = self.ax[0].plot() for r in range(4): for c in range(4): t, adc, thistimestamp = self.getTraceAndFFT(iTrace=iTrace, chan=c + 4 * r) if not (t is None) and not (adc is None): self.plot[c + 4 * r] = self.ax[c + 4 * r].plot(t, adc) if c + 4 * r < 12: self.ax[c + 4 * r].set_xticklabels([]) self.figure.text(0.5, 0.02, 'Time [us]', ha='center', color='black', fontsize='25.0', weight='bold') self.figure.text(0.08, 0.5, 'ADC', ha='center', rotation=90, color='black', fontsize='25.0', weight='bold') if not (thistimestamp is None): self.figure.suptitle( thistimestamp.replace(microsecond=0).isoformat(" ")) self.canvas.draw() return self.plot[0] def getTraceAndFFT(self, iTrace=None, chan=0): """ Gets trace from FEMB and returns 4 1D arrays: times, ADC counts """ data = None timestamp = None if iTrace is None: data = self.femb.get_data(100) timestamp = datetime.datetime.now() self.traces.append(data) self.timestamps.append(timestamp) if len(self.traces) > self.maxtraces: self.traces.pop(0) self.timestamps.pop(0) self.iTrace = len(self.traces) - 1 else: data = self.traces[iTrace] timestamp = self.timestamps[iTrace] if data == None: return None, None, None, None, None if len(data) == 0: return None, None, None, None, None chSamples = None if self.packedHighSpeed: chSamples = WRITE_ROOT_TREE.convertHighSpeedPacked(None, data) else: chSamples = WRITE_ROOT_TREE.convertHighSpeedSimple(None, data) xpoint = [] ypoint = [] num = 0 for samp in chSamples[chan]: xpoint.append(num * 0.5) ypoint.append(samp) num = num + 1 xarr = np.array(xpoint) yarr = np.array(ypoint) return xarr, yarr, timestamp
def show_histograms(self, H_hist, N_hist, C_hist, H_bin, N_bin, C_bin): print('\nH:') print(H_hist) print('\nN:') print(N_hist) print('\nC:') print(C_hist) self.H_hist, self.N_hist, self.C_hist = H_hist, N_hist, C_hist self.fig, self.axes = subplots(figsize=(20, 5), nrows=1, ncols=3) self.fig.set_facecolor("white") subplots_adjust(left=0.04, bottom=0.1, right=0.98, top=0.90, wspace=0.14) self.axes[0].bar(list(H_hist.keys()), H_hist.values(), color='#3dff3d', width=H_bin, edgecolor='#32D032') self.axes[0].set_title("H", fontsize=16) self.axes[0].set_ylabel("Number of occurrences", fontsize=12) self.axes[0].set_xlabel("Chemical shift (ppm)", fontsize=12) draw() self.axes[1].bar(list(N_hist.keys()), N_hist.values(), color='#00ffff', width=N_bin, edgecolor='#00E3E3') self.axes[1].set_title("N", fontsize=16) self.axes[1].set_ylabel("Number of occurrences", fontsize=12) self.axes[1].set_xlabel("Chemical shift (ppm)", fontsize=12) draw() self.axes[2].bar(list(C_hist.keys()), C_hist.values(), color='#ffe23d', width=C_bin, edgecolor='#E0C837') self.axes[2].set_title("C", fontsize=16) self.axes[2].set_ylabel("Number of occurrences", fontsize=12) self.axes[2].set_xlabel("Chemical shift (ppm)", fontsize=12) draw() self.canvas = FigureCanvasTkAgg(self.fig, master=self.plot_frame) self.canvas.get_tk_widget().pack() self.canvas.draw() toolbar = NavTB(self.canvas, self.plot_frame) toolbar.update() self.ax0_xlim = self.axes[0].get_xlim() self.ax0_ylim = self.axes[0].get_ylim() self.ax1_xlim = self.axes[1].get_xlim() self.ax1_ylim = self.axes[1].get_ylim() self.ax2_xlim = self.axes[2].get_xlim() self.ax2_ylim = self.axes[2].get_ylim()
class TRACE_VIEWER(Tk.Frame): """ This window displays a live ADC readout """ def __init__(self, master=None): self.config = CONFIG self.functions = FEMB_CONFIG_BASE(self.config) #Gets the low level module to do UDP packets self.femb = self.functions.lower_functions self.master = master self.functions.configFeAsic( test_cap="on", base=self.config["SYNC_SETTINGS"]["SYNC_BASELINE"], gain=self.config["SYNC_SETTINGS"]["SYNC_GAIN"], shape=self.config["SYNC_SETTINGS"]["SYNC_PEAK"], monitor_ch=None, buffer=self.config["SYNC_SETTINGS"]["SYNC_BUFFER"], leak=self.config["SYNC_SETTINGS"]["SYNC_LEAK"], monitor_param=None, s16=None, acdc=self.config["SYNC_SETTINGS"]["SYNC_ACDC"], test_dac="test_int", dac_value=int( self.config["SYNC_SETTINGS"]["SYNC_DAC_PEAK_HEIGHT"])) self.functions.writeFE() #Creates Tkinter object Tk.Frame.__init__(self, master) # hack to make work in python2 self.pack() #Creates Matplotlib object self.figure = Figure(figsize=(20, 7), dpi=100, facecolor='white') self.canvas = FigureCanvas(self.figure, master=self) self.canvas.show() self.canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) #Create toolbar for bottom self.toolbar = NavigationToolbar(self.canvas, self) self.toolbar.update() self.pauseButton = Tk.Button(self, text="Pause", command=self.pause) self.pauseButton.pack(side=Tk.LEFT) self.playButton = Tk.Button(self, text="Play", command=self.play, state=Tk.DISABLED) self.playButton.pack(side=Tk.LEFT) pulse_options = ["None", "Internal Pulse", "External Pulse"] self.pulse_entry_choices = Tk.StringVar(self.master, name="pulse_entry") self.pulse_entry_choices.set(pulse_options[0]) # initial value self.pulse_entry_choices.trace("w", self.gui_callback) self.pulse_entry = Tk.OptionMenu(self, self.pulse_entry_choices, *pulse_options) self.pulse_entry.pack(side=Tk.LEFT) self.chip = 0 chip_options = [] for i in range(int(self.config["DEFAULT"]["NASICS"])): chip_options.append("Chip {}".format(i)) self.chip_entry_choices = Tk.StringVar(self.master, name="chip_entry") self.chip_entry_choices.set(chip_options[0]) # initial value self.chip_entry_choices.trace("w", self.gui_callback) self.chip_entry = Tk.OptionMenu(self, self.chip_entry_choices, *chip_options) self.chip_entry.pack(side=Tk.LEFT) self.packets = 2 self.packet_label = Tk.Label(self, text="Packet Length:", width=11) self.packet_label.pack(side=Tk.LEFT) self.packet_entry = Tk.Spinbox(self, width=5, from_=1, to=100, name="patcket_entry", command=self.packet_change) self.packet_entry.delete(0, "end") self.packet_entry.insert(0, self.packets) self.packet_entry.pack(side=Tk.LEFT) self.manualSyncButton = Tk.Button(self, text="Manual Sync", command=self.manualSync) self.manualSyncButton.pack(side=Tk.LEFT) self.reset() def reset(self): self.figure.clf() self.subgs = [None] * 16 self.ax = [None] * 16 self.plot = [None] * 16 self.figure.text(0.5, 0.02, 'Time [us]', ha='center', color='black', fontsize='25.0', weight='bold') self.figure.text(0.08, 0.625, 'ADC counts', ha='center', rotation=90, color='black', fontsize='25.0', weight='bold') # 4x4 grid, one cell per channel self.gs = gridspec.GridSpec(4, 4) self.gs.update(wspace=0.2, hspace=0.2) # 1 plots per channel, create axes objects for row in range(4): for col in range(4): ch = col + 4 * row self.subgs[ch] = gridspec.GridSpecFromSubplotSpec( 1, 1, subplot_spec=self.gs[ch], hspace=0.0) self.ax[ch] = self.figure.add_subplot(self.subgs[ch][0]) self.ax[ch].tick_params(axis='x', colors='black', labelsize='medium') self.ax[ch].tick_params(axis='y', colors='black', labelsize='smaller') #Continually updates by calling self.plotData self.ani = animation.FuncAnimation(self.figure, self.plotData, interval=1000, blit=True) self.canvas.draw() def packet_change(self): self.packets = int(self.packet_entry.get()) def gui_callback(self, *args, **kwargs): if (args[0] == "pulse_entry"): if (self.pulse_entry_choices.get() == "None"): self.femb.femb_udp.write_reg( int(self.config["REGISTERS"]["REG_MUX_MODE"]), int(self.config["DEFINITIONS"]["MUX_GND_GND"])) elif (self.pulse_entry_choices.get() == "Internal Pulse"): self.femb.femb_udp.write_reg( int(self.config["REGISTERS"]["REG_MUX_MODE"]), int(self.config["DEFINITIONS"]["MUX_GND_GND_INTPULSE"])) elif (self.pulse_entry_choices.get() == "External Pulse"): self.femb.femb_udp.write_reg( int(self.config["REGISTERS"]["REG_MUX_MODE"]), int(self.config["DEFINITIONS"]["MUX_GND_DACPULSE"])) elif (args[0] == "chip_entry"): self.chip = int( re.findall(r'\d+', self.chip_entry_choices.get())[0]) def pause(self): self.ani.event_source.stop() self.pauseButton['state'] = Tk.DISABLED self.playButton['state'] = Tk.NORMAL def play(self): self.ani.event_source.start() self.pauseButton['state'] = Tk.NORMAL self.playButton['state'] = Tk.DISABLED def plotData(self, iFrame): for a in self.ax: #Clears all previous traces a.cla() #Limits the number of traces on each subplot a.locator_params(tight=True, nbins=3) #In case no data, return an empty plot # self.plot[0] = self.ax[0].plot() t, adc, thistimestamp = self.getData() for r in range(4): for c in range(4): ch = c + 4 * r if not (t is None) and not (adc is None): self.plot[ch] = self.ax[ch].plot(t, adc[ch]) if ch < 12: self.ax[ch].set_xticklabels([]) self.ax[ch].title.set_text("Channel {}".format(ch)) if not (thistimestamp is None): self.figure.suptitle( thistimestamp.replace(microsecond=0).isoformat(" ")) self.canvas.draw() return self.plot[0] def closeSync(self): self.syncWindow.destroy() self.syncWindow.quit() self.syncWindow = None def manualSync(self): self.syncWindow = Tk.Toplevel(self.master) self.app = manSync(self.syncWindow, config=self.config, femb=self.femb) self.syncWindow.title("Manual Synchronization") def getData(self): """ Gets trace from FEMB and returns 4 1D arrays: times, ADC counts """ data = self.femb.get_data_chipX(chip=self.chip, packets=self.packets, data_format="counts", tagged=False, header=False) # data = [[1,2,3,4,5,6,7,8,9,10]]*16 timestamp = datetime.datetime.now() if data == None: return None, None, None if len(data) == 0: return None, None, None xpoint = [] for num, samp in enumerate(data[0]): xpoint.append(num * float(self.config["DEFAULT"]["SAMPLE_PERIOD"])) return xpoint, data, timestamp
class TRACE_ALLCHAN_WINDOW(Tk.Frame): """ This window displays a live ADC redout """ def __init__(self, master=None): self.maxtraces = 5 self.selChan = 0 Tk.Frame.__init__(self, master) # hack to make work in python2 self.pack() self.figure = Figure(figsize=(20, 8), dpi=100, facecolor='white') self.canvas = FigureCanvas(self.figure, master=self) self.canvas.show() self.canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) self.toolbar = NaviationToolbar(self.canvas, self) self.toolbar.update() self.canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) self.pauseButton = Tk.Button(self, text="Pause", command=self.pause) self.pauseButton.pack(side=Tk.LEFT) self.playButton = Tk.Button(self, text="Play", command=self.play, state=Tk.DISABLED) self.playButton.pack(side=Tk.LEFT) self.prevButton = Tk.Button(self, text="Previous Trace", command=self.prevTrace, state=Tk.DISABLED) self.prevButton.pack(side=Tk.LEFT) self.nextButton = Tk.Button(self, text="Next Trace", command=self.nextTrace, state=Tk.DISABLED) self.nextButton.pack(side=Tk.LEFT) self.femb = None self.iTrace = -1 self.traces = [] self.timestamps = [] self.reset() def reset(self, iTrace=None): self.femb = FEMB_UDP() self.femb_config = CONFIG() self.figure.clf() self.subgs = [None] * 16 * 4 self.ax = [None] * 16 * 4 self.plot = [None] * 16 * 4 # 4x4x4 grid, one cell per channel self.gs = gridspec.GridSpec(4, 16) self.gs.update(wspace=0.2, hspace=0.2) # 1 plots per channel for row in range(4): for col in range(16): self.subgs[col + 16 * row] = gridspec.GridSpecFromSubplotSpec( 1, 1, subplot_spec=self.gs[col + 16 * row], hspace=0.0) self.ax[col + 16 * row] = self.figure.add_subplot( self.subgs[col + 16 * row][0]) self.ax[col + 16 * row].tick_params(axis='x', colors='black', labelsize='medium') self.ax[col + 16 * row].tick_params(axis='y', colors='black', labelsize='smaller') if iTrace is None: self.ani = animation.FuncAnimation(self.figure, self.plotData, interval=100, blit=True) else: self.plotData(0, iTrace) self.canvas.draw() def pause(self): self.ani.event_source.stop() self.reset(self.iTrace) self.pauseButton['state'] = Tk.DISABLED self.playButton['state'] = Tk.NORMAL self.prevButton['state'] = Tk.NORMAL self.nextButton['state'] = Tk.DISABLED def play(self): self.ani.event_source.start() self.pauseButton['state'] = Tk.NORMAL self.playButton['state'] = Tk.DISABLED self.prevButton['state'] = Tk.DISABLED self.nextButton['state'] = Tk.DISABLED def prevTrace(self): self.iTrace -= 1 self.reset(self.iTrace) if self.iTrace < 1: self.prevButton['state'] = Tk.DISABLED else: self.prevButton['state'] = Tk.NORMAL if self.iTrace >= len(self.traces) - 1: self.nextButton['state'] = Tk.DISABLED else: self.nextButton['state'] = Tk.NORMAL def nextTrace(self): self.iTrace += 1 self.reset(self.iTrace) if self.iTrace < 1: self.prevButton['state'] = Tk.DISABLED else: self.prevButton['state'] = Tk.NORMAL if self.iTrace >= len(self.traces) - 1: self.nextButton['state'] = Tk.DISABLED else: self.nextButton['state'] = Tk.NORMAL def plotData(self, iFrame, iTrace=None): for a in self.ax: a.cla() a.locator_params(tight=True, nbins=3) # In case no data, return an empty plot self.plot[0] = self.ax[0].plot() for a in range(4): #for a in [2]: #if a != 0: # continue asicNum = a #asicNum = 2 self.femb_config.setExtClockRegs(asicNum) self.femb_config.selectAsic(asicNum) #self.femb_config.doAdcAsicConfig(a) #self.femb_config.initAsic(a) chPlots, thistimestamp = self.getTraceAndFFT(iTrace=iTrace) if chPlots == None: continue if thistimestamp == None: continue if len(chPlots) != 16: continue for chan in range(0, 16, 1): t = chPlots[chan][0] adc = chPlots[chan][1] if not (t is None) and not (adc is None): self.plot[chan + 16 * a] = self.ax[chan + 16 * a].plot( t, adc) #if c+4*r < 12: self.ax[c+4*r].set_xticklabels([]) self.figure.text(0.5, 0.02, 'Time [us]', ha='center', color='black', fontsize='25.0', weight='bold') self.figure.text(0.08, 0.5, 'ADC', ha='center', rotation=90, color='black', fontsize='25.0', weight='bold') if not (thistimestamp is None): self.figure.suptitle( thistimestamp.replace(microsecond=0).isoformat(" ")) self.canvas.draw() return self.plot[0] def getTraceAndFFT(self, iTrace=None): """ Gets trace from FEMB and returns 4 1D arrays: times, ADC counts """ data = None timestamp = None if iTrace is None: data = self.femb.get_data(5) timestamp = datetime.datetime.now() self.traces.append(data) self.timestamps.append(timestamp) if len(self.traces) > self.maxtraces: self.traces.pop(0) self.timestamps.pop(0) self.iTrace = len(self.traces) - 1 else: data = self.traces[iTrace] timestamp = self.timestamps[iTrace] if data == None: return None, None if len(data) == 0: return None, None chSamples = self.convertHighSpeedPacked(data) if len(chSamples) != 16: return None, None chPlots = [] for chan in range(0, 16, 1): xpoint = [] ypoint = [] num = 0 for samp in chSamples[chan]: xpoint.append(num * 0.5) ypoint.append(samp) num = num + 1 xarr = np.array(xpoint) yarr = np.array(ypoint) chPlots.append([xarr, yarr]) return chPlots, timestamp #taken from write_root_tree def convertHighSpeedPacked(self, data): packetNum = 0 wordArray = [] result = [[] for chan in range(16)] for word in data: if str(hex(word)) == "0xface": packetNum = 0 wordArray = [] if packetNum > 0 and packetNum < 13: wordArray.append(word) if packetNum == 12: result[0].append(((wordArray[5] & 0xFFF0) >> 4)) result[1].append(((wordArray[4] & 0xFF00) >> 8) | ((wordArray[5] & 0x000F) << 8)) result[2].append(((wordArray[4] & 0x00FF) << 4) | ((wordArray[3] & 0xF000) >> 12)) result[3].append(((wordArray[3] & 0x0FFF) >> 0)) result[4].append(((wordArray[2] & 0xFFF0) >> 4)) result[5].append(((wordArray[2] & 0x000F) << 8) | ((wordArray[1] & 0xFF00) >> 8)) result[6].append(((wordArray[1] & 0x00FF) << 4) | ((wordArray[0] & 0xF000) >> 12)) result[7].append(((wordArray[0] & 0x0FFF) >> 0)) result[8].append(((wordArray[11] & 0xFFF0) >> 4)) result[9].append(((wordArray[11] & 0x000F) << 8) | ((wordArray[10] & 0xFF00) >> 8)) result[10].append(((wordArray[10] & 0x00FF) << 4) | ((wordArray[9] & 0xF000) >> 12)) result[11].append(((wordArray[9] & 0x0FFF))) result[12].append(((wordArray[8] & 0xFFF0) >> 4)) result[13].append(((wordArray[8] & 0x000F) << 8) | ((wordArray[7] & 0xFF00) >> 8)) result[14].append(((wordArray[7] & 0x00FF) << 4) | ((wordArray[6] & 0xF000) >> 12)) result[15].append(((wordArray[6] & 0x0FFF))) packetNum = packetNum + 1 return result
class TRACE_FFT_WINDOW(Tk.Frame): """ This window displays a live ADC redout and its FFT """ def __init__(self, master=None): self.maxtraces = 5 Tk.Frame.__init__(self, master) # hack to make work in python2 self.pack() self.figure = Figure(figsize=(8, 8), dpi=100) self.canvas = FigureCanvas(self.figure, master=self) self.canvas.show() self.canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) self.toolbar = NaviationToolbar(self.canvas, self) self.toolbar.update() self.canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) self.pauseButton = Tk.Button(self, text="Pause", command=self.pause) self.pauseButton.pack(side=Tk.LEFT) self.playButton = Tk.Button(self, text="Play", command=self.play, state=Tk.DISABLED) self.playButton.pack(side=Tk.LEFT) self.prevButton = Tk.Button(self, text="Previous Trace", command=self.prevTrace, state=Tk.DISABLED) self.prevButton.pack(side=Tk.LEFT) self.nextButton = Tk.Button(self, text="Next Trace", command=self.nextTrace, state=Tk.DISABLED) self.nextButton.pack(side=Tk.LEFT) self.femb = None self.iTrace = -1 self.traces = [] self.timestamps = [] self.reset() def reset(self, iTrace=None): self.femb = FEMB_UDP() self.figure.clf() self.ax1 = self.figure.add_subplot(211) self.ax2 = self.figure.add_subplot(212) self.plot1 = self.ax1.plot([], []) self.plot2 = self.ax2.plot([], []) if iTrace is None: self.ani = animation.FuncAnimation(self.figure, self.plotData, interval=1000, blit=True) else: self.plotData(0, iTrace) self.canvas.draw() def pause(self): self.ani.event_source.stop() self.reset(self.iTrace) self.pauseButton['state'] = Tk.DISABLED self.playButton['state'] = Tk.NORMAL self.prevButton['state'] = Tk.NORMAL self.nextButton['state'] = Tk.DISABLED def play(self): self.ani.event_source.start() self.pauseButton['state'] = Tk.NORMAL self.playButton['state'] = Tk.DISABLED self.prevButton['state'] = Tk.DISABLED self.nextButton['state'] = Tk.DISABLED def prevTrace(self): self.iTrace -= 1 self.reset(self.iTrace) if self.iTrace < 1: self.prevButton['state'] = Tk.DISABLED else: self.prevButton['state'] = Tk.NORMAL if self.iTrace >= len(self.traces) - 1: self.nextButton['state'] = Tk.DISABLED else: self.nextButton['state'] = Tk.NORMAL def nextTrace(self): self.iTrace += 1 self.reset(self.iTrace) if self.iTrace < 1: self.prevButton['state'] = Tk.DISABLED else: self.prevButton['state'] = Tk.NORMAL if self.iTrace >= len(self.traces) - 1: self.nextButton['state'] = Tk.DISABLED else: self.nextButton['state'] = Tk.NORMAL def plotData(self, iFrame, iTrace=None): self.ax1.cla() self.ax2.cla() self.ax1.set_xlabel("Time [us]") self.ax1.set_ylabel("Sample Value [ADC Counts]") self.ax2.set_xlabel("Frequency [MHz]") self.ax2.set_ylabel("|Y(freq)|") t, adc, frq, ampl, thistimestamp = self.getTraceAndFFT(iTrace=iTrace) if not (t is None) and not (adc is None): self.plot1 = self.ax1.plot(t, adc) if not (frq is None) and not (ampl is None): self.plot2 = self.ax2.plot(frq, ampl, 'r') if not (thistimestamp is None): self.figure.suptitle( thistimestamp.replace(microsecond=0).isoformat(" ")) self.canvas.draw() return self.plot1 def getTraceAndFFT(self, iTrace=None): """ Gets trace from FEMB and returns 4 1D arrays: times, ADC counts, frequencies, Amplitude """ Yfft_total = [] first = 1 data = None timestamp = None if iTrace is None: data = self.femb.get_data(10) timestamp = datetime.datetime.now() self.traces.append(data) self.timestamps.append(timestamp) if len(self.traces) > self.maxtraces: self.traces.pop(0) self.timestamps.pop(0) self.iTrace = len(self.traces) - 1 else: data = self.traces[iTrace] timestamp = self.timestamps[iTrace] if data == None: #time.sleep(1.) return None, None, None, None, None if len(data) == 0: #time.sleep(1.) return None, None, None, None, None xpoint = [] ypoint = [] num = 0 for samp in data: chNum = ((samp >> 12) & 0xF) sampVal = (samp & 0xFFF) #print str(chNum) + "\t" + str(sampVal) + "\t" + str( hex(sampVal) ) #if chNum == 0: xpoint.append(num * 0.5) ypoint.append(sampVal) num = num + 1 xarr = np.array(xpoint) yarr = np.array(ypoint) Fs = 2.0 # sampling rate Ts = 1.0 / Fs # sampling interval t = np.arange(0, 1, Ts) # time vector n = len(yarr) # length of the signal k = np.arange(n) T = n / Fs frq = k / T # two sides frequency range frq = frq[:n // 2] # one side frequency range Yfft = np.fft.fft(yarr) / n # fft computing and normalization Yfft = Yfft[:n // 2] frq = frq[1:] Yfft = Yfft[1:] #do averaging and normalization, very messy pos = 0 total = 0 for x in np.nditer(Yfft): #print abs(x) total = total + abs(x) if first == 1: Yfft_total.append(abs(x)) else: Yfft_total[pos] = Yfft_total[pos] + abs(x) pos = pos + 1 first = 0 if total < 0: #time.sleep(0.1) return None, None, None, None pos = 0 Yfft_norm = [] for bin in Yfft_total: Yfft_norm.append(bin / total) return xarr, yarr, frq, Yfft_norm, timestamp
class TRACE_FFT_ALLCHAN_WINDOW(Tk.Frame): """ This window displays a live ADC redout and its FFT """ def __init__(self, master=None): self.maxtraces = 5 self.selChan = 0 Tk.Frame.__init__(self, master) # hack to make work in python2 self.pack() #self.figure = Figure(figsize=(14,9), dpi=100, facecolor='gray') self.figure = Figure(figsize=(14, 8), dpi=100, facecolor='gray') self.canvas = FigureCanvas(self.figure, master=self) self.canvas.show() self.canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) self.toolbar = NaviationToolbar(self.canvas, self) self.toolbar.update() self.canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) self.pauseButton = Tk.Button(self, text="Pause", command=self.pause) self.pauseButton.pack(side=Tk.LEFT) self.playButton = Tk.Button(self, text="Play", command=self.play, state=Tk.DISABLED) self.playButton.pack(side=Tk.LEFT) self.prevButton = Tk.Button(self, text="Previous Trace", command=self.prevTrace, state=Tk.DISABLED) self.prevButton.pack(side=Tk.LEFT) self.nextButton = Tk.Button(self, text="Next Trace", command=self.nextTrace, state=Tk.DISABLED) self.nextButton.pack(side=Tk.LEFT) self.femb = None self.iTrace = -1 self.traces = [] self.timestamps = [] self.reset() def reset(self, iTrace=None): self.femb = FEMB_UDP() self.figure.clf() self.subgs = [None] * 16 self.ax = [None] * 32 self.plot = [None] * 32 # 4x4 grid, one cell per channel self.gs = gridspec.GridSpec(4, 4) self.gs.update(wspace=0.2, hspace=0.2) # 2 plots per channel for row in range(4): for col in range(4): self.subgs[col + 4 * row] = gridspec.GridSpecFromSubplotSpec( 2, 1, subplot_spec=self.gs[col + 4 * row], hspace=0.0) self.ax[col + 8 * row] = self.figure.add_subplot( self.subgs[col + 4 * row][0]) self.ax[col + 8 * row].tick_params(axis='x', colors='blue') self.ax[col + 8 * row].tick_params(axis='y', colors='blue') self.ax[col + 8 * row].xaxis.tick_top() self.ax[col + 8 * row].yaxis.tick_right() self.ax[4 + col + 8 * row] = self.figure.add_subplot( self.subgs[col + 4 * row][1]) self.ax[4 + col + 8 * row].tick_params(axis='x', colors='red') self.ax[4 + col + 8 * row].tick_params(axis='y', colors='red') if iTrace is None: self.ani = animation.FuncAnimation(self.figure, self.plotData, interval=1000, blit=True) else: self.plotData(0, iTrace) self.canvas.draw() def pause(self): self.ani.event_source.stop() self.reset(self.iTrace) self.pauseButton['state'] = Tk.DISABLED self.playButton['state'] = Tk.NORMAL self.prevButton['state'] = Tk.NORMAL self.nextButton['state'] = Tk.DISABLED def play(self): self.ani.event_source.start() self.pauseButton['state'] = Tk.NORMAL self.playButton['state'] = Tk.DISABLED self.prevButton['state'] = Tk.DISABLED self.nextButton['state'] = Tk.DISABLED def prevTrace(self): self.iTrace -= 1 self.reset(self.iTrace) if self.iTrace < 1: self.prevButton['state'] = Tk.DISABLED else: self.prevButton['state'] = Tk.NORMAL if self.iTrace >= len(self.traces) - 1: self.nextButton['state'] = Tk.DISABLED else: self.nextButton['state'] = Tk.NORMAL def nextTrace(self): self.iTrace += 1 self.reset(self.iTrace) if self.iTrace < 1: self.prevButton['state'] = Tk.DISABLED else: self.prevButton['state'] = Tk.NORMAL if self.iTrace >= len(self.traces) - 1: self.nextButton['state'] = Tk.DISABLED else: self.nextButton['state'] = Tk.NORMAL def plotData(self, iFrame, iTrace=None): for a in self.ax: a.cla() a.locator_params(tight=True, nbins=3) # in case no data, return an empty plot self.plot[0] = self.ax[0].plot() for r in range(4): for c in range(4): t, adc, frq, amp, thistimestamp = self.getTraceAndFFT( iTrace=iTrace, chan=c + 4 * r) if not (t is None) and not (adc is None): self.plot[c + 8 * r] = self.ax[c + 8 * r].plot(t, adc) if c + 8 * r > 3: self.ax[c + 8 * r].set_xticklabels([]) if not (frq is None) and not (amp is None): self.plot[4 + c + 8 * r] = self.ax[4 + c + 8 * r].plot( frq, amp, 'r') if 4 + c + 8 * r < 28: self.ax[4 + c + 8 * r].set_xticklabels([]) self.figure.text(0.45, 0.04, 'Time [us]', ha='center', color='blue') self.figure.text(0.55, 0.04, 'Frequency [MHz]', ha='center', color='red') self.figure.text(0.042, 0.45, 'ADC', ha='center', rotation=90, color='blue') self.figure.text(0.04, 0.55, '|Y(freq)|', ha='center', rotation=90, color='red') if not (thistimestamp is None): self.figure.suptitle( thistimestamp.replace(microsecond=0).isoformat(" ")) self.canvas.draw() return self.plot[0] def getTraceAndFFT(self, iTrace=None, chan=0): """ Gets trace from FEMB and returns 4 1D arrays: times, ADC counts, frequencies, Amplitude """ Yfft_total = [] first = 1 data = None timestamp = None if iTrace is None: data = self.femb.get_data(100) timestamp = datetime.datetime.now() self.traces.append(data) self.timestamps.append(timestamp) if len(self.traces) > self.maxtraces: self.traces.pop(0) self.timestamps.pop(0) self.iTrace = len(self.traces) - 1 else: data = self.traces[iTrace] timestamp = self.timestamps[iTrace] if data == None: #time.sleep(1.) return None, None, None, None, None if len(data) == 0: #time.sleep(1.) return None, None, None, None, None xpoint = [] ypoint = [] num = 0 packetNum = 0 wordArray = [] for word in data: #print(str(packetNum) + "\t" + str(hex(word)) ) if str(hex(word)) == "0xface": packetNum = 0 wordArray = [] if packetNum > 0 and packetNum < 13: wordArray.append(word) if packetNum == 12: chSamp = [] for i in range(0, 16, 1): chSamp.append(0) chSamp[0] = ((wordArray[5] & 0xFFF0) >> 4) chSamp[1] = ((wordArray[4] & 0xFF00) >> 8) | ( (wordArray[5] & 0x000F) << 8) chSamp[2] = ((wordArray[4] & 0x00FF) << 4) | ( (wordArray[3] & 0xF000) >> 12) chSamp[3] = ((wordArray[3] & 0x0FFF) >> 0) chSamp[4] = ((wordArray[2] & 0xFFF0) >> 4) chSamp[5] = ((wordArray[2] & 0x000F) << 8) | ( (wordArray[1] & 0xFF00) >> 8) chSamp[6] = ((wordArray[1] & 0x00FF) << 4) | ( (wordArray[0] & 0xF000) >> 12) chSamp[7] = ((wordArray[0] & 0x0FFF) >> 0) chSamp[8] = ((wordArray[11] & 0xFFF0) >> 4) chSamp[9] = ((wordArray[11] & 0x000F) << 8) | ( (wordArray[10] & 0xFF00) >> 8) chSamp[10] = ((wordArray[10] & 0x00FF) << 4) | ( (wordArray[9] & 0xF000) >> 12) chSamp[11] = ((wordArray[9] & 0x0FFF)) chSamp[12] = ((wordArray[8] & 0xFFF0) >> 4) chSamp[13] = ((wordArray[8] & 0x000F) << 8) | ( (wordArray[7] & 0xFF00) >> 8) chSamp[14] = ((wordArray[7] & 0x00FF) << 4) | ( (wordArray[6] & 0xF000) >> 12) chSamp[15] = ((wordArray[6] & 0x0FFF)) xpoint.append(num * 0.5) ypoint.append(chSamp[int(chan)]) num = num + 1 packetNum = packetNum + 1 #return None, None, None, None, None #for samp in data: # chNum = ((samp >> 12 ) & 0xF) # sampVal = (samp & 0xFFF) # #print str(chNum) + "\t" + str(sampVal) + "\t" + str( hex(sampVal) ) # #if chNum == 0: # xpoint.append(num*0.5) # ypoint.append(sampVal) # num = num + 1 xarr = np.array(xpoint) yarr = np.array(ypoint) Fs = 2.0 # sampling rate Ts = 1.0 / Fs # sampling interval t = np.arange(0, 1, Ts) # time vector n = len(yarr) # length of the signal k = np.arange(n) T = n / Fs frq = k / T # two sides frequency range frq = frq[:n // 2] # one side frequency range Yfft = np.fft.fft(yarr) / n # fft computing and normalization Yfft = Yfft[:n // 2] frq = frq[1:] Yfft = Yfft[1:] #do averaging and normalization, very messy pos = 0 total = 0 for x in np.nditer(Yfft): #print abs(x) total = total + abs(x) if first == 1: Yfft_total.append(abs(x)) else: Yfft_total[pos] = Yfft_total[pos] + abs(x) pos = pos + 1 first = 0 if total < 0: #time.sleep(0.1) return None, None, None, None pos = 0 Yfft_norm = [] for bin in Yfft_total: Yfft_norm.append(bin / total) return xarr, yarr, frq, Yfft_norm, timestamp
class TRACE_ROOT_WINDOW(Tk.Frame): """ This window displays the trace from a root file """ def __init__(self, infilename, sampleMax=None, fullADCRange=False, master=None): Tk.Frame.__init__(self, master) # hack to make work in python2 self.pack() self.figure = Figure(figsize=(8, 8), dpi=100) self.axs = [] for iPlot in range(16): self.axs.append(self.figure.add_subplot(4, 4, iPlot + 1)) self.canvas = FigureCanvas(self.figure, master=self) self.canvas.show() self.canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) self.toolbar = NaviationToolbar(self.canvas, self) self.toolbar.update() self.canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) self.draw_trace(infilename, sampleMax=sampleMax, fullADCRange=fullADCRange) def loadWaveform(self, filename): """ result[freq][amp][iChip][iChan][iSample] """ f = ROOT.TFile(filename) if f.IsZombie(): raise FileNotFoundError(filename) tree = f.Get("femb_wfdata") metadataTree = f.Get("metadata") metadatas = [] amplitudes = set() frequencies = set() metadataTree.GetEntry(0) metadata = { 'funcType': metadataTree.funcType, 'funcAmp': metadataTree.funcAmp, 'funcOffset': metadataTree.funcOffset, 'funcFreq': metadataTree.funcFreq, 'iChip': metadataTree.iChip, 'adcSerial': str(metadataTree.adcSerial), 'feSerial': metadataTree.feSerial, } ##### voltageGood = bool(tree.GetBranch("voltage")) calibrationTree = f.Get("calibration") voltages = {} calibSlopes = {} calibInters = {} ##### result = {} for iEntry in range(tree.GetEntries()): tree.GetEntry(iEntry) iChannel = int(tree.chan) % 16 adccodes = list(tree.wf) #if self.nBits < 12: # adccodes = [i >> (12 - self.nBits) for i in adccodes] try: result[iChannel].extend(adccodes) except KeyError: result[iChannel] = adccodes if voltageGood: voltagesTmp = list(tree.voltage) try: voltages[iChannel].extend(voltagesTmp) except KeyError: voltages[iChannel] = voltagesTmp if calibrationTree: calibrationTree.GetEntry(iEntry) calibSlopes[iChannel] = float(calibrationTree.voltsPerADC) calibInters[iChannel] = float(calibrationTree.voltsIntercept) if not voltageGood: voltages = None if not calibrationTree: calibSlopes = None calibInters = None self.waveforms = result self.metadata = metadata del metadataTree del calibrationTree del tree f.Close() del f return result, metadata, voltages, calibSlopes, calibInters def draw_trace(self, infilename, sampleMax=None, fullADCRange=False): waveforms, metadata, voltages, calibSlopes, calibInters = self.loadWaveform( infilename) # self.figure.suptitle("Waveforms for socket: {}, FE: {} ADC: {}".format(metadata['iChip'],metadata['feSerial'],metadata['adcSerial']),fontsize="large") iChip = metadata['iChip'] feSerial = metadata['feSerial'] adcSerial = metadata['adcSerial'] suptitleStr = "Waveforms for socket: {}, FE: {} ADC: {}".format( iChip, feSerial, adcSerial) self.figure.suptitle(suptitleStr, fontsize="large") axRights = [] for iChan in waveforms: ax = self.axs[iChan] waveform = waveforms[iChan] if fullADCRange: ax.set_ylim(0, 4096) if sampleMax: ax.set_xlim(0, sampleMax) if not (voltages is None): if not (calibSlopes is None): ax.plot( numpy.array(voltages[iChan]) / calibSlopes[iChan] - calibInters[iChan] / calibSlopes[iChan], "-g") axRight = ax.twinx() ylow, yhigh = ax.get_ylim() ylow = ylow * calibSlopes[iChan] + calibInters[iChan] yhigh = yhigh * calibSlopes[iChan] + calibInters[iChan] axRight.set_ylim(ylow * 1000., yhigh * 1000.) if iChan % 4 == 3: axRight.set_ylabel("Voltage [mV]") axRights.append(axRight) else: ax.plot(voltages[iChan], "-g") ax.plot(waveform, "-b") ax.set_title("Channel: {}".format(iChan)) if iChan // 4 == 3: ax.set_xlabel("Time Sample") if iChan % 4 == 0: ax.set_ylabel("ADC Code")
class CustomDialog(Dialog): def __init__(self, parent, title, components): if not parent: parent = Tkinter._default_root self.results = None self.components = components Dialog.__init__(self, parent, title) def destroy(self): self.components = None Dialog.destroy(self) def body(self, master): first_entry = None row = 0 grid_frame = Tkinter.Frame(master) # Form plot_frame = Tkinter.Frame(master) # Plot stats_frame = Tkinter.Frame(master) # Listbox for i, component in enumerate(self.components): row += i if component["type"].lower() == "label": component["object"] = Tkinter.Label(grid_frame, text=component["text"]) component["object"].grid(row=row, columnspan=2) if component["type"].lower() == "entry": Tkinter.Label(grid_frame, text=component["text"]).grid(row=row, sticky=Tkinter.W) component["object"] = Tkinter.Entry(grid_frame, justify=Tkinter.RIGHT) component["object"].delete(0, Tkinter.END) component["object"].insert(0, str(component["default"])) component["object"].grid(row=row, column=1) if first_entry is None: first_entry = component["object"] elif component["type"].lower() == "checkbutton": component["variable"] = Tkinter.IntVar() # set to 1 if the button is selected, and 0 otherwise component["variable"].set(component["default"]) component["object"] = Tkinter.Checkbutton(grid_frame, text=component["text"], variable=component["variable"]) component["object"].grid(row=row, columnspan=2, sticky=Tkinter.E) #elif component["type"].lower() == "combobox": elif component["type"].lower() == "optionmenu": if len(component["options"]) <= 0: raise Exception("Options needed!") Tkinter.Label(grid_frame, text=component["text"]).grid(row=row, sticky=Tkinter.W) component["variable"] = Tkinter.StringVar() if "ttk" in sys.modules.keys(): # It supports better long lists of options max_width = 20 for value in component["options"]: if len(value) > max_width: max_width = len(value)+1 component["variable"].set(component["default"]) component["object"] = ttk.Combobox(grid_frame, textvariable=component["variable"], state='readonly', width=max_width) component["object"]['values'] = tuple(component["options"]) component["object"].grid(row=row, column=1, sticky=Tkinter.W) else: Tkinter.Label(grid_frame, text=component["text"]).grid(row=row, sticky=Tkinter.W) component["variable"] = Tkinter.StringVar() component["variable"].set(component["default"]) component["object"] = apply(Tkinter.OptionMenu, (grid_frame, component["variable"]) + tuple(component["options"])) component["object"].grid(row=row, column=1, sticky=Tkinter.W) elif component["type"].lower() == "radiobutton": Tkinter.Label(grid_frame, text=component["text"]).grid(row=row, sticky=Tkinter.W) component["variable"] = Tkinter.StringVar() objects = [] for j, text in enumerate(component["options"]): objects.append(Tkinter.Radiobutton(grid_frame, text=text, variable=component["variable"], value=text)) objects[-1].grid(row=row, column=1, sticky=Tkinter.W) row += 1 component["variable"].set(component["default"]) elif component["type"].lower() == "listbox" and component["options"] is not None and len(component["options"]) > 0: stats_scrollbar = Tkinter.Scrollbar(stats_frame, orient=Tkinter.VERTICAL) component["object"] = Tkinter.Listbox(stats_frame, height=5, yscrollcommand=stats_scrollbar.set, font=('courier',10,'normal'), selectmode=Tkinter.EXTENDED) stats_scrollbar.pack(side=Tkinter.RIGHT, fill=Tkinter.Y) component["object"].delete(0, Tkinter.END) # Delete all for text in component["options"]: component["object"].insert(Tkinter.END, text) component["object"].pack(fill=Tkinter.BOTH, expand=1) elif component["type"].lower() == "plot" and component["function"] is not None: # Create the mpl Figure and FigCanvas objects. # 5x4 inches, 100 dots-per-inch # self.dpi = 100 self.fig = Figure((6.0, 3.0), dpi=self.dpi) self.canvas = FigCanvas(self.fig, master=plot_frame) self.canvas.show() #self.canvas.get_tk_widget().grid(row = 0, column = 0) # or .grid(row = 0) ### Since we have only one plot, we can use add_axes ### instead of add_subplot, but then the subplot ### configuration tool in the navigation toolbar wouldn't ### work. ### if component["axes"] == 1: self.axes = self.fig.add_subplot(1, 1, 1) #### Avoid using special notation that are not easy to understand in axis for big zoom myyfmt = ScalarFormatter(useOffset=False) self.axes.get_xaxis().set_major_formatter(myyfmt) self.axes.get_yaxis().set_major_formatter(myyfmt) self.toolbar = NavigationToolbar(self.canvas, plot_frame) self.toolbar.update() self.canvas._tkcanvas.pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=1) elif component["axes"] > 1: self.axes = [] for i in xrange(component["axes"]): self.axes.append(self.fig.add_subplot(2, 1, i+1)) #### Avoid using special notation that are not easy to understand in axis for big zoom myyfmt = ScalarFormatter(useOffset=False) self.axes[i].get_xaxis().set_major_formatter(myyfmt) self.axes[i].get_yaxis().set_major_formatter(myyfmt) self.toolbar = NavigationToolbar(self.canvas, plot_frame) self.toolbar.update() self.canvas._tkcanvas.pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=1) # Plotting function apply(component["function"], (self.axes, component)) plot_frame.pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=1) stats_frame.pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=1) grid_frame.pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=1) # Which should receive focus: return first_entry def validate(self): for component in self.components: if component["type"] == "Entry": try: #value = float(component["object"].get()) if component["text-type"] == "str": value = eval(component["text-type"] + "('%s')" % component["object"].get()) else: value = eval(component["text-type"] + "(%s)" % component["object"].get()) except Exception: tkMessageBox.showwarning( "Illegal value", "Illegal value for " + component["text"] + "\nPlease try again", parent = self ) return 0 if component["minvalue"] is not None and value < component["minvalue"]: tkMessageBox.showwarning( "Too small", "'%s': " "The allowed minimum value is %s. " "Please try again." % (component["text"], component["minvalue"]), parent = self ) return 0 if component["maxvalue"] is not None and value > component["maxvalue"]: tkMessageBox.showwarning( "Too big", "'%s': " "The allowed maximum value is %s. " "Please try again." % (component["text"], component["maxvalue"]), parent = self ) return 0 return 1 def apply(self): self.results = {} for component in self.components: # Save results and modify defaults if component["type"] == "Entry": if component["text-type"] == "str": value = eval(component["text-type"] + "('%s')" % component["object"].get()) else: value = eval(component["text-type"] + "(%s)" % component["object"].get()) self.results[component["text"]] = value component["default"] = str(value) elif component["type"] in ["Checkbutton", "OptionMenu", "Radiobutton"]: self.results[component["text"]] = component["variable"].get() component["default"] = component["variable"].get()