コード例 #1
0
ファイル: gat.py プロジェクト: FedorSarafanov/bin
class MyProgram():
    def __init__(self):
        #some_gtk_stuff
        self.builder = Gtk.Builder()
        self.builder.add_from_file("u.glade")
        self.window = self.builder.get_object("window1")
        # sw = builder.get_object("sw")
        # canvas = FigureCanvas(fig)
        # sw.add_with_viewport(canvas)
        self.signals = {
            'cos_clicked': self.create_plot,
            'sin_clicked': self.create_plot,
            'sq_clicked': self.create_plot,
            'on_window1_destroy': self.on_window1_destroy,
        }
        self.builder.connect_signals(self.signals)

        self.vbox = self.builder.get_object('vbox')

        self.figure = plt.figure(figsize=(1, 1), dpi=100)
        # self.axis = self.figure.add_subplot(111)
        # self.figure = Figure(figsize=(1,1), dpi=100)
        self.ax = self.figure.add_subplot(111)
        self.canvas = None

        self.window.set_size_request(700, 500)
        self.window.show_all()

    def create_plot(self, button):
        self.ani = animation.FuncAnimation(self.figure,
                                           self.update_plot,
                                           interval=1000)

    def on_window1_destroy(self, *args):
        Gtk.main_quit(*args)

    def update_plot(self, i):
        #read SampleData from txt File
        x = []
        y = []
        with open('s.dat') as f:
            x_raw, y_raw = f.readline().strip().split(',')
            x.append(int(x_raw))
            y.append(int(y_raw))

        self.axis.plot(x, y)

        if not self.canvas:
            self.canvas = FigureCanvas(self.figure)
            self.vbox.pack_start(self.canvas)
            self.canvas.show()

        self.canvas.draw()
コード例 #2
0
class EditAtomTypeView(BaseView):
    builder = resource_filename(__name__, "glade/atoms.glade")
    top = "edit_atom_type"
    widget_format = "atom_%s"

    # ------------------------------------------------------------
    #      Initialisation and other internals
    # ------------------------------------------------------------
    def __init__(self, *args, **kwargs):
        BaseView.__init__(self, *args, **kwargs)

        self.graph_parent = self["view_graph"]
        self.setup_matplotlib_widget()

    def setup_matplotlib_widget(self):
        self.figure = Figure(dpi=72)

        self.plot = self.figure.add_subplot(111)
        self.figure.subplots_adjust(bottom=0.20)

        self.matlib_canvas = FigureCanvasGTK(self.figure)

        self.plot.autoscale_view()

        self.graph_parent.add(self.matlib_canvas)
        self.graph_parent.show_all()

    # ------------------------------------------------------------
    #      Methods & Functions
    # ------------------------------------------------------------
    def update_figure(self, x, y):
        self.plot.cla()
        self.plot.plot(x, y, 'k-', aa=True)
        self.plot.set_ylabel('Scattering factor', size=14, weight="heavy")
        self.plot.set_xlabel('2θ', size=14, weight="heavy")
        self.plot.autoscale_view()
        if self.matlib_canvas is not None:
            self.matlib_canvas.draw()
コード例 #3
0
ファイル: views.py プロジェクト: mathijs-dumon/PyXRD
class EditAtomTypeView(BaseView):
    builder = resource_filename(__name__, "glade/atoms.glade")
    top = "edit_atom_type"
    widget_format = "atom_%s"

    # ------------------------------------------------------------
    #      Initialisation and other internals
    # ------------------------------------------------------------
    def __init__(self, *args, **kwargs):
        BaseView.__init__(self, *args, **kwargs)

        self.graph_parent = self["view_graph"]
        self.setup_matplotlib_widget()

    def setup_matplotlib_widget(self):
        self.figure = Figure(dpi=72)

        self.plot = self.figure.add_subplot(111)
        self.figure.subplots_adjust(bottom=0.20)

        self.matlib_canvas = FigureCanvasGTK(self.figure)

        self.plot.autoscale_view()

        self.graph_parent.add(self.matlib_canvas)
        self.graph_parent.show_all()

    # ------------------------------------------------------------
    #      Methods & Functions
    # ------------------------------------------------------------
    def update_figure(self, x, y):
        self.plot.cla()
        self.plot.plot(x, y, 'k-', aa=True)
        self.plot.set_ylabel('Scattering factor', size=14, weight="heavy")
        self.plot.set_xlabel('2θ', size=14, weight="heavy")
        self.plot.autoscale_view()
        if self.matlib_canvas is not None:
            self.matlib_canvas.draw()
コード例 #4
0
ファイル: monitor.py プロジェクト: RickCarmichael/set64rs
class MonitorWindow(Gtk.Window):
    def __init__(self, pid):
        Gtk.Window.__init__(self, title="Monitor")
        self.pid = pid
        self.restart = False
        main_hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)

        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

        f = matplotlib.figure.Figure()
        self.axes = f.add_subplot(111)
        self.axes.set_xlabel('Time (sec.)')
        self.axes.set_ylabel('Temperature (C)')
        self.axes.autoscale()
        self.out_axes = self.axes.twinx()
        self.out_axes.set_ylabel('OUT (%)')
        self.out_axes.autoscale()
        self.axes.grid()
        self.pv_x = []
        self.pv_y = []
        self.sv_x = []
        self.sv_y = []
        self.out_x = []
        self.out_y = []
        self.pv_plot, = self.axes.plot(self.pv_x, self.pv_y, 'b--') #b
        self.sv_plot, = self.axes.plot(self.sv_x, self.sv_y, 'k-') #k
        self.out_plot, = self.out_axes.plot(self.out_x, self.out_y, 'r:') #r

        self.canvas = FigureCanvas(f)
        self.canvas.set_size_request(800,600)

        vbox.add(self.canvas)

        hbox = Gtk.Box()

        # Start/restart program
        button = Gtk.Button('First Step')
        button.connect('clicked', self.on_restart)
        hbox.pack_start(button, False, False, 0)

        button = Gtk.Button('Continue')
        button.connect('clicked', lambda x: self.pid.coil('next'))
        hbox.pack_start(button, False, False, 0)

        button = Gtk.Button('Pause')
        button.connect('clicked', lambda x: self.pid.coil('pause'))
        hbox.pack_start(button, False, False, 0)

        button = Gtk.Button('Last Step')
        button.connect('clicked', lambda x: self.pid.coil('end'))
        hbox.pack_start(button, False, False, 0)

        hbox.set_sensitive(False)
        vbox.add(hbox)
        main_hbox.add(vbox)

        # Extra information required
        #   Manual/automatic
        #   Program step
        #   Program status (running/pause)
        #   Time/time remaining in step
        #   PV/SV/dSV display?
        #   AL1/AL2

        self.add(main_hbox)

        table = Gtk.Table()
        row = 0

        combo = widgets.PIDComboBoxText(pid, 'ModL')
        pid.connect('changed', lambda pid, n, val, mult, w=combo: w.set_sensitive(not val['A/M']) if n == 'flags' else None)
        label = Gtk.Label('Mode')
        label.set_alignment(0, 0.5)
        table.attach(label, 0, 1, row, row+1, yoptions=Gtk.AttachOptions.SHRINK)
        table.attach(combo, 1, 2, row, row+1, yoptions=Gtk.AttachOptions.SHRINK)
        row += 1


        # Allow changing SV in manual mode
        # FIXME: disable if not SV?
        spin = widgets.PIDSpinButton(pid, 'SV')
        spin.set_sensitive(False)
        #combo.connect('changed', lambda combo, s=spin, c=combo: s.set_sensitive(c.get_active_text() == 'SV'))
        pid.connect('changed', lambda pid, n, val, mult, w=spin, c=combo: w.set_sensitive(not val['A/M'] and c.get_active_text() == 'SV') if n == 'flags' else None)
        pid.connect('changed', lambda pid, n, val, mult, w=spin: w.set_sensitive(val == 'SV') if n == 'ModL' else None)
        pid.connect('changed', lambda pid, n, val, mult, w=hbox: w.set_sensitive(val != 'SV') if n == 'ModL' else None)

        label = Gtk.Label('Set value')
        label.set_alignment(0, 0.5)
        table.attach(label, 0, 1, row, row+1, yoptions=Gtk.AttachOptions.SHRINK)
        table.attach(spin, 1, 2, row, row+1, yoptions=Gtk.AttachOptions.SHRINK)
        row += 1

        label = Gtk.Label('Dynamic SV')
        label.set_alignment(0, 0.5)
        table.attach(label, 0, 1, row, row+1, yoptions=Gtk.AttachOptions.SHRINK)
        label = Gtk.Label()
        label.set_alignment(0, 0.5)
        table.attach(label, 1, 2, row, row+1, yoptions=Gtk.AttachOptions.SHRINK)
        pid.connect('changed', lambda pid, n, val, mult, w=label: w.set_text('%0.1f'%val if mult == .1 else '%d'%val) if n == 'dSV' else None)
        row += 1

        label = Gtk.Label('PV')
        label.set_alignment(0, 0.5)
        table.attach(label, 0, 1, row, row+1, yoptions=Gtk.AttachOptions.SHRINK)
        label = Gtk.Label()
        label.set_alignment(0, 0.5)
        table.attach(label, 1, 2, row, row+1, yoptions=Gtk.AttachOptions.SHRINK)
        pid.connect('changed', lambda pid, n, val, mult, w=label: w.set_text('%0.1f'%val if mult == .1 else '%d'%val) if n == 'PV' else None)
        row += 1

        check = widgets.ActionCheckButton(lambda val: pid.coil('manual' if val else 'auto', val), read=lambda p=pid: p.flag('A/M'))
        pid.connect('changed', lambda pid, n, val, mult, w=check: w.set_active(val['A/M'], user=False) if n == 'flags' else None)
        label = Gtk.Label('Manual mode')
        label.set_alignment(0, 0.5)
        table.attach(label, 0, 1, row, row+1, yoptions=Gtk.AttachOptions.SHRINK)
        table.attach(check, 1, 2, row, row+1, yoptions=Gtk.AttachOptions.SHRINK)
        row += 1

        reg = pld.registers['OUT']
        spin = widgets.PIDSpinButton(pid, 'OUT')
        spin.set_sensitive(False)
        pid.connect('changed', lambda pid, n, val, mult, w=spin: w.set_sensitive(val['A/M']) if n == 'flags' else None)

        label = Gtk.Label('Output level')
        label.set_alignment(0, 0.5)
        table.attach(label, 0, 1, row, row+1, yoptions=Gtk.AttachOptions.SHRINK)
        table.attach(spin, 1, 2, row, row+1, yoptions=Gtk.AttachOptions.SHRINK)
        row += 1

        label = Gtk.Label('Alarm 1')
        label.set_alignment(0, 0.5)
        table.attach(label, 0, 1, row, row+1, yoptions=Gtk.AttachOptions.SHRINK)
        label = Gtk.Label()
        label.set_alignment(0, 0.5)
        table.attach(label, 1, 2, row, row+1, yoptions=Gtk.AttachOptions.SHRINK)
        pid.connect('changed', lambda pid, n, val, mult, w=label: w.set_text('On' if val['AL1'] else 'Off') if n == 'flags' else None)
        row += 1

        label = Gtk.Label('Alarm 2')
        label.set_alignment(0, 0.5)
        table.attach(label, 0, 1, row, row+1, yoptions=Gtk.AttachOptions.SHRINK)
        label = Gtk.Label()
        label.set_alignment(0, 0.5)
        table.attach(label, 1, 2, row, row+1, yoptions=Gtk.AttachOptions.SHRINK)
        pid.connect('changed', lambda pid, n, val, mult, w=label: w.set_text('On' if val['AL2'] else 'Off') if n == 'flags' else None)
        row += 1

        label = Gtk.Label('Current Step')
        label.set_alignment(0, 0.5)
        table.attach(label, 0, 1, row, row+1, yoptions=Gtk.AttachOptions.SHRINK)
        label = Gtk.Label()
        label.set_alignment(0, 0.5)
        table.attach(label, 1, 2, row, row+1, yoptions=Gtk.AttachOptions.SHRINK)
        self.current_step = label
        row += 1

        label = Gtk.Label('Time elapsed/total')
        label.set_alignment(0, 0.5)
        table.attach(label, 0, 1, row, row+1, yoptions=Gtk.AttachOptions.SHRINK)
        label = Gtk.Label()
        label.set_alignment(0, 0.5)
        table.attach(label, 1, 2, row, row+1, yoptions=Gtk.AttachOptions.SHRINK)
        self.step_time = label
        row += 1

        label = Gtk.Label('Step action')
        label.set_alignment(0, 0.5)
        table.attach(label, 0, 1, row, row+1, yoptions=Gtk.AttachOptions.SHRINK)
        label = Gtk.Label()
        label.set_alignment(0, 0.5)
        table.attach(label, 1, 2, row, row+1, yoptions=Gtk.AttachOptions.SHRINK)
        self.status = label
        row += 1

        main_hbox.add(table)

        self.run = True
        self.d = self.loop()
        self.d.addErrback(lambda x: None)
        self.connect('delete-event', self.on_delete)

    def on_restart(self, widget):
        self.restart = True

    def on_delete(self, widget, event):
        self.run = False

    @twisted.internet.defer.inlineCallbacks
    def loop(self):
        start = time.time()
        while self.run:
            if self.restart:
                start = time.time()
                self.pv_x = []
                self.pv_y = []
                self.sv_x = []
                self.sv_y = []
                self.out_x = []
                self.out_y = []
                self.axes.relim()
                self.axes.autoscale()
                self.canvas.draw()
                self.restart = False
                yield self.pid.coil('start')
                yield self.pid.coil('auto')
            try:

                val, mult = yield self.pid.holding_read('Pr+t')
                step, step_t = val
                val, mult = yield self.pid.holding_read('t-' + ('%02d' % step))
                step_total = 0
                if type(val) is tuple:
                    val, idx = val
                if val == 'Run':
                    step_total = idx
                elif val == 'Jump':
                    val += ' to ' + str(abs(idx))

                self.current_step.set_text(str(step))
                self.step_time.set_text(str(step_t) + '/' + str(step_total) if val == 'Run' else 'NA')
                self.status.set_text(val)

                pv, mult = yield self.pid.holding_read('PV')
                now = time.time() - start
                if len(self.pv_y) > 1 and self.pv_y[-2] == self.pv_y[-1] == pv:
                    self.pv_x[-1] = now
                else:
                    self.pv_x.append(now)
                    self.pv_y.append(pv)
                self.pv_plot.set_data(self.pv_x, self.pv_y)
                self.axes.relim()
                self.axes.autoscale()
                self.canvas.draw()

                sv, mult = yield self.pid.holding_read('dSV')
                now = time.time() - start
                if len(self.sv_y) > 1 and self.sv_y[-2] == self.sv_y[-1] == sv:
                    self.sv_x[-1] = now
                else:
                    self.sv_x.append(now)
                    self.sv_y.append(sv)
                self.sv_plot.set_data(self.sv_x, self.sv_y)
                self.axes.relim()
                self.axes.autoscale()
                self.canvas.draw()

                out, mult = yield self.pid.holding_read('OUT')
                now = time.time() - start
                if len(self.out_y) > 1 and self.out_y[-2] == self.out_y[-1] == out:
                    self.out_x[-1] = now
                else:
                    self.out_x.append(now)
                    self.out_y.append(out)
                self.out_plot.set_data(self.out_x, self.out_y)
                self.out_axes.relim()
                self.out_axes.autoscale()
                self.canvas.draw()
            except Exception, e:
                print 'monitor error', e
                traceback.print_exc(file=sys.stdout)

            d = twisted.internet.defer.Deferred()
            twisted.internet.reactor.callLater(0.300 , d.callback, None)
            yield d
コード例 #5
0
class StatPerspective(Gtk.Box, Ide.Perspective):

    """
    Sets up the stats perspective and handles the signals.

    This class sets up the containers of the perspective
    and the matplotlib figure and canvas. An asynchronous
    method iterates over the project and gathers the data
    for the plot.
    """

    def __init__(self, workdir, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.workdir = workdir

        # main containers
        scr_win = Gtk.ScrolledWindow(visible=True)
        pad_box = Gtk.Box(visible=True)
        pad_box.pack_start(scr_win, True, True, 20)

        main_box = Gtk.Box(visible=True, orientation=Gtk.Orientation.VERTICAL)
        scr_win.add_with_viewport(main_box)

        # content
        lbl_head = '<span font="36.0"><b>Project Stats</b></span>'
        heading = Gtk.Label(label=lbl_head, expand=True, visible=True)
        heading.set_use_markup(True)
        main_box.pack_start(heading, False, False, 0)
        line = Gtk.Separator(visible=True)
        main_box.pack_start(line, False, False, 0)

        self.fig = Figure(facecolor='none')
        self.ax = self.fig.add_subplot(111, axisbg='#ffffff')
        self.canvas = FigCanvas(self.fig)
        self.canvas.set_size_request(800, 600)
        self.canvas.draw()
        self.canvas.show()
        main_box.pack_start(self.canvas, True, True, 0)

        self.add(pad_box)
        self.titlebar = Ide.WorkbenchHeaderBar(visible=True)

         # Gather stats
        thread = threading.Thread(target=self.gather_stats)
        thread.daemon = True
        thread.start()

    def gather_stats(self):
        file_types = {}

        for root, subfolders, files in os.walk(self.workdir):
            for file in files:
                try:
                    with open(root + "/" + file) as fl:
                        line_count = 0
                        for line in fl:
                            line_count += 1

                        splt_str = file.split(".")
                        if len(splt_str) > 1:
                            file_ext = splt_str[-1]
                        else:
                            continue
                        if file_ext in file_types:
                            # key exists, add line count
                            file_types[file_ext] = file_types[file_ext] + line_count
                        else:
                            # key doesn't exist, create new key
                            file_types[file_ext] = line_count
                except:
                    continue

        keys = []
        values = []

        for key, value in file_types.items():
            keys.append(key)
            values.append(value)

        key_ar = np.array(keys)
        val_ar = np.array(values).astype(int)

        ar = np.vstack((key_ar, val_ar)).T
        ar = ar[ar[:,1].astype(int).argsort()]
        rows = ar.shape[0]
        val_pos = np.arange(1, ar.shape[0]+1)

        self.ax.barh(val_pos, ar[:,1].astype(int), 0.8, align="center")
        # facecolor='yellow'
        self.ax.set_yticks(val_pos)
        self.ax.tick_params(axis="both", which="major", pad=15)
        self.ax.set_yticklabels(ar[:,0], fontsize="16", weight="bold")
        self.ax.tick_params(axis="x", which="major", labelsize="16")

        self.canvas.set_size_request(800, (rows * 20 + 50))
        self.canvas.draw()

    def do_get_id(self):
        return 'hello-world2'

    def do_get_title(self):
        return 'Hello'

    def do_get_priority(self):
        return 10000

    def do_get_icon_name(self):
        return "utilities-system-monitor-symbolic"

    def do_get_titlebar(self):
        return self.titlebar
コード例 #6
0
ファイル: hp8903.py プロジェクト: cosmonaut/hp8903
class HP8903BWindow(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self, title="HP 8903B Control")

        # Serial connection!
        self.ser = None
        self.gpib_dev = None
        self.devices = list_ports.comports()
        
        # Menu Bar junk!
        action_group = Gtk.ActionGroup("my_actions")
        action_filemenu = Gtk.Action("FileMenu", "File", None, None)
        action_group.add_action(action_filemenu)
        self.action_filesave = Gtk.Action("FileSave", "Save Data", None, None)
        
        action_filequit = Gtk.Action("FileQuit", None, None, Gtk.STOCK_QUIT)
        action_filequit.connect("activate", self.on_menu_file_quit)
        action_group.add_action(self.action_filesave)
        action_group.add_action(action_filequit)
        self.action_filesave.set_sensitive(False)
        self.action_filesave.connect('activate', self.save_data)

        
        uimanager = self.create_ui_manager()
        uimanager.insert_action_group(action_group)

        menubar = uimanager.get_widget("/MenuBar")

        self.status_bar = Gtk.Statusbar()
        self.status_bar.push(0, "HP 8903 Audio Analyzer Control")
        
        self.master_vbox = Gtk.Box(False, spacing = 2, orientation = 'vertical')
        self.master_vbox.pack_start(menubar, False, False, 0)
        master_hsep = Gtk.HSeparator()
        self.master_vbox.pack_start(master_hsep, False, False, 0)
        self.add(self.master_vbox)

        self.hbox = Gtk.Box(spacing = 2)
        self.master_vbox.pack_start(self.hbox, True, True, 0)

        self.master_vbox.pack_start(self.status_bar, False, False, 0)

        # Begin controls
        bframe = Gtk.Frame(label = "Control")
        left_vbox = Gtk.Box(spacing = 2, orientation = 'vertical')
        self.box = Gtk.Box(spacing = 2)

        bframe.add(left_vbox)

        # GPIB device selector
        gpib_frame = Gtk.Frame(label = "GPIB Communication Device")
        self.gpib_big_box = Gtk.Box(spacing = 2)
        gpib_frame.add(self.gpib_big_box)
        self.gpib_box = Gtk.Box(spacing = 2)
        self.gpib_vbox = Gtk.Box(spacing = 2, orientation = 'vertical')
        gpib_label = Gtk.Label("GPIB Device: ")
        self.gpib_box.pack_start(gpib_label, False, False, 0)

        gpib_store = Gtk.ListStore(int, str)
        for n, g_dev in enumerate(HP8903_GPIB_devices):
            gpib_store.append([n, g_dev[1]])
        self.gpib_combo = Gtk.ComboBox.new_with_model_and_entry(gpib_store)
        self.gpib_combo.set_entry_text_column(1)
        self.gpib_combo.set_active(0)

        self.gpib_box.pack_start(self.gpib_combo, False, False, 0)

        gpib_addr_box = Gtk.Box(spacing = 2)

        self.gpib_addr = Gtk.SpinButton()
        self.gpib_addr.set_range(0, 30)
        self.gpib_addr.set_digits(0)
        self.gpib_addr.set_value(0)
        self.gpib_addr.set_increments(1.0, 1.0)


        gpib_addr_label = Gtk.Label("GPIB Address: ")
        gpib_addr_box.pack_start(gpib_addr_label, False, False, 0)
        gpib_addr_box.pack_start(self.gpib_addr, False, False, 0)

        self.gpib_vbox.pack_start(self.gpib_box, False, False, 0)
        self.gpib_vbox.pack_start(gpib_addr_box, False, False, 0)

        self.gpib_big_box.pack_start(self.gpib_vbox, False, False, 0)

        left_vbox.pack_start(gpib_frame, False, False, 0)

        # Device items
        left_vbox.pack_start(self.box, False, False, 0)

        self.hbox.pack_start(bframe, False, False, 0)

        con_hbox = Gtk.Box(spacing = 2)
        self.con_button = Gtk.Button(label = "Connect")
        self.dcon_button = Gtk.Button(label = "Disconnect")

        self.con_button.connect("clicked", self.setup_gpib)
        self.dcon_button.connect("clicked", self.close_gpib)
        
        con_hbox.pack_start(self.con_button, False, False, 0)
        con_hbox.pack_start(self.dcon_button, False, False, 0)

        left_vbox.pack_start(con_hbox, False, False, 0)
        
        device_store = Gtk.ListStore(int, str)

        for i, dev in enumerate(self.devices):
            device_store.append([i, dev[0]])
        self.device_combo = Gtk.ComboBox.new_with_model_and_entry(device_store)
        self.device_combo.set_entry_text_column(1)
        self.device_combo.set_active(0)

        device_label = Gtk.Label("Device: ")
        
        self.box.pack_start(device_label, False, False, 0)
        self.box.pack_start(self.device_combo, False, False, 0)

        hsep0 = Gtk.HSeparator()
        left_vbox.pack_start(hsep0, False, False, 2)

        # Measurement Selection
        mframe = Gtk.Frame(label = "Measurement Selection")
        meas_box = Gtk.Box(spacing = 2)
        meas_vbox = Gtk.Box(spacing = 2)

        mframe.add(meas_box)
        meas_box.pack_start(meas_vbox, False, False, 0)

        meas_store = Gtk.ListStore(int, str)
        meas_dict = {0: "THD+n",
                     1:"Frequency Response",
                     2: "THD+n (Ratio)",
                     3: "Frequency Response (Ratio)",
                     4: "Ouput Level"}
        for k, v in meas_dict.iteritems():
            meas_store.append([k, v])
        self.meas_combo = Gtk.ComboBox.new_with_model_and_entry(meas_store)
        self.meas_combo.set_entry_text_column(1)
        self.meas_combo.set_active(0)

        self.meas_combo.connect("changed", self.meas_changed)
        
        meas_vbox.pack_start(self.meas_combo, False, False, 0)
        left_vbox.pack_start(mframe, False, False, 0)


        units_frame = Gtk.Frame(label = "Units")
        units_box = Gtk.Box(spacing = 2)
        units_vbox = Gtk.Box(spacing = 2)

        units_frame.add(units_box)
        units_box.pack_start(units_vbox, False, False, 0)

        self.thd_units_store = Gtk.ListStore(int, str)
        self.ampl_units_store = Gtk.ListStore(int, str)
        self.thdr_units_store = Gtk.ListStore(int, str)
        self.amplr_units_store = Gtk.ListStore(int, str)
        self.optlvl_units_store = Gtk.ListStore(int, str)
        thd_units_dict = {0: "%", 1: "dB"}
        ampl_units_dict = {0: "V", 1: "dBm"}
        thdr_units_dict = {0: "%", 1: "dB"}
        amplr_units_dict = {0: "%", 1:"dB"}
        optlvl_units_dict = {0: "V"}

        for k, v in thd_units_dict.iteritems():
            self.thd_units_store.append([k, v])
        for k, v in ampl_units_dict.iteritems():
            self.ampl_units_store.append([k, v])
        for k, v in thdr_units_dict.iteritems():
            self.thdr_units_store.append([k, v])
        for k, v in amplr_units_dict.iteritems():
            self.amplr_units_store.append([k, v])
        for k, v in optlvl_units_dict.iteritems():
            self.optlvl_units_store.append([k, v])

            
        self.units_combo = Gtk.ComboBox.new_with_model_and_entry(self.thd_units_store)
        self.units_combo.set_entry_text_column(1)
        self.units_combo.set_active(0)

        self.units_combo.connect("changed", self.units_changed)
        
        units_vbox.pack_start(self.units_combo, False, False, 0)
        left_vbox.pack_start(units_frame, False, False, 0)
        
        # units_combo.set_model(ampl_units_store)
        # units_combo.set_active(0)
        #left_vbox.pack_start(units_combo, False, False, 0)
        
        
        
        hsep1 = Gtk.HSeparator()
        left_vbox.pack_start(hsep1, False, False, 2)

        # Frequency Sweep Control
        #side_filler = Gtk.Box(spacing = 2, orientation = 'vertical')
        swconf = Gtk.Frame(label = "Frequency Sweep Control")
        swhbox = Gtk.Box(spacing = 2)
        swbox = Gtk.Box(spacing = 2, orientation = 'vertical')
        swconf.add(swhbox)
        swhbox.pack_start(swbox, False, False, 0)
        
        left_vbox.pack_start(swconf, False, False, 0)
        
        startf = Gtk.Frame(label = "Start Frequency (Hz)")
        
        self.start_freq = Gtk.SpinButton()
        self.start_freq.set_range(20.0, 100000.0)
        self.start_freq.set_digits(5)
        self.start_freq.set_value(20.0)
        self.start_freq.set_increments(100.0, 1000.0)

        startf.add(self.start_freq)
        #left_vbox.pack_start(startf, False, False, 0)
        swbox.pack_start(startf, False, False, 0)
        self.start_freq.connect("value_changed", self.freq_callback)
        
        stopf = Gtk.Frame(label = "Stop Frequency (Hz)")
        
        self.stop_freq = Gtk.SpinButton()
        self.stop_freq.set_range(20.0, 100000.0)
        self.stop_freq.set_digits(5)
        self.stop_freq.set_value(30000.0)
        self.stop_freq.set_increments(100.0, 1000.0)

        stopf.add(self.stop_freq)
        #left_vbox.pack_start(stopf, False, False, 0)
        swbox.pack_start(stopf, False, False, 0)
        self.stop_freq.connect("value_changed", self.freq_callback)

        stepsf = Gtk.Frame(label = "Steps per Decade")
        
        self.steps = Gtk.SpinButton()
        self.steps.set_range(1.0, 1000.0)
        self.steps.set_digits(1)
        self.steps.set_value(10.0)
        self.steps.set_increments(1.0, 10.0)

        stepsf.add(self.steps)
        swbox.pack_start(stepsf, False, False, 0)
        #left_vbox.pack_start(stepsf, False, False, 0)

        hsep2 = Gtk.HSeparator()
        left_vbox.pack_start(hsep2, False, False, 2)

        # Freq Control

        freqf = Gtk.Frame(label = "Frequency")
        freqbox = Gtk.Box(spacing = 2)
        freqhbox = Gtk.Box(spacing = 2, orientation = 'vertical')

        freqf.add(freqhbox)
        freqhbox.pack_start(freqbox, False, False, 0)

        self.freq = Gtk.SpinButton()
        self.freq.set_range(20.0, 100000.0)
        self.freq.set_digits(5)
        self.freq.set_value(1000.0)
        self.freq.set_increments(100.0, 1000.0)

        self.freq.set_sensitive(False)
        
        freqbox.pack_start(self.freq, False, False, 0)
        left_vbox.pack_start(freqf, False, False, 0)

        freqhsep = Gtk.HSeparator()
        left_vbox.pack_start(freqhsep, False, False, 2)
        
        # Source Control
        sourcef = Gtk.Frame(label = "Source Control (V RMS)")
        source_box = Gtk.Box(spacing = 2)
        sourcef.add(source_box)
        
        self.source = Gtk.SpinButton()
        self.source.set_range(0.0006, 6.0)
        self.source.set_digits(4)
        self.source.set_value(0.5)
        self.source.set_increments(0.5, 1.0)
        source_box.pack_start(self.source, False, False, 0)
        left_vbox.pack_start(sourcef, False, False, 0)

        hsep3 = Gtk.HSeparator()
        left_vbox.pack_start(hsep3, False, False, 2)


        vswconf = Gtk.Frame(label = "Voltage Sweep Control")
        vswhbox = Gtk.Box(spacing = 2)
        vswbox = Gtk.Box(spacing = 2, orientation = 'vertical')
        vswconf.add(vswhbox)
        vswhbox.pack_start(vswbox, False, False, 0)
        
        left_vbox.pack_start(vswconf, False, False, 0)
        
        startv = Gtk.Frame(label = "Start Voltage (V)")
        
        self.start_v = Gtk.SpinButton()
        self.start_v.set_range(0.0006, 6.0)
        self.start_v.set_digits(5)
        self.start_v.set_value(0.1)
        self.start_v.set_increments(0.1, 1)

        startv.add(self.start_v)
        #left_vbox.pack_start(startf, False, False, 0)
        vswbox.pack_start(startv, False, False, 0)
        self.start_v.connect("value_changed", self.volt_callback)
        
        stopv = Gtk.Frame(label = "Stop Voltage (V)")
        
        self.stop_v = Gtk.SpinButton()
        self.stop_v.set_range(0.0006, 6.0)
        self.stop_v.set_digits(5)
        self.stop_v.set_value(1.0)
        self.stop_v.set_increments(0.1, 1.0)

        stopv.add(self.stop_v)
        #left_vbox.pack_start(stopf, False, False, 0)
        vswbox.pack_start(stopv, False, False, 0)
        self.stop_v.connect("value_changed", self.volt_callback)

        stepsv = Gtk.Frame(label = "Total Samples")
        
        self.stepsv = Gtk.SpinButton()
        self.stepsv.set_range(1.0, 1000.0)
        self.stepsv.set_digits(1)
        self.stepsv.set_value(10.0)
        self.stepsv.set_increments(1.0, 10.0)

        stepsv.add(self.stepsv)
        vswbox.pack_start(stepsv, False, False, 0)
        #left_vbox.pack_start(stepsf, False, False, 0)

        hsepsv = Gtk.HSeparator()
        left_vbox.pack_start(hsepsv, False, False, 2)



        
        filterf = Gtk.Frame(label = "Filters")
        filterb = Gtk.Box(spacing = 2)
        filtervb = Gtk.Box(spacing = 2, orientation = 'vertical')
        filterf.add(filterb)
        filterb.pack_start(filtervb, False, False, 0)

        self.f30k = Gtk.CheckButton("30 kHz LP")
        self.f80k = Gtk.CheckButton("80 kHz LP")

        self.lpi = Gtk.CheckButton("Left Plug-in filter")
        self.rpi = Gtk.CheckButton("Right Plug-in filter")

        self.f30k.connect("toggled", self.filter1_callback)
        self.f80k.connect("toggled", self.filter1_callback)

        self.lpi.connect("toggled", self.filter2_callback)
        self.rpi.connect("toggled", self.filter2_callback)
        
        filtervb.pack_start(self.f30k, False, False, 0)
        filtervb.pack_start(self.f80k, False, False, 0)
        filtervb.pack_start(self.lpi, False, False, 0)
        filtervb.pack_start(self.rpi, False, False, 0)

        left_vbox.pack_start(filterf, False, False, 0)
        
        hsep = Gtk.HSeparator()
        left_vbox.pack_start(hsep, False, False, 2)
        
        self.run_button = Gtk.Button(label = "Start Sequence")
        self.run_button.set_sensitive(False)
        left_vbox.pack_start(self.run_button, False, False, 0)
        self.run_button.connect("clicked", self.run_test)
        
        
        self.f = Figure(figsize=(5,4), dpi=100)
        self.a = self.f.add_subplot(111)
        #self.plt = self.a.plot(20,-90, marker = 'x')
        self.plt = self.a.plot(marker = 'x')
        self.a.grid(True)
        self.a.set_xscale('log')
        self.a.set_xlim((10.0, 30000.0))
        self.a.set_ylim((0.0005, 0.01))
        self.a.set_xlabel("Frequency (Hz)")
        self.a.set_ylabel("THD+n (%)")
        
        self.canvas = FigureCanvas(self.f)

        toolbar = NavigationToolbar(self.canvas, self)

        plot_vbox = Gtk.Box(spacing = 2, orientation = 'vertical')
        plot_vbox.pack_start(self.canvas, True, True, 0)
        plot_vbox.pack_start(toolbar, False, False, 0)
        
        #self.hbox.pack_start(self.canvas, True, True, 0)
        self.hbox.pack_start(plot_vbox, True, True, 0)

        # Groups of widgets
        self.measurement_widgets = [self.meas_combo, self.units_combo]
        self.freq_sweep_widgets = [self.start_freq, self.stop_freq, self.steps]
        self.source_widgets = [self.source]
        self.filter_widgets = [self.f30k, self.f80k, self.lpi, self.rpi]
        self.vsweep_widgets = [self.start_v, self.stop_v, self.stepsv]
        
        for w in self.measurement_widgets:
            w.set_sensitive(False)
        for w in self.freq_sweep_widgets:
            w.set_sensitive(False)
        for w in self.source_widgets:
            w.set_sensitive(False)
        for w in self.filter_widgets:
            w.set_sensitive(False)
        for w in self.vsweep_widgets:
            w.set_sensitive(False)

        
        self.meas_string = "THD+n (%)"
        self.units_string = "%"
        self.measurements = None

    def setup_gpib(self, button):
        # Get GPIB info
        gpib_model = self.gpib_combo.get_model()
        gpib_tree_iter = self.gpib_combo.get_active_iter()

        # Get address
        gpib_addr = self.gpib_addr.get_value_as_int()

        # Instantiate GPIB Device class
        self.gpib_dev = HP8903_GPIB_devices[gpib_model[gpib_tree_iter][0]][0](gpib_addr = gpib_addr)
        print("Using GPIB Device: %s" % self.gpib_dev.name())
        print("Using GPIB Address: %s" % str(gpib_addr))

        if (not self.gpib_dev.implements_addr()):
            print("Warning: this GPIB communication device does not implement")
            print("    address setting, check your hardware's settings!")

        # Get device info
        model = self.device_combo.get_model()

        tree_iter = self.device_combo.get_active_iter()

        print("Device: %s" % model[tree_iter][1])
        dev_name = model[tree_iter][1]

        # Disable gpib and devices buttons
        self.con_button.set_sensitive(False)
        self.device_combo.set_sensitive(False)
        self.gpib_combo.set_sensitive(False)
        self.gpib_addr.set_sensitive(False)


        if(not self.gpib_dev.open(dev_name)):
            # Make into warning window?
            print("Failed to open GPIB Device: %s at %s" % (self.gpib_dev.name(), dev_name))
            print("Verify hardware setup and try to connect again")

            self.con_button.set_sensitive(True)
            self.device_combo.set_sensitive(True)
            self.gpib_combo.set_sensitive(True)
            self.gpib_addr.set_sensitive(True)

            return(False)

        # Do test?
        if (not self.gpib_dev.test()):
            print("GPIB device failed self test: %s at %s" % (self.gpib_dev.name(), dev_name))
            print("Verify hardware setup and try to connect again")

            self.con_button.set_sensitive(True)
            self.device_combo.set_sensitive(True)
            self.gpib_combo.set_sensitive(True)
            self.gpib_addr.set_sensitive(True)

            return(False)


        if (self.gpib_dev.is_open()):
            self.gpib_dev.flush_input()
            # Initialize the HP 8903
            status = self.init_hp8903()
            if (not status):
                print("Failed to initialize HP 8903")
                print("Verify hardware setup and try to connect again")

                self.gpib_dev.close()

                self.con_button.set_sensitive(True)
                self.device_combo.set_sensitive(True)
                self.gpib_combo.set_sensitive(True)
                self.gpib_addr.set_sensitive(True)

                return(False)

        else:
            print("Failed to use GPIB device")
            print("Verify hardware setup and try to connect again")

            self.gpib_dev.close()

            self.con_button.set_sensitive(True)
            self.device_combo.set_sensitive(True)
            self.gpib_combo.set_sensitive(True)
            self.gpib_addr.set_sensitive(True)

            return(False)

        # Enable measurement controls
        self.run_button.set_sensitive(True)
        for w in self.measurement_widgets:
            w.set_sensitive(True)
        for w in self.freq_sweep_widgets:
            w.set_sensitive(True)
        for w in self.source_widgets:
            w.set_sensitive(True)
        for w in self.filter_widgets:
            w.set_sensitive(True)
        for w in self.vsweep_widgets:
            w.set_sensitive(False)


        self.status_bar.push(0, "Connected to  HP 8903, ready for measurements")

    def close_gpib(self, button):
        if (self.gpib_dev):
            self.gpib_dev.close()

        # Activate device/connection buttons
        self.con_button.set_sensitive(True)
        self.device_combo.set_sensitive(True)
        self.gpib_combo.set_sensitive(True)
        self.gpib_addr.set_sensitive(True)

        # Disable measurement controls
        for w in self.measurement_widgets:
            w.set_sensitive(False)
        for w in self.freq_sweep_widgets:
            w.set_sensitive(False)
        for w in self.source_widgets:
            w.set_sensitive(False)
        for w in self.filter_widgets:
            w.set_sensitive(False)
        for w in self.vsweep_widgets:
            w.set_sensitive(False)

        self.freq.set_sensitive(False)

        self.run_button.set_sensitive(False)

    def run_test(self, button):
        # Disable all control widgets during sweep
        self.run_button.set_sensitive(False)
        self.action_filesave.set_sensitive(False)

        for w in self.measurement_widgets:
            w.set_sensitive(False)
        for w in self.freq_sweep_widgets:
            w.set_sensitive(False)
        for w in self.source_widgets:
            w.set_sensitive(False)
        for w in self.filter_widgets:
            w.set_sensitive(False)
        for w in self.vsweep_widgets:
            w.set_sensitive(False)

        self.freq.set_sensitive(False)

        
        self.x = []
        self.y = []
        
        # 30, 80, LPI, RPI
        filters = [False, False, False, False]
        filters[0] = self.f30k.get_active()
        filters[1] = self.f80k.get_active()
        filters[2] = self.lpi.get_active()
        filters[3] = self.rpi.get_active()
        #print(filters)

        amp = self.source.get_value()
        
        strtf = self.start_freq.get_value()
        stopf = self.stop_freq.get_value()
        
        num_steps = self.steps.get_value_as_int()
        step_size = 10**(1.0/num_steps)

        strt_dec = math.floor(math.log10(strtf))
        stop_dec = math.floor(math.log10(stopf))

        meas = self.meas_combo.get_active()
        units = self.units_combo.get_active()

        lsteps = []
        vsteps = []
        if ((meas < 4) and (meas >= 0)):
            decs = math.log10(stopf/strtf)
            npoints = int(decs*num_steps)

            for n in range(npoints + 1):
                lsteps.append(strtf*10.0**(float(n)/float(num_steps)))
                
            self.a.set_xlim((lsteps[0]*10**(-2.0/10.0), lsteps[-1]*10**(2.0/10.0)))
            self.a.set_xscale('log')
        elif (meas == 4):
            start_amp = self.start_v.get_value()
            stop_amp = self.stop_v.get_value()
            num_vsteps = self.stepsv.get_value()
            vsteps = np.linspace(start_amp, stop_amp, num_vsteps)
            amp_buf = ((stop_amp - start_amp)*0.1)/2.0
            print(amp_buf)
            self.a.set_xlim(((start_amp - amp_buf), (stop_amp + amp_buf)))
            self.a.set_xscale('linear')
            # print(start_amp)
            # print(stop_amp)
            # print(num_vsteps)


        center_freq = self.freq.get_value()
            
        # center freq...
        self.measurements = [amp, filters, meas, units, self.meas_string, self.units_string]
        
        if ((meas == 0) or (meas == 1)):
            #pass
            pt = self.send_measurement(meas, units, center_freq, amp, filters, ratio = 2)
        elif ((meas == 2) or (meas == 3)):
            pt = self.send_measurement(meas, units, center_freq, amp, filters)
            #print(pt)
            pt = self.send_measurement(meas, units, center_freq, amp, filters, ratio = 1)
            #print("PT: %s" % pt)
        elif (meas == 4):
            pt = self.send_measurement(meas, units, center_freq, start_amp, filters, ratio = 2)

        if ((meas < 4) and (meas >= 0)):
            for i in lsteps:
                meas_point = self.send_measurement(meas, units, i, amp, filters)
                self.x.append(float(i))
                self.y.append(float(meas_point))
                print(float(meas_point))
                self.update_plot(self.x, self.y)
                # plot new measures
                #print(meas_point)
        elif (meas == 4):
            #pass
            for v in vsteps:
                meas_point = self.send_measurement(meas, units, center_freq, v, filters)
                self.x.append(v)
                self.y.append(float(meas_point))
                print("in: %f, out %f" % (v, float(meas_point)))
                self.update_plot(self.x, self.y)
        

        for w in self.measurement_widgets:
            w.set_sensitive(True)
        for w in self.filter_widgets:
            w.set_sensitive(True)

        if ((meas < 4) and (meas >= 0)):
            for w in self.freq_sweep_widgets:
                w.set_sensitive(True)
            for w in self.source_widgets:
                w.set_sensitive(True)
        if (meas == 4):
            for w in self.vsweep_widgets:
                w.set_sensitive(True)

        if (meas > 1):
            self.freq.set_sensitive(True)

        self.run_button.set_sensitive(True)
        self.action_filesave.set_sensitive(True)

    def update_plot(self, x, y):
        if (len(self.plt) < 1):
            self.plt = self.a.plot(x, y, marker = 'x')
        self.plt[0].set_data(x, y)
        ymin = min(y)
        ymax = max(y)

        
        # if (ymin == 0.0):
        #     ymin = -0.01
        # if (ymax == 0.0):
        #     ymax = 0.01

        sep = abs(ymax - ymin)
        sep = sep/10.0

        if (sep == 0.0):
            sep = 0.01

        #self.a.set_ylim((ymin - abs(ymin*0.10), ymax + abs(ymax*0.10)))
        self.a.set_ylim((ymin - abs(sep), ymax + abs(sep)))
        self.canvas.draw()
            
    def init_hp8903(self):
        self.gpib_dev.flush_input()
        # Arbitrary but simple measurement to check device
        self.gpib_dev.write("FR1000.0HZAP0.100E+00VLM1LNL0LNT3")
        status, meas = self.gpib_dev.read(msg_len = 12, timeout = 5000)

        if (status):
            print(meas)
        else:
            print("Failed to initialize HP8903!")
            print(status, meas)
            return(False)

        return(True)
        
    def send_measurement(self, meas, unit, freq, amp, filters, ratio = 0):
        # Store parameters for saving after any measure
        #self.measurements = [amp, filters, meas, unit]
        measurement = ""
        meas_unit = ""
        
        if (filters[0]):
            fs1 = "L1"
        elif (filters[1]):
            fs1 = "L2"
        else:
            fs1 = "L0"

        if (filters[2]):
            fs2 = "H1"
        elif (filters[3]):
            fs2 = "H2"
        else:
            fs2 = "H0"

        if ((meas == 0) or (meas == 2)):
            measurement = "M3"
        elif ((meas == 1) or (meas == 3) or (meas == 4)):
            measurement = "M1"

        if (unit == 0):
            meas_unit = "LN"
        elif (unit == 1):
            meas_unit = "LG"
            
        source_freq = ("FR%.4EHZ" % freq)
        source_ampl = ("AP%.4EVL" % amp)
        filter_s = fs1 + fs2

        rat = ""
        if (ratio == 1):
            rat = "R1"
        elif (ratio == 2):
            rat = "R0"
        
        #payload = source_freq + source_ampl + "M3LN" + filter_s + "LNT3"
        payload = source_freq + source_ampl + measurement + filter_s + meas_unit + rat + "T3"
        #print(payload)
        #print("FR%.4EHZAP1VLM1LNL0LNT3" % freq)
        #print("FR%.4EHZAP%.4EVLM3LNL0LNT3" % (freq, amp))
        #self.ser.write(("FR%.4EHZAP%.4EVLM3LNL2LNT3" % (freq, amp)))

        # Send and read measurement via GPIB controller
        self.gpib_dev.write(payload)
        status, samp = self.gpib_dev.read(timeout = 2500)
        if (status):
            sampf = float(samp)
        else:
            sampf = np.NAN
            print("Failed to get sample")

        if (sampf > 4.0e9):
            print(("Error: %s" % samp[4:6]) + " " + HP8903_errors[int(samp[4:6])])
            samp = np.NAN

        self.status_bar.push(0, "Freq: %f, Amp: %f, Return: %f,    GPIB: %s" % (freq, amp, sampf, payload))
            
        return(samp)

    def save_data(self, button):
        fname = datetime.now().strftime("%Y-%m-%d-%H%M%S")
        fid = open(fname + '.txt', 'w')

        # Write source voltage info
        source_v = str(self.measurements[0])
        fid.write("# Measurement: " + self.measurements[4] + "\n")
        fid.write("# Source Voltage: " + source_v + " V RMS\n")
        # write filter info
        for n, f in enumerate(self.measurements[1]):
            if f:
                fid.write("# " + HP8903_filters[n] + " active\n")

        fid.write("# Frequency (Hz)    " + self.measurements[5] + "\n")
        n = np.array([np.array(self.x), np.array(self.y)])
        np.savetxt(fid, n.transpose(), fmt = ["%f", "%f"])
        fid.close()
        
        
    def freq_callback(self, spinb):
        if (self.start_freq.get_value() > self.stop_freq.get_value()):
            self.start_freq.set_value(self.stop_freq.get_value())

    def volt_callback(self, spinb):
        if (self.start_v.get_value() > self.stop_v.get_value()):
            self.start_v.set_value(self.stop_v.get_value())

    # 30k/80k toggle
    def filter1_callback(self, cb):
        if (cb.get_active()):
            if (cb.get_label() == "30 kHz LP"):
                self.f80k.set_active(False)
            elif (cb.get_label() == "80 kHz LP"):
                self.f30k.set_active(False)

    # left plugin/right plugin toggle
    def filter2_callback(self, cb):
        if (cb.get_active()):
            if (cb.get_label() == "Left Plug-in filter"):
                self.rpi.set_active(False)
            elif (cb.get_label() == "Right Plug-in filter"):
                self.lpi.set_active(False)

    def on_menu_file_quit(self, widget):
        if (self.gpib_dev):
            self.gpib_dev.close()
        Gtk.main_quit()

    def meas_changed(self, widget):
        meas_ind = self.meas_combo.get_active()
        if (meas_ind == 0):
            self.units_combo.set_model(self.thd_units_store)
            self.units_combo.set_active(0)
            self.a.set_ylabel("THD+n (%)")
            self.a.set_xlabel("Frequency (Hz)")            
            self.canvas.draw()
            self.freq.set_sensitive(False)
            self.source.set_sensitive(True)
            for w in self.freq_sweep_widgets:
                w.set_sensitive(True)
            for w in self.vsweep_widgets:
                w.set_sensitive(False)
        elif (meas_ind == 1):
            self.units_combo.set_model(self.ampl_units_store)
            self.units_combo.set_active(0)
            self.a.set_ylabel("AC Level (V RMS)")
            self.a.set_xlabel("Frequency (Hz)")            
            self.canvas.draw()
            self.freq.set_sensitive(False)
            self.source.set_sensitive(True)
            for w in self.freq_sweep_widgets:
                w.set_sensitive(True)
            for w in self.vsweep_widgets:
                w.set_sensitive(False)
        elif (meas_ind == 2):
            self.units_combo.set_model(self.thdr_units_store)
            self.units_combo.set_active(0)
            self.a.set_ylabel("THD+n Ratio (%)")
            self.a.set_xlabel("Frequency (Hz)")
            self.canvas.draw()
            self.freq.set_sensitive(True)
            self.source.set_sensitive(True)
            for w in self.freq_sweep_widgets:
                w.set_sensitive(True)
            for w in self.vsweep_widgets:
                w.set_sensitive(False)
        elif (meas_ind == 3):
            self.units_combo.set_model(self.amplr_units_store)
            self.units_combo.set_active(0)
            self.a.set_ylabel("AC Level Ratio (%)")
            self.a.set_xlabel("Frequency (Hz)")
            self.canvas.draw()
            self.freq.set_sensitive(True)
            self.source.set_sensitive(True)
            for w in self.freq_sweep_widgets:
                w.set_sensitive(True)
            for w in self.vsweep_widgets:
                w.set_sensitive(False)
        elif (meas_ind == 4):
            self.units_combo.set_model(self.optlvl_units_store)
            self.units_combo.set_active(0)
            self.a.set_ylabel("Output Level (V)")
            self.a.set_xlabel("Input Level (V)")
            self.canvas.draw()
            self.freq.set_sensitive(True)
            self.source.set_sensitive(False)
            for w in self.freq_sweep_widgets:
                w.set_sensitive(False)
            for w in self.vsweep_widgets:
                w.set_sensitive(True)


            


    def units_changed(self, widget):
        meas_ind = self.meas_combo.get_active()
        units_ind = self.units_combo.get_active()
        #print("meas ind: %d units ind: %d" % (meas_ind, units_ind))
        # Set units on plot
        meas = ""
        if (meas_ind == 0):
            meas = "THD+n "
            if (units_ind == 0):
                meas += "(%)"
                self.units_string = "%"
            elif (units_ind == 1):
                meas += "(dB)"
                self.units_string = "dB"
        elif (meas_ind == 1):
            meas = "AC Level "
            if (units_ind == 0):
                meas += "(V RMS)"
                self.units_string = "V RMS"
            elif (units_ind == 1):
                meas += "(dB V)"
                self.units_string = "dB V"
        elif (meas_ind == 2):
            meas = "THD+n (Ratio) "
            if (units_ind == 0):
                meas += "(%)"
                self.units_string = "%"
            elif (units_ind == 1):
                meas += "(dB)"
                self.units_string = "dB"
        elif (meas_ind == 3):
            meas = "AC Level (Ratio) "
            if (units_ind == 0):
                meas += "(%)"
                self.units_string = "%"
            elif (units_ind == 1):
                meas += "(dB)"
                self.units_string = "dB"

        # Save text info about units
        self.meas_string = meas
        # Updated plot
        self.a.set_ylabel(meas)
        self.canvas.draw()

    # menu bar junk
    def create_ui_manager(self):
        uimanager = Gtk.UIManager()

        # Throws exception if something went wrong
        uimanager.add_ui_from_string(UI_INFO)

        # Add the accelerator group to the toplevel window
        accelgroup = uimanager.get_accel_group()
        self.add_accel_group(accelgroup)
        return uimanager
コード例 #7
0
class MyWindow(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self,title="Echelle Reduction GUI")
      
        
   ## setting up canvase for plotting ### 
   
        #self.box = Gtk.EventBox()
        
        
        self.set_default_size(1000,700)
    	self.f = Figure(figsize=(5,7), dpi=100)
        self.b = self.f.add_subplot(212) # 1D
        self.c = self.f.add_subplot(231) # PHD
        self.e = self.f.add_subplot(233) # orders 
        self.a = self.f.add_subplot(232) # raw
        self.e.tick_params(axis='both',labelsize=6)
        self.e.set_title("orders")
        self.a.tick_params(axis='both', labelsize=7)
        self.a.set_title("2D raw data")
        self.b.set_title("1D extracted data")
        self.b.set_xlabel('pixels')
        self.b.set_ylabel('intensity')
        self.b.tick_params(axis='both', labelsize=7)
        self.c.set_title('PHD')
        self.c.tick_params(axis='both', labelsize=7)
        
        self.canvas = FigureCanvas(self.f) 
        
   
    # menue bar 
        menubar = Gtk.MenuBar()
        
        filem = Gtk.MenuItem("File")
        filemenu = Gtk.Menu()
        filem.set_submenu(filemenu)
        
        open = Gtk.MenuItem("Open")
        open.connect('activate',self.on_file_clicked)
        filemenu.append(open)
        menubar.append(filem)
        #savesub = Gtk.Menu()
        #savesub.append()
        exit = Gtk.MenuItem('Exit')
        exit.connect('activate',Gtk.main_quit)
        filemenu.append(exit)
       
        
        menubox = Gtk.Box( orientation = Gtk.Orientation.VERTICAL)
        menubox.pack_start(menubar,False,False,0)
        #open.connect("open", self.on_file_clicked)
     
    
    # Navigtion toolbar stuff     
        
        toolbar = NavigationToolbar(self.canvas, self)
        main_box = Gtk.Box( orientation = Gtk.Orientation.VERTICAL)  
        self.add(main_box)
     
    # status bar
        self.statusbar = Gtk.Statusbar()
        context_id=self.statusbar.get_context_id("stat bar example")  
        self.statusbar.push(0,'Please Open 2D Fits Data File')  
        
    # button box
        vbutton_box = Gtk.Box(orientation = Gtk.Orientation.HORIZONTAL)
        self.button1 = Gtk.ToggleButton(label='Raw count rate')
        self.button1.connect("toggled", self.on_button1_clicked, context_id)
        self.button2 = Gtk.Button('Filter PHD')
        self.button2.connect("clicked",self.on_button2_clicked,context_id)
        self.button3 = Gtk.ToggleButton(label='Fit 1D Gauss')
        self.button3.set_active(False)
        self.button3.connect("toggled", self.on_button3_clicked,  context_id)
        self.orderbutton = Gtk.ToggleButton(label='Remove Orders')
        self.orderbutton.connect("toggled",self.orderbutton_clicked,context_id)
        self.buttonbg = Gtk.Button('Airglow')
        self.buttonbg.connect('clicked', self.buttonbg_clicked, context_id)
        
        
        vbutton_box.pack_start(self.button1,True,True, 0)
        vbutton_box.pack_start(self.button2,True, True, 0)
        vbutton_box.pack_start(self.button3,True, True, 0)
        vbutton_box.pack_start(self.orderbutton,True,True,0)
        vbutton_box.pack_start(self.buttonbg,True,True,0)
        
     
        
    # packing in main_box
        main_box.pack_start(self.statusbar, False,False,0)
        main_box.pack_start(self.canvas, True, True, 0)
        main_box.pack_start(vbutton_box,False,False,0)
        main_box.pack_start(toolbar, False, False, 0)
        main_box.pack_start(menubox,False,False,0)


# ### file selector window ###
    def on_file_clicked(self, widget):
        dialog = Gtk.FileChooserDialog("Please Choose a File", self,
            Gtk.FileChooserAction.OPEN,
            (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
             Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
        dialog.set_default_response(Gtk.ResponseType.OK)
        filter = Gtk.FileFilter()
        filter.set_name('fits Files')
        filter.add_mime_type('fits')
        filter.add_pattern('*.fits')
        dialog.add_filter(filter)
   
        response = dialog.run()
        
        if response == Gtk.ResponseType.OK :
        	fname = dialog.get_filename()
        	global _File
        	_File = fname
        	#print "open file" + fname
        	self.statusbar.push(0,'Opened File:' + fname)
        	dialog.destroy()
        	self.open_file(_File)
        elif response == Gtk.ResponseType.CANCEL:
        	dialog.destroy()
   
   # opening fits file
    def open_file(self,_File):
    	#this opens up the fits file
    	hdulist = fits.open(_File)
        self.targname = hdulist[0].header['targname']    
    
        #this picks out the actual data from fits file, and turns it into numpy array
    	#self.scidata = hdulist['sci',2].data 
    	self.scidata = hdulist['sci',1].data 
    	hdulist.close()
    	
    	scidata = self.scidata
    	
    	targname = self.targname
    	self.science(scidata,targname)
    	
    
    def science(self,scidata,targname):
    	# sends 2d data to my gui plotting funtion
	
    	self.update_plot(scidata)
        #self.scidata = scidata
        
        
    ### smashing 2D data into 1D to view orders as peaks ####
    	
    # filling in y with the sums of the rows of scidata
        y=[]
   	for i in range(0,len(scidata[0])):
        	t = np.sum(scidata[i,:])
        	y.append(t)
        
    # making an x axis with same dementions as y
    	x = np.linspace(0,len(scidata[0]), num = len(scidata[0]))
    	self.x = x

    #reversing x for the sake of the visualization
    	xrev = x[::-1]

    # the orders seem to blend around lyman alpha so i have to select
    # the biggest chunk I could use to get a delta y between the
    # orders. i wil have to make this selectable on the GUI some how
    	chunk = [0,500]
	minv = chunk[0]
	maxv = chunk[1]
 
	
    #drawing box around my chunk to check makesure I have a good portion
	#plt.hself.lines(chunk,[-1000],[5000],color='r')
        #plt.vself.lines([-1000,5000],minv,maxv,color='r')
	#plt.show()
    
    #cutting out the chunk of data that i selected
	xchunk = x[max(x)-chunk[1]:max(x)]
	index1 = int(max(x)-chunk[1])
	index2 = int(max(x))
	ychunk = y[index1:index2]
    #reversing x for the sake of the plot
    	xrevchunk = xchunk[::-1]
    	
    	
    
    	
    	#plt.figure(figsize=(7.5,8.4))
    #
    # using scipy.signal.find_peaks_cwt() to find centers of orders.  this required scipy version .11.0 or greater
    	peakind=signal.find_peaks_cwt(ychunk,np.arange(3,15))
    
    # plotting chunk of 1D data with self.lines through the centers of the orders to double check how the peak finder did

    	self.lines=xchunk[peakind]
    	revlines=self.lines[::-1]
    	lines = self.lines
    	self.xchunk = xchunk
    	self.ychunk = ychunk
    	self.update_ordersplot(ychunk,xchunk,self.lines)
   
      
    	
    ### fake PDH stuff ### (fake data for now)
	PHDfake = '/home/rachel/codes/chesstest.fits'
	hdu = fits.open(PHDfake)
	PHD = hdu[1].data['PHD']
	self.update_PHDplot(PHD)
	hdu.close() 
	
	self.dragbox=[]
   
      ### extraction of orders ###   
     # find w, the widths of the orders (difference between peaks)
    	w=[]
    	for i in range(1,len(peakind)):
    		t=peakind[i]-peakind[i-1]
    		w.append(t)
    	
    # i have to add an extra w at the end of the array to make it the right size i (hopefully this is kosher)
    	maxw=max(w)-4
    	w.append(maxw)
        self.w = w
    
    ### making arrays of 1s ans 0s and extracting the 1d orders by matrix multiplication 
    #def extraction(self, peakind,x,scidata):
   	zeros=np.zeros((len(x),1))
    	index = range(0,len(self.w))
    	reindex = index[::-1]
        global oneDorders
    	oneDorders = {}
    	for i in reindex:
    		zeros1=np.copy(zeros)
    		zeros1[ len(scidata[0]) - (np.sum(w[(i):18])) : len(scidata[0]) - np.sum(w[(i+1):18]) ] = 1
    		twoD = scidata*zeros1
    			   		
            # making 2d orders in to 1d orders
                Y=[]
    		for j in range(0,len(scidata[0])):
        		t = np.sum(twoD[:,j])
        		Y.append(t)
            # placing 1d orders in dictionary called oneDorders
        	oneDorders[str(i)]=Y
        
        	
     # sending plotting info to update_1dplot for gui (for now using just on order until cross coralation is added to script
    	self.x = np.linspace(0,len(scidata[0]), num = len(scidata[0]))
        self.odo=oneDorders['16']
        odo = self.odo[:]
    	self.update_1dplot(odo,x)
    	self.save_pickle(oneDorders)
    		
        
    def update_plot(self, scidata):
        
        #self.a.cla()
        #cbar.self.a.cla()
        
        self.plt= self.a.imshow(scidata, vmin = 0, vmax = 255,origin = 'lower')
        
        cbar=self.f.colorbar(self.plt,shrink=.84,pad=0.01) 
 
        self.canvas.draw()

    def update_ordersplot(self,ychunk,xchunk,lines):
        ## if you dont want to new airglow subtracted data to over plot but to replot, uncomment this next line
        self.e.cla()
        self.e.set_title("orders")
        self.plt=self.e.plot(ychunk,xchunk)
        self.e.hlines(lines,0,2000,color='purple',label='centers')
        self.canvas.draw()

    def update_1dplot(self,odo,x):
        ## if you dont want to new airglow subtracted data to over plot but to replot, uncomment this next line
        self.b.cla()
    	self.plt=self.b.plot(x,self.odo)
    	self.canvas.draw()
    	
    def update_PHDplot(self,PHD):
        ## if you dont want to new airglow subtracted data to over plot but to replot, uncomment this next line
        self.c.cla()
        self.c.set_title('PHD')
        self.plt=self.c.hist(PHD,bins=80,histtype='stepfilled')
        self.canvas.draw()
        
        
 ## airglow button ##
    def buttonbg_clicked(self, widget, data):
    	dialog = Gtk.FileChooserDialog("Please Choose Airglow File", self,
            Gtk.FileChooserAction.OPEN,
            (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
             Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
        dialog.set_default_response(Gtk.ResponseType.OK)
        filter = Gtk.FileFilter()
        filter.set_name('fits Files')
        filter.add_mime_type('fits')
        filter.add_pattern('*.fits')
        dialog.add_filter(filter)
   
        response = dialog.run()
        
        if response == Gtk.ResponseType.OK :
        	fname = dialog.get_filename()
        	global _AirglowFile
        	_AirglowFile = fname
        	#print "open file" + fname
        	#self.statusbar.push(0,'Opened File:' + fname)
        	dialog.destroy()
        	self.open_Airglowfile(_AirglowFile)
        elif response == Gtk.ResponseType.CANCEL:
        	dialog.destroy()
        	
# opening a‏iglow fits file
    def open_Airglowfile(self,_AirglowFile):
    	#this opens up the fits file
    	hdulist = fits.open(_AirglowFile)
      
      ## this line will need to be used for real data
        #self.targname = hdulist[0].header['targname']    
        #targname = self.targname
        
      ## but for now
        targname = 'HD128627J'
        
      #  this picks out the actual data from fits file, and turns it into numpy array
    	self.glowdata = hdulist[0].data 
    	hdulist.close()
      # simple subtraction of aurglow image from science image
    	scidata = self.scidata - self.glowdata
    	self.science(scidata,targname)
        
  ## gauss fitting button 
    
    def on_button3_clicked(self, widget, data):

         	self.statusbar.push(data,'Ready to fit.  Click on both sides of the emission feature you wish to fit')
         	self.xdata = []
                def onclick(event):
                    if self.button3.get_active():
    	        	 self.xdata.append(event.xdata)
    	        	 self.statusbar.push(data,'one more click...')
        		 if len(self.xdata) == 2:
			        self.statusbar.push(data,'Ready to fit.  Click on both sides of the emission feature you wish to fit')
			 	xdata=self.xdata
	    	                self.gauss_fit(xdata)
	    	    
	    	    	
        #  mouse click event on 1d	
    		cid = self.canvas.mpl_connect('button_press_event', onclick)
    		if [self.button3.get_active()] == [False]:
    			self.statusbar.push(0,'Opened File:' + _File)
    	 
    
    		
 ### guass fitting ###
    def gauss_fit(self,xdata):
        
        x = list(self.x)
        xg=[]     
        xg.append(int(xdata[0]))
        xg.append(int(xdata[1])) 
        xg1 = min(xg)
        xg2 = max(xg)       
        xgauss = x[xg1:xg2]
        ygauss = self.odo[xg1:xg2]
        right = ygauss[len(xgauss)-4:len(xgauss)]
        left = ygauss[0:4]
       
       # background subtraction
        averight = sum(right)/len(right)
        aveleft = sum(left)/len(left)
        bg_y = [averight,aveleft]
        rightx = xgauss[len(xgauss)-4:len(xgauss)]
        leftx = xgauss[0:4]
        averightx = sum(rightx)/len(rightx)
        aveleftx = sum(leftx)/len(leftx)
        bg_x = [averightx,aveleftx]
       
        m,b = np.polyfit(bg_x,bg_y,1)
        slopex = [i * m for i in xgauss]
        bg_fit = slopex+b
        
        
        
       # makeing a model gauss
        def gauss(xgauss,MAX,mu,sigma):
        	return MAX*np.exp(-(xgauss-mu)**2/(2.*sigma**2))
        avex = sum(xgauss)/len(xgauss) 
        guess = [1.,avex,1.]
       # plugging in model to matplotlibs curve_fit()
       
        coeff, var_matrix = curve_fit(gauss,xgauss,ygauss-bg_fit,p0=guess) 
        fit = gauss(xgauss, *coeff)
        sigma = coeff[2]
        FWHM = sigma*2*np.sqrt(2*np.log(2))
        FWHM = round(FWHM,2)
 	fitplot = plt.plot(xgauss,ygauss,color='k')
 	plt.plot(xgauss,fit+bg_fit,color = 'b',linewidth = 1.5)
 	xpos = xgauss[0]+.01*(coeff[1]-xgauss[0])
 	strFWHM = str(FWHM)
 	plt.text(xpos,.9*max(ygauss),'FWHM = '+strFWHM+'',color = 'purple',fontweight = 'bold')
 	 
 	center = str(round(coeff[1],2))
 	plt.text(xpos,.95*max(ygauss),'Center = '+center+'',color = 'green',fontweight = 'bold')
 	plt.plot(xgauss,bg_fit,'r--')
 	
 	plt.show()
 	self.xdata = []
 	
 	
    ### count rate button  
    def on_button1_clicked(self, widget,data):
        if self.button1.get_active():
    	   self.statusbar.push(data,'Use zoom feature in navigation bar to select count rate region')
    	else: 
    	   self.statusbar.push(0,'Opened File:' + _File)
    	
    	def onclick2(event):
    	       if self.button1.get_active():
    	          self.dragbox = []
                  #print event.xdata, event.ydata
                  self.dragbox.append(event.xdata)
                  self.dragbox.append(event.ydata)
                  
                  
        def offclick2(event):
                 # print event.xdata, event.ydata
               if self.button1.get_active():
                  self.dragbox.append(event.xdata)
                  self.dragbox.append(event.ydata)
                  dragbox = self.dragbox
                  self.cnt_rate(dragbox,data)
                 
                  
        cid2 = self.canvas.mpl_connect('button_press_event',onclick2 )
        cid3 = self.canvas.mpl_connect('button_release_event',offclick2 )
       

 	
 ### count rate #####
        
    def cnt_rate(self,dragbox,data):
        # fake exposure time in seconds
        datafake = '/home/rachel/codes/chesstest.fits'
	hdu = fits.open(datafake)
	exptime = hdu[0].header['EXPOSURE']
    	dragbox = [int(x) for x in dragbox]
    	cntbox = self.scidata[dragbox[0]:dragbox[2],1024-dragbox[1]:1024-dragbox[3]]
    	totpix = np.size(cntbox)
    	cntrate = np.sum(cntbox)/exptime
    	totpix = str(totpix)
    	cntrate = str(cntrate)
    	self.statusbar.push(data,'count rate in box = '+cntrate+' cnt/sec,    pixels in box = '+totpix+'')
    	return cntrate
  
  #### phd filter button ##
    
    def on_button2_clicked(self,widget,data):
    	self.phd_window = Gtk.MessageDialog(image = None)
    	self.phd_window.set_size_request(500,100)
    	self.phd_window.move(400, 300)
    	#self.phd_window.connect("delet_event",lambda w,e:)    
       
        mainbox = self.phd_window.get_content_area()
        self.phd_window.add(mainbox)
        thebox = Gtk.HBox(False, 0)
        
        label = Gtk.Label("Discard PHD between")
        label2 = Gtk.Label('and')
        
        label.show()
        label2.show()
        
        self.okbutton = Gtk.Button('Okay')
        self.okbutton.connect('clicked',self.phd_entry_button)
        
        self.entry = Gtk.Entry()
        self.entry.set_activates_default(True)
        
        self.entry2 = Gtk.Entry()
        self.entry2.set_activates_default(True)
        self.entry.show()
        self.entry2.show()
        self.okbutton.show()
        
        thebox.pack_start(label,False,False,0)
        thebox.pack_start(self.entry,False,False,0)
        
        thebox.pack_start(label2,False,False,0)
        thebox.pack_start(self.entry2,False,False,0)
        mainbox.pack_start(thebox,True,True,0)
        mainbox.pack_start(self.okbutton,True,False,0)
       
        
        
        
        mainbox.show()
        thebox.show()
        self.phd_window.show()
        
    def phd_entry_button(self,widget):
        minphd = self.entry.get_text()
        maxphd = self.entry2.get_text()
        phdfilt = [minphd,maxphd]
        self.phd_window.destroy()
        self.filter_phd(phdfilt)
#    	
    ### phd filter function ##
    def filter_phd(self, phdfilt):
        phdfilt = [int(x) for x in phdfilt]
        
    	
    	fakedata = '/home/rachel/codes/chesstest.fits'
	hdu = fits.open(fakedata)
	PHD = hdu[1].data['PHD']
	PHD = np.array(PHD)
	data  = hdu[1].data
	newdata = data[(PHD > phdfilt[0]) & (PHD < phdfilt[1])]
	
	
	plt.subplot(221)
	oldplot = plt.plot(data['X'],data['Y'],linestyle = '',marker = '.')
	
	plt.subplot(222)
	newplot = plt.plot(newdata['X'],newdata['Y'],linestyle = '',marker = '.')
	
	plt.show()
    	

    	 
   ### mouse click on remove orders ###
    def orderbutton_clicked(self, widget, data):
    	self.statusbar.push(data,'click on the order that you want to exclude.')
   	
   	self.remove = []
   	lines = self.lines
   	def onclick_order(event):
   		if self.orderbutton.get_active():
	   		self.remove.append(event.ydata)
	   		remove = self.remove
	   		self.remove_orders(remove,lines)
   		
   	cid4 = self.canvas.mpl_connect('button_press_event',onclick_order)
   	if [self.orderbutton.get_active()] == [False]:
    			self.statusbar.push(0,'Opened File:' + _File)
   ### removing orders
    def remove_orders(self,remove,lines):
    	bad_orders = []
    	bad_orders_index = []
    	
    	for i in range(0,len(remove)):
    		bad = min(lines, key=lambda x:abs(x-remove[i]))
    	        bad_orders.append(bad)
    	        bad_orders_index.append( np.where(lines == bad) )

    	      
    	newlines = filter(lambda lines: lines not in bad_orders,lines)
    	xchunk = self.xchunk
    	ychunk = self.ychunk
    	self.e.cla()
    	lines = newlines
    	self.update_ordersplot(ychunk,xchunk,lines)
    	
    	#for key in oneDorders.keys(): print key
    	print 'number or original orders',len(oneDorders)
        self.new_dictionary(bad_orders_index)
        

    def new_dictionary(self,bad_orders_index):
                
        maxint = len(oneDorders)	
        for i in range(0,len(bad_orders_index)):
        	num = int(bad_orders_index[i][0])
	
        	if oneDorders.get(str(num),None):
        		oneDorders.pop(str(num))
        	for key in oneDorders.keys():
        	        k = int(key)
        		if k > num:
        		        oneDorders[str(k-1)] = oneDorders.get(key)
        		if k == maxint-1:
        		        
        			oneDorders.pop(key)
#        		
        	
        print 'corrected number of orders',len(oneDorders)
        	
        self.save_pickle(oneDorders)
        #for key in oneDorders.keys(): print key
    def save_pickle(self, ondDorders):
    	order_dict = oneDorders
        now = datetime.datetime.now()
        date = now.strftime("%m_%d_%Y")	
        targname = str(self.targname)
    	pickle.dump(order_dict,open(''+targname+'_1D_'+date+'.p','wb'))       
コード例 #8
0
ファイル: Principal.py プロジェクト: etvorellana/iem-wbb
class MyWindow(Gtk.Window):
    def __init__(self):


        #Janela
        Gtk.Window.__init__(self, title="Testando")
        self.set_resizable(False)
        self.set_size_request(600, 600)
        self.set_position(Gtk.WindowPosition.CENTER)

        self.set_border_width(10)

        principal = Gtk.Box(spacing=10)
        principal.set_homogeneous(False)

        vbox_left = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        vbox_left.set_homogeneous(False)
        vbox_right = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        vbox_right.set_homogeneous(False)

            ### Boxes que ficarão dentro da vbox_left ###
        hbox_MDIST = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        hbox_MDIST.set_homogeneous(False)
        hbox_labels = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        hbox_labels.set_homogeneous(False)
        hbox_RDIST = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        hbox_RDIST.set_homogeneous(True)
        hbox_TOTEX = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        hbox_TOTEX.set_homogeneous(True)
        hbox_MVELO = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        hbox_MVELO.set_homogeneous(True)

        #criando os elementos das boxes Mdist, Labels, Rdist, TOTEX, Mvelo
                ##MDIST##
        label_Mdist = Gtk.Label('MDIST')
        self.entry_Mdist = Gtk.Entry()
        self.entry_Mdist.set_editable(False)
        self.entry_Mdist.set_max_length(max=8)
                ##LABELS##
        label_vazia = Gtk.Label('     ')
        label_AP = Gtk.Label('AP')
        label_ML = Gtk.Label('ML')
        label_TOTAL = Gtk.Label('TOTAL')
                ##RDIST##
        label_Rdist = Gtk.Label('RDIST')
        self.entry_Rdist_AP = Gtk.Entry()
        self.entry_Rdist_AP.set_editable(False)
        self.entry_Rdist_AP.set_max_length(max=8)
        self.entry_Rdist_ML = Gtk.Entry()
        self.entry_Rdist_ML.set_editable(False)
        self.entry_Rdist_ML.set_max_length(max=8)
        self.entry_Rdist_TOTAL = Gtk.Entry()
        self.entry_Rdist_TOTAL.set_editable(False)
        self.entry_Rdist_TOTAL.set_max_length(max=8)
                ##TOTEX##
        label_TOTEX = Gtk.Label('TOTEX')
        self.entry_TOTEX_AP = Gtk.Entry()
        self.entry_TOTEX_AP.set_editable(False)
        self.entry_TOTEX_AP.set_max_length(max=8)
        self.entry_TOTEX_ML = Gtk.Entry()
        self.entry_TOTEX_ML.set_editable(False)
        self.entry_TOTEX_ML.set_max_length(max=8)
        self.entry_TOTEX_TOTAL = Gtk.Entry()
        self.entry_TOTEX_TOTAL.set_editable(False)
        self.entry_TOTEX_TOTAL.set_max_length(max=8)
                ##MVELO##
        label_MVELO = Gtk.Label('MVELO')
        self.entry_MVELO_AP = Gtk.Entry()
        self.entry_MVELO_AP.set_editable(False)
        self.entry_MVELO_AP.set_max_length(max=8)
        self.entry_MVELO_ML = Gtk.Entry()
        self.entry_MVELO_ML.set_editable(False)
        self.entry_MVELO_ML.set_max_length(max=8)
        self.entry_MVELO_TOTAL = Gtk.Entry()
        self.entry_MVELO_TOTAL.set_editable(False)
        self.entry_MVELO_TOTAL.set_max_length(max=8)

        #colocando cada elemento dentro da sua box
        hbox_MDIST.pack_start(label_Mdist,True,True,0)
        hbox_MDIST.pack_start(self.entry_Mdist,True,True,0)

        hbox_labels.pack_start(label_vazia,True,True,0)
        hbox_labels.pack_start(label_AP,True,True,0)
        hbox_labels.pack_start(label_ML,True,True,0)
        hbox_labels.pack_start(label_TOTAL,True,True,0)

        hbox_RDIST.pack_start(label_Rdist,True,True,0)
        hbox_RDIST.pack_start(self.entry_Rdist_AP,True,True,0)
        hbox_RDIST.pack_start(self.entry_Rdist_ML,True,True,0)
        hbox_RDIST.pack_start(self.entry_Rdist_TOTAL,True,True,0)

        hbox_TOTEX.pack_start(label_TOTEX, True, True, 0)
        hbox_TOTEX.pack_start(self.entry_TOTEX_AP, True, True, 0)
        hbox_TOTEX.pack_start(self.entry_TOTEX_ML, True, True, 0)
        hbox_TOTEX.pack_start(self.entry_TOTEX_TOTAL, True, True, 0)

        hbox_MVELO.pack_start(label_MVELO, True, True, 0)
        hbox_MVELO.pack_start(self.entry_MVELO_AP, True, True, 0)
        hbox_MVELO.pack_start(self.entry_MVELO_ML, True, True, 0)
        hbox_MVELO.pack_start(self.entry_MVELO_TOTAL, True, True, 0)

        #colocando as boxes pequenas dentro das box vbox_left
        vbox_left.pack_start(hbox_MDIST, True, True, 0)
        vbox_left.pack_start(hbox_labels, True, True, 0)
        vbox_left.pack_start(hbox_RDIST, True, True, 0)
        vbox_left.pack_start(hbox_TOTEX, True, True, 0)
        vbox_left.pack_start(hbox_MVELO, True, True, 0)

        #elementos da vbox_right)
        #Notebook
        self.notebook = Gtk.Notebook()
        self.fig = plt.figure()


        self.axis = self.fig.add_subplot(111)
        self.axis.set_ylabel('ML')
        self.axis.set_xlabel('AP')
        self.canvas = FigureCanvas(self.fig)
        self.canvas.set_size_request(500, 500)



        self.page1 = Gtk.Box()
        self.page1.set_border_width(10)
        self.page1.add(self.canvas)
        self.notebook.append_page(self.page1, Gtk.Label('Gráfico do CoP'))

        ##aqui fica a segunda janela do notebook
        self.fig2 = plt.figure()
        self.axis2 = self.fig2.add_subplot(111)
        self.axis2.set_ylabel('ML')
        self.axis2.set_xlabel('AP')
        self.canvas2 = FigureCanvas(self.fig2)
        self.canvas2.set_size_request(500, 500)

        self.page2 = Gtk.Box()
        self.page2.set_border_width(10)
        self.page2.add(self.canvas2)
        self.notebook.append_page(self.page2, Gtk.Label('Gráfico na frequência'))

        #criando os botoes
        hbox_botoes = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        hbox_botoes.set_homogeneous(True)

        self.button1 = Gtk.Button(label="Capturar")
        self.button1.connect("clicked", self.on_button1_clicked)

        self.button2 = Gtk.Button(label="Processar")
        self.button2.connect("clicked", self.on_button2_clicked)
        #self.set_resizable(True
        #colocando os botoes nas boxes
        hbox_botoes.pack_start(self.button1, True, True,0)
        hbox_botoes.pack_start(self.button2, True, True, 0)

        vbox_right.pack_start(self.notebook, True, True, 0)
        vbox_right.pack_start(hbox_botoes, True, True, 0)
        # colocando as boxes verticais dentro da box principal
        principal.pack_start(vbox_left, True, True, 0)
        principal.pack_start(vbox_right, True, True, 0)

        #Adicionano os elementos na box exterior
        self.add(principal)

    def on_button1_clicked(self, widget):
        global APs, MLs
    
        pos_AP = []
        pos_ML = []
        
        AP_aux = []
        ML_aux = []

        ref_arquivo_x_diferente = open("/home/thales/wiibalance/cwiid/python/xdiferente.txt", "r")
        ref_arquivo_y_diferente = open("/home/thales/wiibalance/cwiid/python/ydiferente.txt", "r")

        for linhax in ref_arquivo_x_diferente:
            AP_aux.append(ref_arquivo_x_diferente.readline(13))

        for linhay in ref_arquivo_y_diferente:
            ML_aux.append(ref_arquivo_y_diferente.readline(13))

        ref_arquivo_x_diferente.close()
        ref_arquivo_y_diferente.close()

        for i in range(len(AP_aux)):
            e = AP_aux[i]

            try:
                APs.append(float(e))
            except:
                #print('posicao de x que nao conseguiu pegar o valor real:', i)
                pos_AP.append(i)
                
        for j in range(len(ML_aux)):
            e = ML_aux[j]

            try:
                MLs.append(float(e))
            except:
                #print('posicao de y que nao conseguiu pegar o valor real:', j)
                pos_ML.append(j)
                
        #APs, MLs = calc.geraNumeroAleatorio(-3, 7, -4, 6, 40)

        if calc.diferentes(APs,MLs):
            if len(APs) > len(MLs):
                APs = calc.delEleAP(APs, pos_ML)
            else:
                MLs =calc.delEleML(MLs, pos_AP)

        max_absoluto_AP = calc.valorAbsoluto(min(APs), max(APs))
        max_absoluto_ML = calc.valorAbsoluto(min(MLs), max(MLs))

        print('max_absoluto_AP:',max_absoluto_AP,'max_absoluto_ML:',max_absoluto_ML)

        self.axis.clear()
        self.axis.set_ylabel('ML')
        self.axis.set_xlabel('AP')

        self.axis.set_xlim(-max_absoluto_AP, max_absoluto_AP)
        self.axis.set_ylim(-max_absoluto_ML, max_absoluto_ML)
        self.axis.plot(APs, MLs,'-',color='r')
        self.canvas.draw()


    def on_button2_clicked(self, widget):
        global APs, MLs
        APs, MLs = calc.geraAP_ML(APs, MLs)

        dis_resultante_total = calc.distanciaResultante(APs, MLs)
        dis_resultante_AP = calc.distanciaResultanteParcial(APs)
        dis_resultante_ML = calc.distanciaResultanteParcial(MLs)

        dis_media = calc.distanciaMedia(dis_resultante_total)

        dis_rms_total = calc.dist_RMS(dis_resultante_total)
        dis_rms_AP = calc.dist_RMS(dis_resultante_AP)
        dis_rms_ML = calc.dist_RMS(dis_resultante_ML)

        totex_total = calc.totex(APs, MLs)
        totex_AP = calc.totexParcial(APs)
        totex_ML = calc.totexParcial(MLs)

        mvelo_total = calc.mVelo(totex_total, 20)
        mvelo_AP = calc.mVelo(totex_AP, 20)
        mvelo_ML =  calc.mVelo(totex_ML, 20)

        self.entry_Mdist.set_text(str(dis_media))

        self.entry_Rdist_TOTAL.set_text(str(dis_rms_total))
        self.entry_Rdist_AP.set_text(str(dis_rms_AP))
        self.entry_Rdist_ML.set_text(str(dis_rms_ML))

        self.entry_TOTEX_TOTAL.set_text(str(totex_total))
        self.entry_TOTEX_AP.set_text(str(totex_AP))
        self.entry_TOTEX_ML.set_text(str(totex_ML))

        self.entry_MVELO_TOTAL.set_text(str(mvelo_total))
        self.entry_MVELO_AP.set_text(str(mvelo_AP))
        self.entry_MVELO_ML.set_text(str(mvelo_ML))

        max_absoluto_AP = calc.valorAbsoluto(min(APs), max(APs))
        max_absoluto_ML = calc.valorAbsoluto(min(MLs), max(MLs))

        print('max_absoluto_AP:', max_absoluto_AP, 'max_absoluto_ML:', max_absoluto_ML)
        self.axis.clear()

        self.axis.set_xlim(-max_absoluto_AP, max_absoluto_AP)
        self.axis.set_ylim(-max_absoluto_ML, max_absoluto_ML)

        self.axis.plot(APs, MLs,'.-',color='g')

        self.axis.set_ylabel('ML')
        self.axis.set_xlabel('AP')
        self.canvas.draw()
コード例 #9
0
class CampaignGraph(object):
	"""
	A basic graph provider for using :py:mod:`matplotlib` to create graph
	representations of campaign data. This class is meant to be subclassed
	by real providers.
	"""
	name = 'Unknown'
	"""The name of the graph provider."""
	name_human = 'Unknown'
	"""The human readable name of the graph provider used for UI identification."""
	graph_title = 'Unknown'
	"""The title that will be given to the graph."""
	table_subscriptions = []
	"""A list of tables from which information is needed to produce the graph."""
	is_available = True
	def __init__(self, config, parent, size_request=None):
		"""
		:param dict config: The King Phisher client configuration.
		:param parent: The parent window for this object.
		:type parent: :py:class:`Gtk.Window`
		:param tuple size_request: The size to set for the canvas.
		"""
		self.config = config
		"""A reference to the King Phisher client configuration."""
		self.parent = parent
		"""The parent :py:class:`Gtk.Window` instance."""
		self.figure, _ = pyplot.subplots()
		self.axes = self.figure.get_axes()
		self.canvas = FigureCanvas(self.figure)
		self.manager = None
		if size_request:
			self.canvas.set_size_request(*size_request)
		self.canvas.mpl_connect('button_press_event', self.mpl_signal_canvas_button_pressed)
		self.canvas.show()
		self.navigation_toolbar = NavigationToolbar(self.canvas, self.parent)
		self.popup_menu = Gtk.Menu.new()

		menu_item = Gtk.MenuItem.new_with_label('Export')
		menu_item.connect('activate', self.signal_activate_popup_menu_export)
		self.popup_menu.append(menu_item)

		menu_item = Gtk.MenuItem.new_with_label('Refresh')
		menu_item.connect('activate', lambda action: self.refresh())
		self.popup_menu.append(menu_item)

		menu_item = Gtk.CheckMenuItem.new_with_label('Show Toolbar')
		menu_item.connect('toggled', self.signal_toggled_popup_menu_show_toolbar)
		self._menu_item_show_toolbar = menu_item
		self.popup_menu.append(menu_item)
		self.popup_menu.show_all()
		self.navigation_toolbar.hide()

	def _load_graph(self, info_cache):
		raise NotImplementedError()

	def _graph_bar_set_yparams(self, top_lim):
		min_value = top_lim + (top_lim * 0.075)
		if min_value <= 25:
			scale = 5
		else:
			scale = scale = 10 ** (len(str(int(min_value))) - 1)
		inc_scale = scale
		while scale <= min_value:
			scale += inc_scale
		top_lim = scale

		ax = self.axes[0]
		yticks = set((round(top_lim * 0.5), top_lim))
		ax.set_yticks(tuple(yticks))
		ax.set_ylim(top=top_lim)
		return

	def _graph_null_pie(self, title):
		ax = self.axes[0]
		ax.pie((100,), labels=(title,), colors=(MPL_COLOR_NULL,), autopct='%1.0f%%', shadow=True, startangle=90)
		ax.axis('equal')
		return

	def add_legend_patch(self, legend_rows, fontsize=None):
		handles = []
		if not fontsize:
			scale = self.markersize_scale
			if scale < 5:
				fontsize = 'xx-small'
			elif scale < 7:
				fontsize = 'x-small'
			elif scale < 9:
				fontsize = 'small'
			else:
				fontsize = 'medium'
		for row in legend_rows:
			handles.append(patches.Patch(color=row[0], label=row[1]))
		self.axes[0].legend(handles=handles, fontsize=fontsize, loc='lower right')

	def graph_bar(self, bars, color=None, xticklabels=None, ylabel=None):
		"""
		Create a standard bar graph with better defaults for the standard use
		cases.

		:param list bars: The values of the bars to graph.
		:param color: The color of the bars on the graph.
		:type color: list, str
		:param list xticklabels: The labels to use on the x-axis.
		:param str ylabel: The label to give to the y-axis.
		:return: The bars created using :py:mod:`matplotlib`
		:rtype: `matplotlib.container.BarContainer`
		"""
		color = color or MPL_COLOR_NULL
		width = 0.25
		ax = self.axes[0]
		self._graph_bar_set_yparams(max(bars) if bars else 0)
		bars = ax.bar(range(len(bars)), bars, width, color=color)
		ax.set_xticks([float(x) + (width / 2) for x in range(len(bars))])
		if xticklabels:
			ax.set_xticklabels(xticklabels, rotation=30)
			for col in bars:
				height = col.get_height()
				ax.text(col.get_x() + col.get_width() / 2.0, height, "{0:,}".format(height), ha='center', va='bottom')
		if ylabel:
			ax.set_ylabel(ylabel)
		self.figure.subplots_adjust(bottom=0.25)
		return bars

	def make_window(self):
		"""
		Create a window from the figure manager.

		:return: The graph in a new, dedicated window.
		:rtype: :py:class:`Gtk.Window`
		"""
		if self.manager == None:
			self.manager = FigureManager(self.canvas, 0)
		self.navigation_toolbar.destroy()
		self.navigation_toolbar = self.manager.toolbar
		self._menu_item_show_toolbar.set_active(True)
		window = self.manager.window
		window.set_transient_for(self.parent)
		window.set_title(self.graph_title)
		return window

	@property
	def markersize_scale(self):
		bbox = self.axes[0].get_window_extent().transformed(self.figure.dpi_scale_trans.inverted())
		return max(bbox.width, bbox.width) * self.figure.dpi * 0.01

	def mpl_signal_canvas_button_pressed(self, event):
		if event.button != 3:
			return
		self.popup_menu.popup(None, None, None, None, event.button, Gtk.get_current_event_time())
		return True

	def signal_activate_popup_menu_export(self, action):
		dialog = gui_utilities.FileChooser('Export Graph', self.parent)
		file_name = self.config['campaign_name'] + '.png'
		response = dialog.run_quick_save(file_name)
		dialog.destroy()
		if not response:
			return
		destination_file = response['target_path']
		self.figure.savefig(destination_file, format='png')

	def signal_toggled_popup_menu_show_toolbar(self, widget):
		if widget.get_property('active'):
			self.navigation_toolbar.show()
		else:
			self.navigation_toolbar.hide()

	def load_graph(self):
		"""Load the graph information via :py:meth:`.refresh`."""
		self.refresh()

	def refresh(self, info_cache=None, stop_event=None):
		"""
		Refresh the graph data by retrieving the information from the
		remote server.

		:param dict info_cache: An optional cache of data tables.
		:param stop_event: An optional object indicating that the operation should stop.
		:type stop_event: :py:class:`threading.Event`
		:return: A dictionary of cached tables from the server.
		:rtype: dict
		"""
		info_cache = (info_cache or {})
		if not self.parent.rpc:
			return info_cache
		for table in self.table_subscriptions:
			if stop_event and stop_event.is_set():
				return info_cache
			if not table in info_cache:
				info_cache[table] = tuple(self.parent.rpc.remote_table('campaign/' + table, self.config['campaign_id']))
		for ax in self.axes:
			ax.clear()
		self._load_graph(info_cache)
		self.axes[0].set_title(self.graph_title, y=1.03)
		self.canvas.draw()
		return info_cache
コード例 #10
0
class RotationDialog(object):
    """
    This class controls the appearance and signals of the data-rotation dialog.

    This class pulls the rotation dialog from the Glade file, intilizes the
    widgets and has methods for the signals defined in Glade.
    """
    def __init__(self, main_window, settings, data, add_layer_dataset,
                 add_feature, redraw_main):
        """
        Initializes the RotationDialog class.

        Requires the main_window object, the settings object (PlotSettings
        class) and the data rows to initialize. All the necessary widgets are
        loaded from the Glade file. A matplotlib figure is set up and added
        to the scrolledwindow. Two axes are set up that show the original and
        rotated data.
        """
        self.builder = Gtk.Builder()
        self.builder.set_translation_domain(i18n().get_ts_domain())
        script_dir = os.path.dirname(__file__)
        rel_path = "gui_layout.glade"
        abs_path = os.path.join(script_dir, rel_path)
        self.builder.add_objects_from_file(
            abs_path, ("dialog_rotation", "adjustment_rotation_dipdir",
                       "adjustment_rotation_dip", "adjustment_rotation_angle"))
        self.dialog = self.builder.get_object("dialog_rotation")
        self.dialog.set_transient_for(main_window)
        self.settings = settings
        self.data = data
        self.trans = self.settings.get_transform()
        self.add_layer_dataset = add_layer_dataset
        self.add_feature = add_feature
        self.redraw_main = redraw_main

        self.adjustment_rotation_dipdir = self.builder.get_object(
            "adjustment_rotation_dipdir")
        self.adjustment_rotation_dip = self.builder.get_object(
            "adjustment_rotation_dip")
        self.adjustment_rotation_angle = self.builder.get_object(
            "adjustment_rotation_angle")

        self.spinbutton_rotation_dipdir = self.builder.get_object(
            "spinbutton_rotation_dipdir")
        self.spinbutton_rotation_dip = self.builder.get_object(
            "spinbutton_rotation_dip")
        self.spinbutton_rotation_angle = self.builder.get_object(
            "spinbutton_rotation_angle")

        self.scrolledwindow_rotate = self.builder.get_object(
            "scrolledwindow_rotate")

        self.fig = Figure(dpi=self.settings.get_pixel_density())
        self.canvas = FigureCanvas(self.fig)
        self.scrolledwindow_rotate.add_with_viewport(self.canvas)

        gridspec = GridSpec(1, 2)
        original_sp = gridspec.new_subplotspec((0, 0), rowspan=1, colspan=1)
        rotated_sp = gridspec.new_subplotspec((0, 1), rowspan=1, colspan=1)
        self.original_ax = self.fig.add_subplot(
            original_sp, projection=self.settings.get_projection())
        self.rotated_ax = self.fig.add_subplot(
            rotated_sp, projection=self.settings.get_projection())

        self.canvas.draw()
        self.redraw_plot()
        self.dialog.show_all()
        self.builder.connect_signals(self)
        if sys.platform == "win32":
            translate_gui(self.builder)

    def run(self):
        """
        Runs the dialog.

        Called from the MainWindow class. Initializes and shows the dialog.
        """
        self.dialog.run()

    def on_dialog_rotation_destroy(self, widget):
        """
        Hides the dialog on destroy.

        When the dialog is destroyed it is hidden.
        """
        self.dialog.hide()

    def on_button_cancel_rotation_clicked(self, button):
        """
        Exits the rotation dialog and makes no changes to the project.

        When the user clicks on Cancel the dialog is hidden, and no changes
        are made to the project structure.
        """
        self.dialog.hide()

    def on_button_apply_rotate_clicked(self, button):
        """
        Adds the rotated layers to the project.

        When the user clicks on "apply the rotation", the rotated data is
        added to the project as new datasets.
        """
        raxis_dipdir = self.spinbutton_rotation_dipdir.get_value()
        raxis_dip = self.spinbutton_rotation_dip.get_value()
        raxis = [raxis_dipdir, raxis_dip]
        raxis_angle = self.spinbutton_rotation_angle.get_value()

        for lyr_obj in self.data:
            lyr_type = lyr_obj.get_layer_type()
            lyr_store = lyr_obj.get_data_treestore()

            if lyr_type == "plane":
                dipdir_org, dips_org, dipdir_lst, dips_lst, strat, dipdir_az = \
                    self.parse_plane(lyr_store, raxis, raxis_angle)

                store, new_lyr_obj = self.add_layer_dataset("plane")
                for dipdir, dip, strt in zip(dipdir_az, dips_lst, strat):
                    self.add_feature("plane", store, dipdir, dip, strt)

            elif lyr_type == "line":
                ldipdir_org, ldips_org, ldipdir_lst, ldips_lst, sense = \
                    self.parse_line(lyr_store, raxis, raxis_angle)

                store, new_lyr_obj = self.add_layer_dataset("line")

                for dipdir, dip, sns in zip(ldipdir_lst, ldips_lst, sense):
                    self.add_feature("line", store, dipdir, dip, sns)

            elif lyr_type == "smallcircle":
                ldipdir_org, ldips_org, ldipdir_lst, ldips_lst, angle = \
                    self.parse_line(lyr_store, raxis, raxis_angle)

                store, new_lyr_obj = self.add_layer_dataset("smallcircle")
                for dipdir, dip, ang in zip(ldipdir_lst, ldips_lst, angle):
                    self.add_feature("smallcircle", store, dipdir, dip, ang)

            elif lyr_type == "faultplane":
                rtrn = self.parse_faultplane(lyr_store, raxis, raxis_angle)
                dipdir_org, dips_org, dipdir_lst, dips_lst, ldipdir_org, \
                ldips_org, ldipdir_lst, ldips_lst, sense, dipdir_az = rtrn[0], \
                rtrn[1], rtrn[2], rtrn[3], rtrn[4], rtrn[5], rtrn[6], rtrn[7], \
                rtrn[8], rtrn[9]

                store, new_lyr_obj = self.add_layer_dataset("faultplane")
                for dipdir, dip, ldipdir, ldip, sns in zip(
                        dipdir_az, dips_lst, ldipdir_lst, ldips_lst, sense):
                    self.add_feature("faultplane", store, dipdir, dip, ldipdir,
                                     ldip, sns)

            new_lyr_obj.set_properties(lyr_obj.get_properties())

        self.dialog.hide()
        self.redraw_main()

    def on_spinbutton_rotation_dipdir_value_changed(self, spinbutton):
        """
        Redraws the plot.

        When the value of the spinbutton is changed, the redraw_plot method
        is called, which rotates the data according to the new setting.
        """
        self.redraw_plot()

    def on_spinbutton_rotation_dip_value_changed(self, spinbutton):
        """
        Redraws the plot.

        When the value of the spinbutton is changed, the redraw_plot method
        is called, which rotates the data according to the new setting.
        """
        self.redraw_plot()

    def on_spinbutton_rotation_angle_value_changed(self, spinbutton):
        """
        Redraws the plot.

        When the value of the spinbutton is changed, the redraw_plot method
        is called, which rotates the data according to the new setting.
        """
        self.redraw_plot()

    def convert_lonlat_to_dipdir(self, lon, lat):
        """
        Converts lat-lon data to dip-direction and dip.

        Expects a longitude and a latitude value. The measurment is forward
        transformed into stereonet-space. Then the azimut (dip-direction) and
        diping angle are calculated. Returns two values: dip-direction and dip.
        """
        #The longitude and latitude have to be forward-transformed to get
        #the corect azimuth angle
        xy = np.array([[lon, lat]])
        xy_trans = self.trans.transform(xy)
        x = float(xy_trans[0, 0:1])
        y = float(xy_trans[0, 1:2])
        alpha = np.arctan2(x, y)
        alpha_deg = np.degrees(alpha)
        if alpha_deg < 0:
            alpha_deg += 360

        #Longitude and Latitude don't need to be converted for rotation.
        #The correct dip is the array[1] value once the vector has been
        #rotated in north-south position.
        array = mplstereonet.stereonet_math._rotate(np.degrees(lon),
                                                    np.degrees(lat),
                                                    alpha_deg * (-1))
        gamma = float(array[1])
        gamma_deg = 90 - np.degrees(gamma)

        #If the longitude is larger or small than pi/2 the measurment lies
        #on the upper hemisphere and needs to be corrected.
        if lon > (np.pi / 2) or lon < (-np.pi / 2):
            alpha_deg = alpha_deg + 180

        return alpha_deg, gamma_deg

    def rotate_data(self, raxis, raxis_angle, dipdir, dip):
        """
        Rotates a measurment around a rotation axis a set number of degrees.

        Expects a rotation-axis, a rotation-angle, a dip-direction and a
        dip angle. The measurement is converted to latlot and then passed
        to the mplstereonet rotate function.
        """
        lonlat = mplstereonet.line(dip, dipdir)

        #Rotation around x-axis until rotation-axis azimuth is east-west
        rot1 = (90 - raxis[0])
        lon1 = np.degrees(lonlat[0])
        lat1 = np.degrees(lonlat[1])
        lon_rot1, lat_rot1 = mplstereonet.stereonet_math._rotate(lon1,
                                                                 lat1,
                                                                 theta=rot1,
                                                                 axis="x")

        #Rotation around z-axis until rotation-axis dip is east-west
        rot2 = -(90 - raxis[1])
        lon2 = np.degrees(lon_rot1)
        lat2 = np.degrees(lat_rot1)
        lon_rot2, lat_rot2 = mplstereonet.stereonet_math._rotate(lon2,
                                                                 lat2,
                                                                 theta=rot2,
                                                                 axis="z")

        #Rotate around the x-axis for the specified rotation:
        rot3 = raxis_angle
        lon3 = np.degrees(lon_rot2)
        lat3 = np.degrees(lat_rot2)
        lon_rot3, lat_rot3 = mplstereonet.stereonet_math._rotate(lon3,
                                                                 lat3,
                                                                 theta=rot3,
                                                                 axis="x")

        #Undo the z-axis rotation
        rot4 = -rot2
        lon4 = np.degrees(lon_rot3)
        lat4 = np.degrees(lat_rot3)
        lon_rot4, lat_rot4 = mplstereonet.stereonet_math._rotate(lon4,
                                                                 lat4,
                                                                 theta=rot4,
                                                                 axis="z")

        #Undo the x-axis rotation
        rot5 = -rot1
        lon5 = np.degrees(lon_rot4)
        lat5 = np.degrees(lat_rot4)
        lon_rot5, lat_rot5 = mplstereonet.stereonet_math._rotate(lon5,
                                                                 lat5,
                                                                 theta=rot5,
                                                                 axis="x")
        dipdir5, dip5 = self.convert_lonlat_to_dipdir(lon_rot5, lat_rot5)
        return dipdir5, dip5

    def parse_plane(self, lyr_store, raxis, raxis_angle):
        """
        Parses and rotates data of a plane layer.

        Expects a TreeStore of a layer, the rotation axis and the
        angle of rotation. The method returns each column unrotated and rotated.        
        """
        dipdir_org = []
        dips_org = []
        dipdir_lst = []
        dips_lst = []
        dipdir_az = []
        strat = []

        for row in lyr_store:
            dipdir_org.append(row[0] - 90)
            dips_org.append(row[1])
            #Planes and faultplanes are rotated using their poles
            dipdir, dip = self.rotate_data(raxis, raxis_angle, row[0] + 180,
                                           90 - row[1])
            dipdir_lst.append(dipdir + 90)
            dipdir_az.append(dipdir + 180)
            dips_lst.append(90 - dip)
            strat.append(row[2])

        return dipdir_org, dips_org, dipdir_lst, dips_lst, strat, dipdir_az

    def parse_line(self, lyr_store, raxis, raxis_angle):
        """
        Parses and rotates data of a linear or smallcircle layer.

        Expects a TreeStore of a layer, the rotation axis and the
        angle of rotation. The method returns each column unrotated and rotated.        
        """
        ldipdir_org = []
        ldips_org = []
        ldipdir_lst = []
        ldips_lst = []
        third_col = []

        for row in lyr_store:
            ldipdir_org.append(row[0])
            ldips_org.append(row[1])
            ldipdir, ldip = self.rotate_data(raxis, raxis_angle, row[0],
                                             row[1])
            ldipdir_lst.append(ldipdir)
            ldips_lst.append(ldip)
            third_col.append(row[2])

        return ldipdir_org, ldips_org, ldipdir_lst, ldips_lst, third_col

    def parse_faultplane(self, lyr_store, raxis, raxis_angle):
        """
        Parses and rotates data of a faultplane layer.

        Expects a TreeStore of a faultplane layer, the rotation axis and the
        angle of rotation. The method returns each column unrotated and rotated.        
        """
        dipdir_org = []
        dips_org = []
        dipdir_lst = []
        dips_lst = []
        ldipdir_org = []
        ldips_org = []
        ldipdir_lst = []
        ldips_lst = []
        dipdir_az = []
        sense = []

        for row in lyr_store:
            dipdir_org.append(row[0] - 90)
            dips_org.append(row[1])
            #Planes and faultplanes are rotated using their poles
            dipdir, dip = self.rotate_data(raxis, raxis_angle, row[0] + 180,
                                           90 - row[1])
            dipdir_lst.append(dipdir + 90)
            dipdir_az.append(dipdir + 270)
            dips_lst.append(90 - dip)

            ldipdir_org.append(row[2])
            ldips_org.append(row[3])
            ldipdir, ldip = self.rotate_data(raxis, raxis_angle, row[2],
                                             row[3])
            ldipdir_lst.append(ldipdir)
            ldips_lst.append(ldip)
            sense.append(row[4])

        return (dipdir_org, dips_org, dipdir_lst, dips_lst, ldipdir_org,
                ldips_org, ldipdir_lst, ldips_lst, sense, dipdir_az)

    def redraw_plot(self):
        """
        Redraws the plot using the current settings of the dialog's spinbuttons.

        This method clears the two axes and adds the annotations. The current
        values of the rotation axis and rotation angle spinbuttons are
        retrieved. The data is parsed, and the features are then drawn.
        In addition the rotation-axis is drawn.
        """
        self.original_ax.cla()
        self.rotated_ax.cla()
        self.original_ax.grid(False)
        self.rotated_ax.grid(False)
        self.original_ax.set_azimuth_ticks([0], labels=["N"])
        self.rotated_ax.set_azimuth_ticks([0], labels=["N"])

        bar = 0.05
        self.original_ax.annotate("",
                                  xy=(-bar, 0),
                                  xytext=(bar, 0),
                                  xycoords="data",
                                  arrowprops=dict(arrowstyle="-",
                                                  connectionstyle="arc3"))
        self.original_ax.annotate("",
                                  xy=(0, -bar),
                                  xytext=(0, bar),
                                  xycoords="data",
                                  arrowprops=dict(arrowstyle="-",
                                                  connectionstyle="arc3"))
        self.rotated_ax.annotate("",
                                 xy=(-bar, 0),
                                 xytext=(bar, 0),
                                 xycoords="data",
                                 arrowprops=dict(arrowstyle="-",
                                                 connectionstyle="arc3"))
        self.rotated_ax.annotate("",
                                 xy=(0, -bar),
                                 xytext=(0, bar),
                                 xycoords="data",
                                 arrowprops=dict(arrowstyle="-",
                                                 connectionstyle="arc3"))

        raxis_dipdir = self.spinbutton_rotation_dipdir.get_value()
        raxis_dip = self.spinbutton_rotation_dip.get_value()
        raxis = [raxis_dipdir, raxis_dip]
        raxis_angle = self.spinbutton_rotation_angle.get_value()

        for lyr_obj in self.data:
            lyr_type = lyr_obj.get_layer_type()
            lyr_store = lyr_obj.get_data_treestore()

            if lyr_type == "plane":
                dipdir_org, dips_org, dipdir_lst, dips_lst, strat, dipdir_az = \
                    self.parse_plane(lyr_store, raxis, raxis_angle)

                self.original_ax.plane(dipdir_org,
                                       dips_org,
                                       color=lyr_obj.get_line_color(),
                                       linewidth=lyr_obj.get_line_width(),
                                       linestyle=lyr_obj.get_line_style(),
                                       dash_capstyle=lyr_obj.get_capstyle(),
                                       alpha=lyr_obj.get_line_alpha(),
                                       clip_on=False)
                self.rotated_ax.plane(dipdir_lst,
                                      dips_lst,
                                      color=lyr_obj.get_line_color(),
                                      linewidth=lyr_obj.get_line_width(),
                                      linestyle=lyr_obj.get_line_style(),
                                      dash_capstyle=lyr_obj.get_capstyle(),
                                      alpha=lyr_obj.get_line_alpha(),
                                      clip_on=False)

            elif lyr_type == "line":
                ldipdir_org, ldips_org, ldipdir_lst, ldips_lst, sense = \
                    self.parse_line(lyr_store, raxis, raxis_angle)

                self.original_ax.line(
                    ldips_org,
                    ldipdir_org,
                    marker=lyr_obj.get_marker_style(),
                    markersize=lyr_obj.get_marker_size(),
                    color=lyr_obj.get_marker_fill(),
                    markeredgewidth=lyr_obj.get_marker_edge_width(),
                    markeredgecolor=lyr_obj.get_marker_edge_color(),
                    alpha=lyr_obj.get_marker_alpha(),
                    clip_on=False)
                self.rotated_ax.line(
                    ldips_lst,
                    ldipdir_lst,
                    marker=lyr_obj.get_marker_style(),
                    markersize=lyr_obj.get_marker_size(),
                    color=lyr_obj.get_marker_fill(),
                    markeredgewidth=lyr_obj.get_marker_edge_width(),
                    markeredgecolor=lyr_obj.get_marker_edge_color(),
                    alpha=lyr_obj.get_marker_alpha(),
                    clip_on=False)

            elif lyr_type == "smallcircle":
                ldipdir_org, ldips_org, ldipdir_lst, ldips_lst, angle = \
                    self.parse_line(lyr_store, raxis, raxis_angle)

                self.original_ax.cone(ldips_org,
                                      ldipdir_org,
                                      angle,
                                      facecolor="None",
                                      color=lyr_obj.get_line_color(),
                                      linewidth=lyr_obj.get_line_width(),
                                      label=lyr_obj.get_label(),
                                      linestyle=lyr_obj.get_line_style())
                self.rotated_ax.cone(ldips_lst,
                                     ldipdir_lst,
                                     angle,
                                     facecolor="None",
                                     color=lyr_obj.get_line_color(),
                                     linewidth=lyr_obj.get_line_width(),
                                     label=lyr_obj.get_label(),
                                     linestyle=lyr_obj.get_line_style())

            elif lyr_type == "faultplane":
                rtrn = self.parse_faultplane(lyr_store, raxis, raxis_angle)
                dipdir_org, dips_org, dipdir_lst, dips_lst, ldipdir_org, \
                ldips_org, ldipdir_lst, ldips_lst, sense = rtrn[0], rtrn[1], \
                rtrn[2], rtrn[3], rtrn[4], rtrn[5], rtrn[6], rtrn[7], rtrn[8]

                self.original_ax.plane(dipdir_org,
                                       dips_org,
                                       color=lyr_obj.get_line_color(),
                                       linewidth=lyr_obj.get_line_width(),
                                       linestyle=lyr_obj.get_line_style(),
                                       dash_capstyle=lyr_obj.get_capstyle(),
                                       alpha=lyr_obj.get_line_alpha(),
                                       clip_on=False)
                self.rotated_ax.plane(dipdir_lst,
                                      dips_lst,
                                      color=lyr_obj.get_line_color(),
                                      linewidth=lyr_obj.get_line_width(),
                                      linestyle=lyr_obj.get_line_style(),
                                      dash_capstyle=lyr_obj.get_capstyle(),
                                      alpha=lyr_obj.get_line_alpha(),
                                      clip_on=False)

                self.original_ax.line(
                    ldips_org,
                    ldipdir_org,
                    marker=lyr_obj.get_marker_style(),
                    markersize=lyr_obj.get_marker_size(),
                    color=lyr_obj.get_marker_fill(),
                    markeredgewidth=lyr_obj.get_marker_edge_width(),
                    markeredgecolor=lyr_obj.get_marker_edge_color(),
                    alpha=lyr_obj.get_marker_alpha(),
                    clip_on=False)
                self.rotated_ax.line(
                    ldips_lst,
                    ldipdir_lst,
                    marker=lyr_obj.get_marker_style(),
                    markersize=lyr_obj.get_marker_size(),
                    color=lyr_obj.get_marker_fill(),
                    markeredgewidth=lyr_obj.get_marker_edge_width(),
                    markeredgecolor=lyr_obj.get_marker_edge_color(),
                    alpha=lyr_obj.get_marker_alpha(),
                    clip_on=False)

        #Plot rotation axis
        self.original_ax.line(raxis_dip,
                              raxis_dipdir,
                              marker="o",
                              markersize=10,
                              color="#ff0000",
                              markeredgewidth=1,
                              markeredgecolor="#000000",
                              alpha=1,
                              clip_on=False)

        self.canvas.draw()
コード例 #11
0
ファイル: autotune.py プロジェクト: RickCarmichael/set64rs
class ATWindow(Gtk.Window):
    def __init__(self, pid):
        Gtk.Window.__init__(self, title="Auto-tune")
        self.pid = pid
        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

        f = matplotlib.figure.Figure()
        self.axes = f.add_subplot(111)
        self.axes.set_xlabel('Time (sec.)')
        self.axes.set_ylabel('Temperature (C)')
        self.axes.autoscale()
        self.out_axes = self.axes.twinx()
        self.out_axes.set_ylabel('OUT (%)')
        self.out_axes.autoscale()
        self.axes.grid()
        self.pv_x = []
        self.pv_y = []
        self.sv_x = []
        self.sv_y = []
        self.out_x = []
        self.out_y = []
        self.pv_plot, = self.axes.plot(self.pv_x, self.pv_y, 'b--') #b
        self.sv_plot, = self.axes.plot(self.sv_x, self.sv_y, 'k-') #k
        self.out_plot, = self.out_axes.plot(self.out_x, self.out_y, 'r:') #r

        self.canvas = FigureCanvas(f)
        self.canvas.set_size_request(800,600)

        vbox.add(self.canvas)

        hbox = Gtk.Box()

        self.start = Gtk.Button('Start', Gtk.STOCK_EXECUTE)
        self.start.connect('clicked', self.on_start)
        self.start.set_sensitive(False)
        hbox.pack_start(self.start, False, False, 0)

        self.stop = Gtk.Button('Stop', Gtk.STOCK_STOP)
        self.stop.connect('clicked', self.on_stop)
        self.stop.set_sensitive(False)
        hbox.pack_start(self.stop, False, False, 0)

        button = Gtk.Button('Close', Gtk.STOCK_CLOSE)
        button.connect('clicked', self.on_close)
        hbox.pack_end(button, False, False, 0)

        vbox.add(hbox)

        self.add(vbox)
        self.run = True
        self.start_at = True
        self.stop_at = False
        self.d = self.loop()
        self.d.addErrback(lambda x: None)
        self.connect('delete-event', self.on_delete)

    def on_start(self, widget):
        self.start_at = True

    def on_stop(self, widget):
        self.stop_at = True

    def on_delete(self, widget, event):
        self.run = False

    def on_close(self, widget):
        self.emit('delete-event', None)
        self.destroy()

    @twisted.internet.defer.inlineCallbacks
    def loop(self):
        start = time.time()
        while self.run:
            try:
                d = yield self.pid.flags()
                active = d['AT']
                if active:
                    self.stop.set_sensitive(True)
                    self.start.set_sensitive(False)
                    if self.stop_at:
                        yield self.pid.coil('NAT')

                    pv, mult = yield self.pid.holding_read('PV')
                    self.pv_x.append(time.time() - start)
                    self.pv_y.append(pv)
                    self.pv_plot.set_data(self.pv_x, self.pv_y)
                    self.axes.relim()
                    self.axes.autoscale()
                    self.canvas.draw()

                    sv, mult = yield self.pid.holding_read('dSV')
                    self.sv_x.append(time.time() - start)
                    self.sv_y.append(sv)
                    self.sv_plot.set_data(self.sv_x, self.sv_y)
                    self.axes.relim()
                    self.axes.autoscale()
                    self.canvas.draw()

                    out, mult = yield self.pid.holding_read('OUT')
                    self.out_x.append(time.time() - start)
                    self.out_y.append(out)
                    self.out_plot.set_data(self.out_x, self.out_y)
                    self.out_axes.relim()
                    self.out_axes.autoscale()
                    self.canvas.draw()

                else:
                    self.start.set_sensitive(True)
                    self.stop.set_sensitive(False)
                    if self.start_at:
                        yield self.pid.raw('ModL', 'SV')
                        yield self.pid.raw('At', 'On')
                        start = time.time()
                        self.pv_x = []
                        self.pv_y = []
                        self.sv_x = []
                        self.sv_y = []
                        self.out_x = []
                        self.out_y = []

                self.start_at = False
                self.stop_at = False
            except:
                pass

            d = twisted.internet.defer.Deferred()
            twisted.internet.reactor.callLater(1, d.callback, None)
            yield d

        yield self.pid.coil('NAT')
コード例 #12
0
class Handler:
    ## == initialization ==
    def __init__(self):  #{{{
        self.lockTreeViewEvents = False
        np.seterr(all='ignore')

        ## Plotting initialization
        self.fig = matplotlib.figure.Figure(figsize=(8, 8),
                                            dpi=96,
                                            facecolor='#eeeeee',
                                            tight_layout=1)
        # (figure is static, axes clear on every replot)
        self.canvas = FigureCanvas(self.fig)
        self.canvas.set_size_request(300, 300)
        self.toolbar = matplotlib.backends.backend_gtk3.NavigationToolbar2GTK3(
            self.canvas,
            w('box4').get_parent_window())

        self.xlim, self.ylim = None, None
        self.sw = Gtk.ScrolledWindow()
        self.sw.add_with_viewport(self.canvas)
        w('box4').pack_start(self.toolbar, False, True, 0)

        #self.toolbar.append_item(Gtk.Button('tetet'))
        ## TODO find out how to modify the NavigationToolbar...
        w('box4').pack_start(self.sw, True, True, 0)
        self.toolbar.pan()
        #TODO - define global shortcuts as a superset of the Matplotlib-GUI's internal, include also:
        #toolbar.zoom() #toolbar.home() #toolbar.back() #toolbar.forward() #toolbar.save_figure(toolbar)
        #TODO http://stackoverflow.com/questions/26433169/personalize-matplotlib-toolbar-with-log-feature
        #TODO http://dalelane.co.uk/blog/?p=778

        self.opj_file_cache = {}

        ## TreeStore and ListStore initialization
        self.tsFiles = Gtk.TreeStore(str, Pixbuf, str, Pixbuf, int, int, str)
        self.treeStoreColumns = {
            'filepath': 0,
            'icon': 1,
            'name': 2,
            'plotstyleicon': 3,
            'column': 4,
            'spreadsheet': 5,
            'rowtype': 6
        }
        self.dummy_treestore_row = [None for x in self.treeStoreColumns.keys()]

        treeViewCol0 = Gtk.TreeViewColumn("Plot")  # Create a TreeViewColumn
        colCellPlot = Gtk.CellRendererPixbuf(
        )  # Create a column cell to display text
        treeViewCol0.pack_start(colCellPlot, expand=True)
        treeViewCol0.add_attribute(colCellPlot, "pixbuf",
                                   3)  # set params for icon
        w('treeview1').append_column(
            treeViewCol0)  # Append the columns to the TreeView

        treeViewCol = Gtk.TreeViewColumn("File")  # Create a TreeViewColumn
        colCellImg = Gtk.CellRendererPixbuf(
        )  # Create a column cell to display an image
        colCellText = Gtk.CellRendererText(
        )  # Create a column cell to display text
        treeViewCol.pack_start(colCellImg,
                               expand=False)  # Add the cells to the column
        treeViewCol.pack_start(colCellText, expand=True)
        treeViewCol.add_attribute(
            colCellImg, "pixbuf",
            1)  # Bind the image cell to column 1 of the tree's model
        treeViewCol.add_attribute(
            colCellText, "text",
            2)  # Bind the text cell to column 0 of the tree's model
        w('treeview1').append_column(
            treeViewCol)  # Append the columns to the TreeView
        w('treeview1').set_expander_column(treeViewCol)
        w('treeview1').set_model(
            self.tsFiles)  # Append the columns to the TreeView
        w('treeview1').get_selection().set_select_function(
            self.treeview1_selectmethod, data=None)  # , full=True

        ## TODO: If files are specified as arguments, select these at start, and plot them at once

        ## If a directory is specified, just set it as the root of the file list. If none, use current working dir.
        self.populateTreeStore(
            self.tsFiles,
            reset_path=os.getcwd() if len(sys.argv) <= 1 else sys.argv[1])
        self.plot_reset()
        self.plot_all_sel_records()

        ## Initialize the default plotting commands
        w('txt_rc').get_buffer().set_text(line_plot_command)
        w('txt_rc').modify_font(Pango.FontDescription("monospace 10"))

        ## Add the data cursor by default  # TODO - make this work
        #cursor = Cursor(self.ax, useblit=True, color='red', linewidth=2)

        #}}}

    ## === FILE HANDLING ===
    def is_dir(self, filename):  # {{{
        try:
            return stat.S_ISDIR(os.stat(filename).st_mode)
        except FileNotFoundError:  ## this may be e.g. due to a broken symlink
            return False
        # }}}
    def row_type_from_fullpath(self, fullpath):  # {{{
        """
        Known row types:

            #Type                   row_is_leaf row_can_plot    row_icon
            dir                     0           0               ''
            updir                   1           0               'go-up'
            csvtwocolumn            1           1               ''
            csvmulticolumn          0           0               ''
            xlsfile                 0           0               ''
            xlsspread               0           0               ''
            xlscolumn               1           1               ''
            opjfile                 0           0               ''
            opjgraph                0           0               ''
            opjspread               0           0               ''
            opjcolumn               1           1               ''
            unknown                 1           0               ''
        """
        ## Note: Remaining row types not returned by this function (i.e. xlsspread, xlscolumn, opjgraph etc.) are
        ## never assigned to files; they are added only when a file or spreadsheet is unpacked and populated.
        ## The determination of file type from its name is a bit sloppy, but it works and it is fast.
        assert isinstance(fullpath, str)

        if self.is_dir(fullpath):
            return 'dir'
        elif fullpath.lower().endswith('.xls'):
            ## TODO XLS support : determine if single spreadsheet, and/or if spreadsheet(s) contain single column
            return 'xlsfile'
        elif fullpath.lower().endswith('.opj'):
            return 'opjfile'
        elif fullpath.lower().endswith('.csv') or fullpath.lower().endswith(
                '.dat') or fullpath.lower().endswith('.txt'):
            try:
                ## Note: column number is incorrectly determined if header is longer than sizehint, but 10kB should be enough
                data_array, header, parameters = robust_csv_parser.loadtxt(
                    fullpath, sizehint=SIZELIMIT_FOR_HEADER)
                print("LENHEADER", header)

                if len(header) <= 2: return 'csvtwocolumn'
                else: return 'csvmulticolumn'
            except (
                    IOError, RuntimeError
            ):  # This error is usually returned for directories and non-data files
                return 'unknown'
        else:
            return 'unknown'

        # }}}
    def rowtype_is_leaf(self, rowtype):  # {{{
        """ Determines if row shall be selected (or unpacked, otherwise)
        
        Rows representing containers (e.g. directories, multicolumn CSV files or Origin files)  
        are not "leaves", since they contain some structure that can be further unpacked. In contrast, 
        ordinary two-column CSV files or columns of CSV files are "leaves" and can be directly plotted.
        """
        return (rowtype in ('csvtwocolumn', 'csvcolumn', 'xlscolumn',
                            'opjcolumn', 'unknown'))

    # }}}
    def rowtype_can_plot(self, rowtype):  # {{{
        """ Determines if row shall be plotted """
        return (rowtype in ('csvtwocolumn', 'xlscolumn', 'opjcolumn'))

    # }}}
    def rowtype_icon(self, rowtype, iconsize=8):  # {{{
        iconname = {
            'updir': 'go-up',
            'dir': 'folder',
            'csvtwocolumn': 'empty',
            'csvmulticolumn': 'zip',
            'csvcolumn': 'empty',
            'opjfile': 'zip',
            'opjspread': 'go-next',
            'opjgraph': 'go-previous',
            'opjcolumn': 'empty',
            'xlsfile': 'zip',
            'xlsspread': 'go-next',
            'xlscolumn': 'empty',
            'unknown': 'stop'
        }
        return Gtk.IconTheme.get_default().load_icon(iconname[rowtype],
                                                     iconsize, 0)

    # }}}
    def origin_parse_or_cache(self, basepath):  # {{{
        if basepath in self.opj_file_cache.keys():
            return self.opj_file_cache[basepath]
        else:
            opj = liborigin.parseOriginFile(basepath)
            self.opj_file_cache[basepath] = opj
            return opj
        # }}}
    def decode_origin_label(self, bb, splitrows=False):  # {{{
        bb = bb.decode('utf-8', errors='ignore').replace('\r', '').strip()
        bb = bb.replace(
            '\\-', '_')  ## this is the lower index - todo: use latex notation?
        for asc, greek in zip(
                'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
                'αβγδεζηθιjκλμνοπρςστυφχξψωΑΒΓΔΕΖΗΘΙJΚΛΜΝΟΠQΡΣΤΥΦΧΞΨΩ'):
            bb = bb.replace('\\g(%s)' % asc, greek)
        if not splitrows: return bb.replace('\n', ' ')
        else: return bb.split('\n')

    # }}}
    def populateTreeStore(self,
                          treeStore,
                          parent_row=None,
                          reset_path=None):  # {{{
        ## without any parent specified, rows will be added to the very left of the TreeView,
        ## otherwise they will become childs thereof
        if parent_row is None:
            if reset_path is not None:
                basepath = reset_path
            else:
                if self.row_prop(self.tsFiles.get_iter_first(),
                                 'rowtype') == 'updir':
                    basepath = self.row_prop(self.tsFiles.get_iter_first(),
                                             'filepath')
                else:
                    raise AttributeError(
                        'Specify either parent_row, reset_path, or ensure the first row is of "updir" type'
                    )
            w('window1').set_title('PlotCommander: %s' % basepath)

            ## On startup, or when the 'updir' node is selected, we update the whole tree.
            ## Initially, it has to be cleared of all rows.
            ## During this operation, its selection will change, but the plots should not be updated so that it is fast.
            self.lockTreeViewEvents = True
            self.tsFiles.clear(
            )  ## TODO: remember the unpacked rows, and also the selected ones
            self.clearAllPlotIcons(
                self.tsFiles.get_iter_first())  ## TODO: obsolete, rm!
            self.lockTreeViewEvents = False

            ## The first node of cleared treeStore will point to the above directory, enabling one to browse whole filesystem
            plotstyleIcon = Pixbuf.new(Colorspace.RGB, True, 8, 10, 10)
            plotstyleIcon.fill(0xffffffff)
            currentIter = treeStore.append(None, [
                basepath,
                self.rowtype_icon('updir'), '..', plotstyleIcon, None, None,
                'updir'
            ])
            ## ^^ FIXME basepath? or os.path.dirname(basepath) ?
            treeStore.append(currentIter, self.dummy_treestore_row)
        elif parent_row is not None and reset_path is None:
            ## If not resetting the whole tree, get the basepath from the parent row
            basepath = treeStore.get_value(parent_row,
                                           self.treeStoreColumns['filepath'])
        else:
            raise AttributeError()

        ## Prepare the lists of paths, column numbers and spreadsheet numbers to be added
        parentrowtype = self.row_prop(parent_row,
                                      'rowtype') if parent_row else 'dir'
        assert not self.rowtype_is_leaf(parentrowtype)
        if parentrowtype == 'dir':  ## Populate a directory with files/subdirs
            ## Get the directory contents and sort it alphabetically
            filenames = os.listdir(basepath)
            filenames = sorted(filenames,
                               key=sort_alpha_numeric.split_alpha_numeric
                               )  # intelligent alpha/numerical sorting
            fileFilterString = w('enFileFilter').get_text().strip()
            itemFullNames = [
                os.path.join(basepath, filename) for filename in filenames
            ]  # add the full path
            # dirs will be listed first and files below; filter the files  ## FIXME: filter only through the file name, not full path!
            itemFullNames =  [f for f in itemFullNames if     self.is_dir(f)] + \
                    [f for f in itemFullNames if (not self.is_dir(f) and (fileFilterString == '' or re.findall(fileFilterString, f)))]
            itemShowNames = [os.path.split(f)[1] for f in itemFullNames
                             ]  # only file name without path will be shown
            columnNumbers = [None] * len(
                itemFullNames
            )  # obviously files/subdirs are assigned no column number
            spreadNumbers = [None] * len(
                itemFullNames)  # nor they are assigned any spreadsheet number
            rowTypes = [self.row_type_from_fullpath(f) for f in itemFullNames]
        elif parentrowtype == 'csvmulticolumn':
            ## Note: Multicolumn means at least 3 columns (i.e. x-column and two or more y-columns)
            data_array, header, parameters = robust_csv_parser.loadtxt(
                basepath, sizehint=10000)
            columnFilterString = w('enColFilter').get_text().strip()
            columnNumbers, header = zip(*[
                n for n in enumerate(header)
                if re.findall(columnFilterString, n[1])
            ])  ## filter the columns
            #FIXME File "/home/dominecf/p/plotcommander/plotcommander.py", line 303, in populateTreeStore
            #columnNumbers, header = zip(*[n for n in enumerate(header) if re.findall(columnFilterString, n[1])]) ## filter the columns
            #ValueError: not enough values to unpack (expected 2, got 0)
            itemFullNames = [basepath] * len(
                header)  # all columns are from one file
            itemShowNames = header  # column numbers are either in file header, or auto-generated
            spreadNumbers = [None] * len(
                header)  # there are no spreadsheets in CSV files
            rowTypes = ['csvcolumn'] * len(header)
        elif parentrowtype == 'opjfile':
            print("parentrowtype == 'opjfile':", basepath)
            opj = self.origin_parse_or_cache(basepath)

            ## Add "graphs" - which show the selected columns in presentation-ready format
            ## Fixme support for multiple opjlayers also here
            def generate_graph_annotation(graph):
                layerNumber = 0  ## Fixme support for multiple opjlayers:    ["graphs"][1].layers[0].curves[3].xColumnName
                legend_box = self.decode_origin_label(
                    graph.layers[0].legend.text, splitrows=True)
                comment = ""
                for legendline in legend_box:  ## the legend may have format as such: ['\l(1) 50B', '\l(2) 48B', ...], needs to be pre-formatted:
                    newline = re.sub(r'\\l\(\d\)\s', '', legendline)
                    if newline == legendline: comment += newline + ' '
                return comment

            itemShowNames = [
                '%s; name: %s; label: %s' % (self.decode_origin_label(
                    graph.name), self.decode_origin_label(
                        graph.label), generate_graph_annotation(graph))
                for graph in opj['graphs']
            ]
            itemFullNames = [basepath] * len(
                itemShowNames)  # all columns are from one file
            columnNumbers = [None] * len(itemShowNames)
            spreadNumbers = list(range(len(itemShowNames)))
            rowTypes = ['opjgraph'] * len(itemShowNames)

            ## Add "columns" - which enable to access all data in the file, including those not used in "graphs"
            for spread in opj['spreads']:
                print(spread.label, self.decode_origin_label(spread.label))
            itemShowNames = itemShowNames + [
                '%s "%s"' % (self.decode_origin_label(
                    spread.name), self.decode_origin_label(spread.label))
                for spread in opj['spreads']
            ]
            itemFullNames = itemFullNames + [basepath] * len(
                itemShowNames)  # all columns are from one file
            columnNumbers = columnNumbers + [None] * len(itemShowNames)
            spreadNumbers = spreadNumbers + list(range(len(itemShowNames)))
            rowTypes = rowTypes + ['opjspread'] * len(itemShowNames)
        elif parentrowtype == 'opjspread':
            opj = self.origin_parse_or_cache(basepath)
            parent_spreadsheet = self.row_prop(parent_row, 'spreadsheet')
            itemShowNames = [
                self.decode_origin_label(column.name)
                for column in opj['spreads'][parent_spreadsheet].columns
            ]
            itemFullNames = [basepath] * len(
                itemShowNames)  # all columns are from one file
            columnNumbers = list(range(len(itemShowNames)))
            spreadNumbers = [parent_spreadsheet] * len(itemShowNames)
            rowTypes = ['opjcolumn'] * len(itemShowNames)
        elif parentrowtype == 'opjgraph':
            opj = self.origin_parse_or_cache(basepath)
            parent_graph = self.row_prop(
                parent_row, 'spreadsheet'
            )  ## The key 'spreadsheet' is misused here to mean 'graph'
            layerNumber = 0  ## Fixme support for multiple opjlayers:    ["graphs"][1].layers[0].curves[3].xColumnName

            ## Try to extract meaningful legend for each curve, assuming the legend box has the same number of lines
            curves = opj['graphs'][parent_graph].layers[layerNumber].curves
            legend_box = self.decode_origin_label(
                opj['graphs'][parent_graph].layers[layerNumber].legend.text,
                splitrows=True)
            legends = []
            for legendline in legend_box:  ## the legend may have format as such: ['\l(1) 50B', '\l(2) 48B', ...], needs to be pre-formatted:
                newline = re.sub(r'\\l\(\d\)\s', '', legendline)
                if newline != legendline: legends.append(newline)
            legends = legends[:len(curves)] + (
                [''] * (len(curves) - len(legends))
            )  ## trim or extend the legends to match the curves

            itemShowNames, itemFullNames, columnNumbers, spreadNumbers = [], [], [], []
            for curve, legend in zip(curves, legends):
                ## FIXME add support for xColumn different than the first one in Spreadsheet, also here
                #print("curve t xCol yCol:", curve.dataName.self.decode_origin_label('utf-8'),
                #curve.xColumnName.self.decode_origin_label('utf-8'), curve.yColumnName.self.decode_origin_label('utf-8'))
                #print([spread.name for spread in opj['spreads']], (curve.dataName[2:]))

                ## Seek the corresponding spreadsheet and column by their name
                spreadsheet_index = [spread.name for spread in opj['spreads']
                                     ].index(curve.dataName[2:])
                spread = opj['spreads'][spreadsheet_index]
                y_column_index = [column.name for column in spread.columns
                                  ].index(curve.yColumnName)
                x_column_index = [column.name for column in spread.columns
                                  ].index(curve.xColumnName)
                #print(curve.dataName[2:].self.decode_origin_label('utf-8'), spreadsheet_index, curve.yColumnName.self.decode_origin_label('utf-8'), y_column_index)

                itemShowNames.append(
                    '%s -> spread %s: column %s (against  %s)' %
                    (legend, self.decode_origin_label(spread.name),
                     self.decode_origin_label(
                         spread.columns[y_column_index].name),
                     self.decode_origin_label(
                         spread.columns[x_column_index].name)))
                itemFullNames.append(basepath)  # all columns are from one file
                columnNumbers.append(y_column_index)
                spreadNumbers.append(spreadsheet_index)
            rowTypes = ['opjcolumn'] * len(
                itemShowNames)  ## TODO or introduce opjgraphcurve ?
        else:
            warnings.warn(
                'Not prepared yet to show listings of this file: %s' %
                parentrowtype)
            return

        ## Go through all items and populate the node
        for itemFullName, itemShowName, columnNumber, spreadNumber, rowtype in \
                zip(itemFullNames, itemShowNames, columnNumbers, spreadNumbers, rowTypes):
            plotstyleIcon = Pixbuf.new(Colorspace.RGB, True, 8, 10, 10)
            plotstyleIcon.fill(0xffffffff)
            currentIter = treeStore.append(parent_row, [
                itemFullName,
                self.rowtype_icon(rowtype), itemShowName, plotstyleIcon,
                columnNumber, spreadNumber, rowtype
            ])
            if not self.rowtype_is_leaf(
                    rowtype):  ## TODO row---> parentrowtype
                treeStore.append(
                    currentIter, self.dummy_treestore_row
                )  # shows the "unpacking arrow" left of the item
        # }}}

    ## === GRAPHICAL PRESENTATION ===
    def clearAllPlotIcons(self, treeIter):  # {{{
        while treeIter != None:
            iterpixbuf = self.row_prop(treeIter, 'plotstyleicon')
            if iterpixbuf:
                iterpixbuf.fill(self.array2rgbhex(
                    [.5, .5, 1],
                    alpha=0))  ## some nodes may have pixbuf set to None
            self.clearAllPlotIcons(self.tsFiles.iter_children(treeIter))
            treeIter = self.tsFiles.iter_next(treeIter)
        # }}}
    def array2rgbhex(self, arr3, alpha=1):  # {{{
        return  int(arr3[0]*256-.5)*(256**3) +\
                int(arr3[1]*256-.5)*(256**2) +\
                int(arr3[2]*256-.5)*(256**1) +\
                int(alpha*255  -.5)
        # }}}
    def plot_reset(self):  # {{{
        #self.ax.cla() ## TODO clearing matplotlib plot - this is inefficient, rewrite
        self.fig.clf()
        self.ax = self.fig.add_subplot(111)
        self.ax.callbacks.connect('xlim_changed', self.on_xlims_change)
        self.ax.callbacks.connect('ylim_changed', self.on_ylims_change)

        ## TODO: this may enable better handling of axes, but needs to make compatible with the object model of figure.Figure
        #        self.ax = host_subplot(111, figure=self.fig.gcf() )

        def recursive_clear_icon(treeIter):
            while treeIter != None:
                iterpixbuf = self.tsFiles.get_value(treeIter, 3)
                if iterpixbuf:
                    iterpixbuf.fill(self.array2rgbhex(
                        [.5, .5, 1],
                        alpha=0))  ## some nodes may have pixbuf set to None
                recursive_clear_icon(self.tsFiles.iter_children(treeIter))
                treeIter = self.tsFiles.iter_next(treeIter)

        recursive_clear_icon(self.tsFiles.get_iter_first())
        w('treeview1').queue_draw()
        # }}}
    def load_row_data(self, row):  # {{{
        """ loads all relevant data for a given treestore row, and returns: x, y, label, parameters, xlabel, ylabel

        Plotting is "on-the-fly", i.e., program does not store any data (except OPJ file cache) and loads them 
        from disk upon every (re)plot.
        """

        ## Load the data
        rowfilepath = self.row_prop(row, 'filepath')
        rowtype = self.row_prop(row, 'rowtype')
        rowxcolumn = 0  ## TODO allow ordinate also on >0th column
        rowycolumn = self.row_prop(row, 'column')
        rowsheet = self.row_prop(row, 'spreadsheet')
        if rowtype == 'opjcolumn':
            opj = self.origin_parse_or_cache(rowfilepath)
            # TODO: what does opj['spreads'][3].multisheet mean?
            x, y = [
                opj['spreads'][rowsheet].columns[c].data
                for c in [rowxcolumn, rowycolumn]
            ]
            if len(x) > 2 and x[-2] > x[-1] * 1e6:
                x = x[:
                      -1]  ## the last row from liborigin is sometimes erroneous zero
            if len(x) < len(y):
                y = y[0:len(
                    x)]  ## in any case, match the length of x- and y-data
            if len(y) < len(x): x = x[0:len(y)]
            try:  ## fast string-to-float conversion
                x, y = [np.array(arr) for arr in (x, y)]  ## TODO dtype=float
            except ValueError:  ## failsafe string-to-float conversion
                x0, y0 = [], []
                for x1, y1 in zip(x, y):
                    try:
                        xf, yf = float(x1), float(y1)
                        x0.append(xf)
                        y0.append(yf)
                    except ValueError:
                        pass
                x, y = x0, y0
            xlabel, ylabel = [
                self.decode_origin_label(
                    opj['spreads'][rowsheet].columns[c].name)
                for c in [rowxcolumn, rowycolumn]
            ]
            parameters = {
            }  ## todo: is it possible to load parameters from origin column?
            return x, y, ylabel, parameters, xlabel, ylabel
        elif rowtype == 'csvtwocolumn':
            ycolumn = 1
            data_array, header, parameters = robust_csv_parser.loadtxt(
                rowfilepath, sizehint=SIZELIMIT_FOR_DATA)
            print()
            print()
            print()
            print(data_array, len(header), header)
            if len(header) == 1:
                data_array = np.vstack(
                    [np.arange(len(data_array)), data_array.T]).T
                header = ['point number'] + header
            print(data_array, len(header), header)
            print()
            print()
            print()
            return data_array.T[0], data_array.T[1], os.path.split(rowfilepath)[1][:-4], parameters, \
                    header[0], header[1] ## LINES NAMED BY THEIR FILE NAME ##TODO make it automatic
            #return  data_array.T[0], data_array.T[1], os.path.split(os.path.split(rowfilepath)[0])[1], parameters, header[0], header[1] ## TODO
            ## TODO replace os.path.split(rowfile)[-2] with a parameter reasonably recovered from the file name
        elif rowtype == 'csvcolumn':
            data_array, header, parameters = robust_csv_parser.loadtxt(
                rowfilepath, sizehint=SIZELIMIT_FOR_DATA)
            return data_array.T[rowxcolumn], data_array.T[rowycolumn], rowfilepath, parameters, \
                    header[rowxcolumn], header[rowycolumn] ## LINES NAMED BY THEIR FILE NAME ##TODO make it automatic
            #return data_array.T[rowxcolumn], data_array.T[rowycolumn], os.path.split(os.path.split(rowfilepath)[0])[1], parameters, \
            #header[rowxcolumn], header[rowycolumn] ## LINES NAMED BY THEIR FILE DIRECTORY

        #elif rowtype == 'xls':
        # TODO a XLS file is a *container* with multiple sheets, a sheet may contain multiple columns
        #return
        #xl = pd.ExcelFile(infile, header=1) ##
        #print(xl.sheet_names)
        #print(xl.sheets[rowsheet])
        #df = xl.parse()
        #x, y, xlabel, ylabel = df.values.T[rowxcolumn], df.values.T[rowycolumn], header[rowxcolumn], header[rowycolumn]
        ## TODO Should offer choice of columns ## FIXME clash with 'header'!!
        else:
            raise RuntimeError  ## for all remaining filetypes, abort plotting quietly

# }}}

    def plot_all_sel_records(self):  # {{{

        ## Setting persistent view is somewhat kafkaesque with matplotlib.
        ## self.xlim        remembers the correct view from the last GUI resize , but
        ## ax.get_xlim      from the start of this method returns the wrong (autoscaled) limits, why?
        if not w('chk_autoscale_x').get_active() and self.xlim:
            self.ax.set_xlim(self.xlim)
        if not w('chk_autoscale_y').get_active() and self.ylim:
            self.ax.set_ylim(self.ylim)

        ## Load all row data
        (model, pathlist) = w('treeview1').get_selection().get_selected_rows()
        if len(pathlist) == 0: return
        error_counter = 0
        row_data = []
        row_labels = []
        plotted_paths = []
        for path in pathlist:
            try:
                row_data.append(self.load_row_data(
                    self.tsFiles.get_iter(path)))
                plotted_paths.append(path)
            except (RuntimeError, ValueError):
                traceback.print_exc()
                error_counter += 1
        w('statusbar1').push(
            0, ('%d records loaded' % len(pathlist)) +
            ('with %d errors' % error_counter) if error_counter else '')
        if row_data == []: return False
        xs, ys, labels, params, xlabels, ylabels = zip(*row_data)
        #for n,v in zip('xs, ys, labels, params, xlabels, ylabels'.split(), [xs, ys, labels, params, xlabels, ylabels]):
        #print(n,v)
        ## TODO: check if there is exactly one column in the 'params' table that differs among files:       label="%s=%s" % (labelkey, labelval)
        ## If it is, append its name and value to the respective 'labels' field, so that all plotted lines are distinguishable by this value!
        ## If there is none, or too many, the curves will be labeled just by their column label found in the header.
        ## TODO allow also to name the curves by the file name, if the column names do not exist or are all the same!

        ## Generate the color palette for curves
        color_pre_map = np.linspace(0.05, .95, len(plotted_paths) + 1)[:-1]
        colors = matplotlib.cm.gist_rainbow(
            color_pre_map * .5 + np.sin(color_pre_map * np.pi / 2)**2 * .5)
        for path, color_from_palette in zip(plotted_paths, colors):
            ## If no exception occured during loading, colour the icon according to the line colour
            icon = self.row_prop(self.tsFiles.get_iter(path), 'plotstyleicon')
            if icon: icon.fill(self.array2rgbhex(color_from_palette))
            plotted_paths.append(path)

        ## TODO: decide what is the distinguishing parameter for the given set of rows ---> <str> labelkey, <labelvals
        # 1) (almost) all curves should have it defined
        # 2) it should differ among (almost) all curves
        # 3) it may be in the params dict, or in the filename (for csvtwocolumn), or in the header of csvcolumn, opjcolumn etc.

        #print("self.ax.axis", self.ax.axis())
        ## Plot all curves sequentially
        plot_cmd_buffer = w('txt_rc').get_buffer()
        plot_command = plot_cmd_buffer.get_text(
            plot_cmd_buffer.get_start_iter(),
            plot_cmd_buffer.get_end_iter(),
            include_hidden_chars=True)
        #print("BEFORE COMMAND")
        #print(row_data)
        if plot_command.strip() != '':
            #np = numpy
            def dedup(l):
                return list(
                    dict.fromkeys(l[::-1])
                )[::
                  -1]  ## deduplicates items, preserves order of first occurence

            exec_env = {
                'np': np,
                'sc': sc,
                'matplotlib': matplotlib,
                'cm': matplotlib.cm,
                'ax': self.ax,
                'fig': self.fig,
                'xs': np.array(xs),
                'ys': np.array(ys),
                'labels': labels,
                'params': np.array(params),
                'xlabels': xlabels,
                'ylabels': ylabels,
                'xlabelsdedup': ', '.join(dedup(xlabels))[:100],
                'ylabelsdedup': ', '.join(dedup(ylabels))[:100],
                'colors': colors
            }
            #self.fig.clf() ## clear figure
            try:
                exec(plot_command, exec_env)
                #print("JUST AFTER COMMAND")
            except SyntaxError:
                #print("SYNTAX ERROR:")
                traceback.print_exc()  ## TODO locate the error
            except:
                #print("SOME ERROR")
                traceback.print_exc()  ## TODO locate the error
        #print("AFTER COMMAND")
        #code = compile(plot_command, "somefile.py", 'exec') TODO
        #exec(code, global_vars, local_vars)
        #else:
        #plot_command = default_plot_command
        #plot_cmd_buffer.set_text(default_plot_command)

        cursor = Cursor(
            self.ax, color='red', linewidth=.5
        )  ## , useblit=True   .. fixme: useblit made the cursor disappear
        # Note: blit cannot be used: AttributeError: 'FigureCanvasGTK3Cairo' object has no attribute 'copy_from_bbox'

        #self.ax.legend(loc="best")
        self.ax.grid(True)
        self.ax.set_xscale(
            'log' if w('chk_xlogarithmic').get_active() else 'linear')  ##XXX
        self.ax.set_yscale(
            'log' if w('chk_ylogarithmic').get_active() else 'linear')  ##XXX

        self.ax.relim()
        self.ax.autoscale_view(
        )  # 	Autoscale the view limits using the data limits.
        self.canvas.draw()
        return True

        # }}}
    def on_xlims_change(self, axes):
        self.xlim = axes.get_xlim()  ## dirty hack: Needs fixing in the future

    def on_ylims_change(self, axes):
        self.ylim = axes.get_ylim()  ## dtto

    ## == FILE AND DATA UTILITIES ==
    def row_prop(self, row, prop):  # {{{
        return self.tsFiles.get_value(row, self.treeStoreColumns[prop])
        # }}}
    def remember_treeView_expanded_rows(self, treeStore, treeView):  # {{{
        ## returns a list of paths of expanded files/directories
        expanded_row_names = []

        def remember_treeview_states(treeIter):
            while treeIter != None:
                if w('treeview1').row_expanded(treeStore.get_path(treeIter)):
                    expanded_row_names.append(treeStore.get_value(
                        treeIter, 0))  # get the full path of the position
                remember_treeview_states(treeStore.iter_children(treeIter))
                treeIter = treeStore.iter_next(treeIter)

        remember_treeview_states(treeStore.get_iter_first())
        return expanded_row_names
        # }}}
    def remember_treeView_selected_rows(self, treeStore, treeView):  # {{{
        ## returns a list of paths of selected files/directories
        (model,
         selectedPathList) = treeView.get_selection().get_selected_rows()
        selected_row_names = []
        for treePath in selectedPathList:
            selected_row_names.append(
                treeStore.get_value(treeStore.get_iter(treePath), 0))
        return selected_row_names
        # }}}
    def restore_treeView_expanded_rows(self, expanded_row_names):  # {{{
        def recursive_expand_rows(treeIter, ):
            while treeIter != None:
                if self.tsFiles.get_value(treeIter, 0) in expanded_row_names:
                    self.lockTreeViewEvents = True
                    w('treeview1').expand_row(self.tsFiles.get_path(treeIter),
                                              open_all=False)
                    self.lockTreeViewEvents = False
                recursive_expand_rows(self.tsFiles.iter_children(treeIter))
                treeIter = self.tsFiles.iter_next(treeIter)

        recursive_expand_rows(self.tsFiles.get_iter_first())
        # }}}
    def restore_treeView_selected_rows(self, selected_row_names):  # {{{
        def recursive_select_rows(treeIter):
            while treeIter != None:
                if self.tsFiles.get_value(treeIter, 0) in selected_row_names:
                    self.lockTreeViewEvents = True
                    w('treeview1').get_selection().select_path(
                        self.tsFiles.get_path(treeIter))
                    self.lockTreeViewEvents = False
                recursive_select_rows(self.tsFiles.iter_children(treeIter))
                treeIter = self.tsFiles.iter_next(treeIter)

        recursive_select_rows(self.tsFiles.get_iter_first())
        self.plot_all_sel_records()
        # }}}

    ## == USER INTERFACE HANDLERS ==
    def possible_rc_filenames(self):
        (model, pathlist) = w('treeview1').get_selection().get_selected_rows()
        if pathlist:
            firstselfilenamepath = self.row_prop(
                self.tsFiles.get_iter(pathlist[0]), 'filepath')
            firstselfilepath, firstselfilename = os.path.dirname(
                firstselfilenamepath), os.path.basename(firstselfilenamepath)
            testrcfilenamepath1 = os.path.join(
                firstselfilepath, 'plotrc_%s.py' % firstselfilename)
            testrcfilenamepath2 = os.path.join(firstselfilepath, 'plotrc.py')
            return (testrcfilenamepath1, testrcfilenamepath2)
        else:
            return None

    def relevant_rc_filename(self):
        prf = self.possible_rc_filenames()
        if prf:
            rc_filename = prf[0] if os.path.isfile(
                prf[0]) else prf[1] if os.path.isfile(prf[1]) else None
            return rc_filename
        else:
            return None

    def load_plotcommand_from_rcfile(self):
        rc_filename = self.relevant_rc_filename()
        if rc_filename:
            with open(rc_filename) as rcfile:
                return rcfile.read()
        else:
            return ''

    def update_plotcommand_from_rcfile(self, allow_overwrite_by_empty=True):
        plotcommand = self.load_plotcommand_from_rcfile()
        if plotcommand or allow_overwrite_by_empty:
            w('txt_rc').get_buffer().set_text(plotcommand)

    def plotcommand_get_text(self):
        buf = w('txt_rc').get_buffer()
        return buf.get_text(buf.get_start_iter(),
                            buf.get_end_iter(),
                            include_hidden_chars=True)

    def plotcommand_set_text(self, text):
        buf = w('txt_rc').get_buffer()
        buf.set_text(text)

    def on_plotcommand_toggled(self, *args):  # {{{
        radiobutton = args[0]

        w('chk_xlogarithmic').set_active(False)
        if radiobutton is w('rad_plotstyle_rc'):
            if radiobutton.get_active():  ## selecting action
                self.update_plotcommand_from_rcfile()
            else:
                pass  ## todo - ask whether to save the command file, if changed
        else:
            if radiobutton.get_active():  ## selecting action
                self.plotcommand_set_text(
                    plot_commands[radiobutton.get_label().strip()])
            else:  ## deselecting action
                plot_commands[radiobutton.get_label().strip(
                )] = self.plotcommand_get_text()

        if radiobutton.get_active():  ## selecting action
            ## Update the graphical presentation
            self.plot_reset(
            )  ## first delete the curves, to hide (also) unselected plots
            self.plot_all_sel_records()  ## then show the selected ones

    # }}}
    def on_btn_plotrc_save_clicked(self, *args):  # {{{
        rc_filename = self.relevant_rc_filename(
        ) or self.possible_rc_filenames()[0]
        with open(rc_filename, 'w') as rcfile:
            rcfile.write(self.plotcommand_get_text())

    # }}}
    """
    if radio changes to some defaultcommand
                    ---> change to selected command
    if radio changes to rcfile
        if relevant rcfile exists
                    ---> change to selected command ( LOAD rcfile command)
                    ---> then REPLOT
        if rcfile does not exist
                    ---> EMPTy txtbox 
        if nothing selected
                    ---> EMPTy txtbox 
    if selection changes 
        if relevant rcfile exists   
                    ---> CHANGE radio TO RCFILE
                    ---> change to selected command ( LOAD rcfile command) (automatic event handler?)
        if rcfile does not exist
                    ---> CHANGE radio TO DEFAULT
        if nothing selected
                    --->

    ---> then always REPLOT
        
    """

    def on_treeview1_row_expanded(self, treeView, treeIter, treePath):  # {{{

        ## Add the children
        treeStore = treeView.get_model()
        newFilePath = treeStore.get_value(
            treeIter, 0)  # get the full path of the position
        self.populateTreeStore(treeStore, parent_row=treeIter)

        ## The dummy row has to be removed AFTER this, otherwise the empty treeView row will NOT expand)
        if treeStore.iter_children(treeIter):
            treeStore.remove(treeStore.iter_children(treeIter))

    #}}}
    def on_treeview1_row_collapsed(self, treeView, treeIter, treePath):  # {{{
        ## Remove all child nodes of the given row (useful mostly to prevent de-syncing from some changes in the filesystem)
        #if self.lockTreeViewEvents: return      ## prevent event handlers triggering other events
        currentChildIter = self.tsFiles.iter_children(treeIter)
        while currentChildIter:
            self.tsFiles.remove(currentChildIter)
            currentChildIter = self.tsFiles.iter_children(treeIter)
        self.tsFiles.append(treeIter, self.dummy_treestore_row)

    # }}}
    def on_treeview1_selection_changed(self,
                                       *args):  # {{{       ## triggers replot
        if self.lockTreeViewEvents:
            return  ## prevent event handlers triggering other events

        ## Update the plot command
        if w('rad_plotstyle_rc').get_active():
            ## TODO if it does not exist
            self.update_plotcommand_from_rcfile(allow_overwrite_by_empty=False)
        elif self.relevant_rc_filename():
            w('rad_plotstyle_rc').set_active(True)

        ## Update the graphical presentation
        self.plot_reset(
        )  ## first delete the curves, to hide (also) unselected plots
        self.plot_all_sel_records()  ## then show the selected ones

    # }}}
    def treeview1_selectmethod(self, selection, model, treePath, is_selected,
                               user_data):  # {{{
        ## TODO reasonable behaviour for block-selection over different unpacked directories/files
        ## Expand a directory by clicking, but do not allow user to select it
        treeIter = self.tsFiles.get_iter(treePath)
        #self.treeStoreColumns=      {'filepath':0, 'icon':1, 'name':2, 'plotstyleicon':3, 'column':4, 'spreadsheet':5, 'rowtype':6}

        if self.lockTreeViewEvents:
            return  ## during folding, prevent triggering 'on_select' events on all node children
        #lockTreeViewEvents_tmp = self.lockTreeViewEvents       ## TODO understand and clear out when select events can occur
        #self.lockTreeViewEvents = True
        # ...
        #self.lockTreeViewEvents = lockTreeViewEvents_tmp

        ## Clicking action of non-leaf un-selectable rows:
        rowtype = self.tsFiles.get_value(treeIter,
                                         self.treeStoreColumns['rowtype'])
        if self.rowtype_is_leaf(rowtype):
            return True  ## allow selecting or unselecting
        else:
            if rowtype == "updir":
                ## If the expanded row was "..", do not expand it, instead change to up-dir and refresh whole tree
                expanded_row_names = self.remember_treeView_expanded_rows(
                    self.tsFiles, w('treeview1'))
                selected_row_names = self.remember_treeView_selected_rows(
                    self.tsFiles, w('treeview1'))
                self.populateTreeStore(self.tsFiles,
                                       reset_path=os.path.dirname(
                                           self.row_prop(treeIter,
                                                         'filepath')))
            elif w('treeview1').row_expanded(treePath):
                w('treeview1').collapse_row(treePath)
            elif not w('treeview1').row_expanded(treePath):
                w('treeview1').expand_row(treePath, open_all=False)
            return False

# }}}

    def on_enFileFilter_activate(self, *args):  # {{{
        expanded_row_names = self.remember_treeView_expanded_rows(
            self.tsFiles, w('treeview1'))
        selected_row_names = self.remember_treeView_selected_rows(
            self.tsFiles, w('treeview1'))
        # Passing parent=None will populate the whole tree again
        #self.lockTreeViewEvents = True
        self.populateTreeStore(self.tsFiles, reset_path=None)
        #self.lockTreeViewEvents = False
        self.restore_treeView_expanded_rows(expanded_row_names)
        self.restore_treeView_selected_rows(selected_row_names)
        # }}}
    def on_enFileFilter_focus_out_event(self, *args):  # {{{
        self.on_enFileFilter_activate(self)

    # }}}
    def on_enColFilter_activate(self, *args):  # {{{ TODO
        pass

    def on_enColFilter_focus_out_event(self, *args):
        pass


# }}}

    def on_window1_delete_event(self, *args):  # {{{
        Gtk.main_quit(*args)  # }}}
コード例 #13
0
ファイル: echellorama.py プロジェクト: cpiehl/CHESS_pipeline
class MyWindow(Gtk.Window):

	@timing
	def __init__(self):
		Gtk.Window.__init__(self, title="Echelle Reduction GUI")

		self.set_default_size(1000, 800)
		self.figure = Figure(figsize=(5,7), dpi=100)
		self.plot_1D = self.figure.add_subplot(212)
		self.plot_2D = self.figure.add_subplot(232)
		self.plot_PHD = self.figure.add_subplot(231)
		self.plot_orders = self.figure.add_subplot(233)
		self.plot_orders.tick_params(axis='both', labelsize=6)
		self.plot_orders.set_title("Orders")
		self.plot_2D.tick_params(axis='both', labelsize=7)
		self.plot_2D.set_title("2D Raw Data")
		self.plot_1D.set_title("1D Extracted Data")
		self.plot_1D.set_xlabel('pixels')
		self.plot_1D.set_ylabel('intensity')
		self.plot_1D.tick_params(axis='both', labelsize=7)
		self.plot_PHD.set_title('Pulse Height Data')
		self.plot_PHD.tick_params(axis='both', labelsize=7)

		self.canvas = FigureCanvas(self.figure)

		menubar = Gtk.MenuBar()

		menubar_file = Gtk.MenuItem("File")
		filemenu = Gtk.Menu()
		menubar_file.set_submenu(filemenu)
		menubar.append(menubar_file)

		filemenu_open = Gtk.MenuItem("Open")
		filemenu_open.connect('activate', self.open_file_dialog)
		filemenu.append(filemenu_open)

		filemenu.append(Gtk.SeparatorMenuItem())

		filemenu_save = Gtk.MenuItem("Save Orders")
		filemenu_save.connect('activate', self.on_filemenu_save_clicked)
		filemenu.append(filemenu_save)

		filemenu_load = Gtk.MenuItem("Load Orders")
		filemenu_load.connect('activate', self.on_filemenu_load_clicked)
		filemenu.append(filemenu_load)

		filemenu.append(Gtk.SeparatorMenuItem())

		filemenu_exit = Gtk.MenuItem('Exit')
		filemenu_exit.connect('activate', Gtk.main_quit)
		filemenu.append(filemenu_exit)

		menubox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
		menubox.pack_start(menubar, False, False, 0)

		toolbar = NavigationToolbar(self.canvas, self)
		main_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
		self.add(main_box)

		self.statusbar = Gtk.Statusbar()
		self.context_id = self.statusbar.get_context_id("stat bar example")
		self.statusbar.push(0, 'Please Open 2D Fits Data File')

		hbutton_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
		self.count_rate_button = Gtk.ToggleButton(label='Raw count rate')
		self.count_rate_button.connect("toggled", self.on_count_rate_button_clicked, self.context_id)
		self.filter_phd_button = Gtk.Button('Filter PHD')
		self.filter_phd_button.connect("clicked", self.on_filter_phd_button_clicked, self.context_id)
		self.gauss_fit_button = Gtk.ToggleButton(label='Fit 1D Gauss')
		self.gauss_fit_button.set_active(False)
		self.gauss_fit_button.connect("toggled", self.on_gauss_fit_button_clicked, self.context_id)
		self.remove_orders_button = Gtk.ToggleButton(label='Remove Orders')
		self.remove_orders_button.connect("toggled", self.on_remove_orders_button_clicked, self.context_id)
		self.add_orders_button = Gtk.ToggleButton(label='Add Orders')
		self.add_orders_button.connect("toggled", self.on_add_orders_button_clicked, self.context_id)
		self.buttonbg = Gtk.Button('Airglow')
		self.buttonbg.connect('clicked', self.buttonbg_clicked, self.context_id)
		self.recalculate_button = Gtk.Button('Recalculate')
		self.recalculate_button.connect('clicked', self.on_recalculate_button_clicked, self.context_id)

		hbutton_box.pack_start(self.count_rate_button, True, True, 0)
		hbutton_box.pack_start(self.filter_phd_button, True, True, 0)
		hbutton_box.pack_start(self.gauss_fit_button, True, True, 0)
		hbutton_box.pack_start(self.remove_orders_button, True, True, 0)
		hbutton_box.pack_start(self.add_orders_button, True, True, 0)
		hbutton_box.pack_start(self.buttonbg, True, True, 0)
		hbutton_box.pack_start(self.recalculate_button, True, True, 0)

		main_box.pack_start(menubox, False, False, 0)
		main_box.pack_start(toolbar, False, False, 0)
		main_box.pack_start(self.canvas, True, True, 0)
		main_box.pack_start(hbutton_box, False, False, 0)
		main_box.pack_start(self.statusbar, False, False, 0)

		#~ self.filename = './2014-03-14-185937.fits'
		#~ self.open_file(self.filename)

	@timing
	def open_file_dialog(self, widget):
		dialog = Gtk.FileChooserDialog(
			"Please Choose a File",
			self,
			Gtk.FileChooserAction.OPEN,
			(	Gtk.STOCK_CANCEL,
				Gtk.ResponseType.CANCEL,
				Gtk.STOCK_OPEN,
				Gtk.ResponseType.OK ) )
		dialog.set_default_response(Gtk.ResponseType.OK)
		filter = Gtk.FileFilter()
		filter.set_name('fits Files')
		filter.add_mime_type('fits')
		filter.add_pattern('*.fits')
		dialog.add_filter(filter)

		response = dialog.run()

		if response == Gtk.ResponseType.OK :
			self.filename = dialog.get_filename()
			self.statusbar.push(0, 'Opened File: ' + self.filename)
			dialog.destroy()
			del dialog
			self.open_file(self.filename)

		elif response == Gtk.ResponseType.CANCEL:
			dialog.destroy()
			del dialog


	@timing
	def open_file(self, filename):
		hdulist = fits.open(filename)
		self.photon_list = hdulist[1].data
		hdulist.close()

		 # Init for new file
		self.orders = []
		self.science(self.photon_list)


	@timing
	def science(self, photon_list, min_phd=0, max_phd=255, orders=[]):
		self.recalculate_button.set_sensitive(False)
		self.min_phd = min_phd
		self.max_phd = max_phd
		PHD = np.array(photon_list['PHD'])
		photon_list_filtered = photon_list[(PHD >= min_phd) & (PHD <= max_phd)]
		image, xedges, yedges = np.histogram2d(photon_list_filtered['X'], photon_list_filtered['Y'], bins=2048, range=[[0,8192],[0,8192]])
		self.update_2D_plot(image)

	# Collapse 2D data into 1D to view orders as peaks
		peaks = []
		for i in range(0, len(image[0])):
			# sums ith row
			peaks.append(np.sum(image[i,:]))

	# Smooth peaks by convolving with a boxcar
		boxcar = np.zeros(300)
		boxcar[125:175] = 1.0
		smooth = np.convolve(peaks, boxcar, mode='same')
		#~ self.peaks_smoothed = peaks / smooth
		self.peaks_smoothed = (peaks/max(peaks)) - (smooth/max(smooth)/2)

	# Only find orders if there are no orders yet, eg. first run
		if not self.orders and not orders:
			print 'Finding peaks...'
			# Requires scipy version .11.0 or greater
			self.orders = signal.find_peaks_cwt(self.peaks_smoothed, np.arange(10, 20))
		elif orders:
			print 'Using premade peaks list...'
			self.orders = orders

	# Plot 1D data with lines through the centers of the
	# orders to double check how the peak finder did
		self.update_orders_plot(self.peaks_smoothed, self.orders)

	#
		self.update_PHD_plot(PHD, min_phd, max_phd)

		self.dragbox = []

	### extraction of orders ###
	# find the widths of the orders (difference between peaks)
		peak_widths = []
		for i in range(1, len(self.orders)):
			peak_widths.append(self.orders[i] - self.orders[i - 1])

	# Double last entry to make peak_widths the right length
		peak_widths.append(peak_widths[-1])


	# Add up spectrum lines from 2D plot where y coord is an order +/-FWHM
	# Remember, peak_widths[0] is orders[1]-orders[0].
		FWHM = 0.63 # full width half max
		spectrum = []
		for i in range(len(self.orders)):
			peak = int(self.orders[i])
			#~ width = int(peak_widths[i]*FWHM)
			width = 1
			for j in range(0, width):
				# Find chord length of circular image
				r = len(image[0])/2
				start = int(r - (peak * (2*r - peak))**0.5)
				end = int(2 * r - start)
				for k in range(start, end):
					spectrum.append(image[peak-width/2+j][k])

		self.update_1D_plot(spectrum)

		self.statusbar.push(0, 'Done! ' + self.filename)

	@timing
	def update_2D_plot(self, image):
		self.plot_2D.cla()
		self.plot_2D.tick_params(axis='both', labelsize=7)
		self.plot_2D.set_title("2D Raw Data")
		max = np.amax(image)

		self.plot_2D.imshow(image, norm=LogNorm(vmin=0.1, vmax=max/2), origin='lower')
		self.canvas.draw()

	@timing
	def update_orders_plot(self, peaks, orders):
		self.plot_orders.cla()
		self.plot_orders_line, = self.plot_orders.plot([],[])
		self.plot_orders.tick_params(axis='both', labelsize=6)
		self.plot_orders.set_title("Orders")

		self.plot_orders_line.set_xdata(peaks)
		self.plot_orders_line.set_ydata(np.arange(len(peaks)))
		self.plot_orders.hlines(orders, min(peaks), max(peaks), color='purple')

		self.plot_orders.relim()
		self.plot_orders.autoscale_view(True, True, True)

		self.canvas.draw()


	# Seems a max of 18980 x values are supported by Cairo.  Since
	# we have more than the max we have to reduce the spectrum
	# resolution to fit.
	# Maybe do this dynamically based on xlim()?
	# xmin, xmax = xlim()   # return the current xlim
	@timing
	def update_1D_plot(self, spectrum):
		self.plot_1D.cla()
		self.plot_1D_line, = self.plot_1D.plot([],[])
		self.plot_1D.set_title("1D Extracted Data")
		self.plot_1D.set_xlabel('pixels')
		self.plot_1D.set_ylabel('intensity')
		self.plot_1D.tick_params(axis='both', labelsize=7)

		MAX = 18980 #16384 # 2^14
		scale = int(len(spectrum)/MAX) + 1

		print len(spectrum), scale, len(spectrum)/scale

		# When we get wavelength calibration, change this line to
		#~ x = np.linspace(minWL, maxWL, num = len(spectrum)/scale)
		x = np.arange(0, len(spectrum), scale)
		spectrum = [np.sum(spectrum[i:i+scale]) for i in x]

		self.plot_1D_line.set_xdata(x)
		self.plot_1D_line.set_ydata(spectrum)
		self.plot_1D.relim()
		self.plot_1D.autoscale_view(True, True, True)
		self.canvas.draw()


	@timing
	def update_PHD_plot(self, PHD, min_phd, max_phd):
		self.plot_PHD.cla()
		self.plot_PHD.set_title('Pulse Height Data')
		self.plot_PHD.tick_params(axis='both', labelsize=7)
		self.plot_PHD.axvline(x=min_phd, color='purple')
		self.plot_PHD.axvline(x=max_phd, color='purple')
		self.plot_PHD.hist(PHD, bins=256, range=[0,255], histtype='stepfilled')
		self.plot_PHD.relim()
		self.plot_PHD.autoscale_view(True, True, True)
		self.canvas.draw()


## airglow button ##
	def buttonbg_clicked(self, widget, data):
		dialog = Gtk.FileChooserDialog("Please Choose Airglow File", self,
			Gtk.FileChooserAction.OPEN,
			(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
			 Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
		dialog.set_default_response(Gtk.ResponseType.OK)
		filter = Gtk.FileFilter()
		filter.set_name('fits Files')
		filter.add_mime_type('fits')
		filter.add_pattern('*.fits')
		dialog.add_filter(filter)

		response = dialog.run()

		if response == Gtk.ResponseType.OK:
			self.airglow_filename = dialog.get_filename()
			#~ global _AirglowFile
			#~ _AirglowFile = fname
			#print "open file" + fname
			#self.statusbar.push(0,'Opened File:' + fname)
			dialog.destroy()
			self.open_airglow_file(self.airglow_filename)
		elif response == Gtk.ResponseType.CANCEL:
			dialog.destroy()

# opening a‏iglow fits file
	def open_airglow_file(self, airglow_filename):
		#this opens up the fits file
		hdulist = fits.open(airglow_filename)

	## this line will need to be used for real data
		targname = hdulist[0].header['targname']
		#targname = self.targname

	## but for now
		#~ targname = 'HD128627J'

	#  this picks out the actual data from fits file, and turns it into numpy array
		self.glowdata = hdulist[0].data
		hdulist.close()
	# simple subtraction of aurglow image from science image
		scidata = self.scidata - self.glowdata
		self.science(scidata, targname)

## gauss fitting button
	def on_gauss_fit_button_clicked(self, widget, data):

		self.statusbar.push(data,'Ready to fit.  Click on both sides of the emission feature you wish to fit')
		self.xdata = []
		def onclick(event):
			if self.gauss_fit_button.get_active():
				self.xdata.append(event.xdata)
				self.statusbar.push(data, 'one more click...')
				if len(self.xdata) == 2:
					self.statusbar.push(data, 'Ready to fit.  Click on both sides of the emission feature you wish to fit')
					xdata = self.xdata
					self.gauss_fit(xdata)

		#  mouse click event on 1d
		cid = self.canvas.mpl_connect('button_press_event', onclick)
		if [self.gauss_fit_button.get_active()] == [False]:
			self.statusbar.push(0, 'Opened File:' + File)


### gauss fitting ###
	def gauss_fit(self, xdata):

		x = list(self.x)
		xg = []
		xg.append(int(xdata[0]))
		xg.append(int(xdata[1]))
		xg1 = min(xg)
		xg2 = max(xg)
		xgauss = x[xg1:xg2]
		ygauss = self.odo[xg1:xg2]
		right = ygauss[len(xgauss)-4:len(xgauss)]
		left = ygauss[0:4]

	# background subtraction
		averight = sum(right) / len(right)
		aveleft = sum(left) / len(left)
		bg_y = [averight, aveleft]
		rightx = xgauss[len(xgauss)-4:len(xgauss)]
		leftx = xgauss[0:4]
		averightx = sum(rightx) / len(rightx)
		aveleftx = sum(leftx) / len(leftx)
		bg_x = [averightx, aveleftx]

		m,b = np.polyfit(bg_x, bg_y, 1)
		slopex = [i * m for i in xgauss]
		bg_fit = slopex + b



		# making a model gauss
		def gauss(xgauss, MAX, mu, sigma):
			return MAX * np.exp(-(xgauss - mu)**2 / (2.0 * sigma**2))

		avex = sum(xgauss) / len(xgauss)
		guess = [1.0, avex, 1.0]

		# plugging in model to matplotlibs curve_fit()
		coeff, var_matrix = curve_fit(gauss, xgauss, ygauss-bg_fit, p0=guess)
		fit = gauss(xgauss, *coeff)
		sigma = coeff[2]
		FWHM = sigma * 2 * np.sqrt(2 * np.log(2))
		FWHM = round(FWHM, 2)
		fitplot = plt.plot(xgauss, ygauss, color='k')
		plt.plot(xgauss, fit + bg_fit, color='b', linewidth=1.5)
		xpos = xgauss[0] + 0.01 * (coeff[1] - xgauss[0])
		strFWHM = str(FWHM)
		plt.text(xpos, 0.9 * max(ygauss), 'FWHM = ' + strFWHM + '', color='purple', fontweight='bold')

		center = str(round(coeff[1], 2))
		plt.text(xpos, 0.95 * max(ygauss), 'Center = ' + center + '', color='green', fontweight='bold')
		plt.plot(xgauss, bg_fit, 'r--')

		plt.show()
		self.xdata = []


	### count rate button
	def on_count_rate_button_clicked(self, widget, data):
		if self.count_rate_button.get_active():
		   self.statusbar.push(data,'Use zoom feature in navigation bar to select count rate region')
		else:
		   self.statusbar.push(0, 'Opened File:' + self.filename)

		dragbox = []

		def onclick(event):
			if self.count_rate_button.get_active():
				dragbox.append(event.xdata)
				dragbox.append(event.ydata)


		def offclick(event):
			if self.count_rate_button.get_active():
				dragbox.append(event.xdata)
				dragbox.append(event.ydata)
				self.count_rate(dragbox, data)


		self.canvas.mpl_connect('button_press_event', onclick)
		self.canvas.mpl_connect('button_release_event', offclick)


	def count_rate(self, dragbox, data):
		# fake exposure time in seconds
		datafake = './chesstest.fits'
		hdu = fits.open(datafake)
		exptime = hdu[0].header['EXPOSURE']
		dragbox = [int(x) for x in dragbox]
		cntbox = self.scidata[ dragbox[0]:dragbox[2], 1024-dragbox[1]:1024-dragbox[3] ]
		totpix = np.size(cntbox)
		cntrate = np.sum(cntbox) / exptime
		totpix = str(totpix)
		cntrate = str(cntrate)
		self.statusbar.push(data, 'count rate in box = ' + cntrate + ' cnt/sec,    pixels in box = ' + totpix + '')
		return cntrate


	@timing
	def on_filter_phd_button_clicked(self, widget, data):
		self.phd_window = Gtk.MessageDialog(image = None)
		self.phd_window.set_size_request(500, 100)
		self.phd_window.move(400, 300)
		#self.phd_window.connect("delet_event",lambda w,e:)
		#~ self.phd_window.connect("delete-event", self.phd_window.destroy)

		mainbox = self.phd_window.get_content_area()
		thebox = Gtk.HBox(False, 0)

		label = Gtk.Label("Keep PHD between")
		label2 = Gtk.Label('and')

		label.show()
		label2.show()

		self.ok_button = Gtk.Button('Okay')
		self.ok_button.connect('clicked', self.phd_entry_button_clicked)
		self.min_phd_entry = Gtk.Entry()
		self.min_phd_entry.set_activates_default(True)
		self.max_phd_entry = Gtk.Entry()
		#~ self.max_phd_entry.set_activates_default(True)

		self.min_phd_entry.show()
		self.max_phd_entry.show()
		self.ok_button.show()

		thebox.pack_start(label,False,False,0)
		thebox.pack_start(self.min_phd_entry,False,False,0)

		thebox.pack_start(label2,False,False,0)
		thebox.pack_start(self.max_phd_entry,False,False,0)
		mainbox.pack_start(thebox,True,True,0)
		mainbox.pack_start(self.ok_button,True,False,0)

		mainbox.show()
		thebox.show()
		self.phd_window.show()

	@timing
	def phd_entry_button_clicked(self, widget):
		min_phd = int(self.min_phd_entry.get_text())
		max_phd = int(self.max_phd_entry.get_text())
		self.phd_window.destroy()
		self.statusbar.push(0, 'Filtering by: ' + str(min_phd) + ' < PHD < ' + str(max_phd))
		self.orders = []
		self.science(self.photon_list, min_phd, max_phd)


	@timing
	def on_add_orders_button_clicked(self, widget, data):
		if [self.add_orders_button.get_active()] == [True]:
			self.remove_orders_button.set_sensitive(False)
			self.statusbar.push(data, 'Click where to add an order.')

			def onclick_peak(event):
				if self.add_orders_button.get_active():
					self.add_order(event.ydata)

			self.cid_add = self.canvas.mpl_connect('button_press_event', onclick_peak)

		else:
			self.canvas.mpl_disconnect(self.cid_add)
			del self.cid_add

			self.remove_orders_button.set_sensitive(True)
			self.statusbar.push(0, 'Opened File:' + self.filename)


	@timing
	def add_order(self, ydata):
		order = ydata

		print 'Number of original orders', len(self.orders)

		self.orders.append(order)
		self.orders.sort()
		self.update_orders_plot(self.peaks_smoothed, self.orders)
		self.recalculate_button.set_sensitive(True)

		print 'Corrected number of orders', len(self.orders)


	@timing
	def on_remove_orders_button_clicked(self, widget, data):
		if [self.remove_orders_button.get_active()] == [True]:
			self.add_orders_button.set_sensitive(False)
			self.statusbar.push(data, 'Click on the order to remove.')

			def onclick_order(event):
				if self.remove_orders_button.get_active():
					self.remove_order(event.ydata)

			self.cid_remove = self.canvas.mpl_connect('button_press_event', onclick_order)

		else:
			self.canvas.mpl_disconnect(self.cid_remove)
			del self.cid_remove

			self.add_orders_button.set_sensitive(True)
			self.statusbar.push(0, 'Opened File:' + self.filename)


	@timing
	def remove_order(self, ydata):
		order = min(self.orders, key=lambda x:abs(x - ydata))

		print 'Number of original orders', len(self.orders)

		self.orders.remove(order)
		self.update_orders_plot(self.peaks_smoothed, self.orders)
		self.recalculate_button.set_sensitive(True)

		print 'Corrected number of orders', len(self.orders)


	def on_recalculate_button_clicked(self, widget, data):
		self.science(self.photon_list, self.min_phd, self.max_phd)


	def on_filemenu_save_clicked(self, widget):
		now = datetime.datetime.now()
		date = now.strftime("%Y_%m_%d_%H_%M_%S")
		temp = self.orders, self.min_phd, self.max_phd
		pickle.dump(temp, open(self.filename[:-5] + '_1D_' + date + '.orders', 'wb'))
		self.statusbar.push(0, 'Saved Orders: ' + self.filename[:-5] + '_1D_' + date + '.orders')


	def on_filemenu_load_clicked(self, widget):
		dialog = Gtk.FileChooserDialog(
			"Please Choose a File",
			self,
			Gtk.FileChooserAction.OPEN,
			(	Gtk.STOCK_CANCEL,
				Gtk.ResponseType.CANCEL,
				Gtk.STOCK_OPEN,
				Gtk.ResponseType.OK ) )
		dialog.set_default_response(Gtk.ResponseType.OK)
		filter = Gtk.FileFilter()
		filter.set_name('orders	Files')
		filter.add_mime_type('orders')
		filter.add_pattern('*.orders')
		dialog.add_filter(filter)

		response = dialog.run()

		if response == Gtk.ResponseType.OK :
			filename = dialog.get_filename()
			self.statusbar.push(0, 'Loaded Orders: ' + filename)
			dialog.destroy()
			del dialog
			orders, min_phd, max_phd = pickle.load(open(filename, 'rb'))
			self.science(self.photon_list, min_phd, max_phd, orders)

		elif response == Gtk.ResponseType.CANCEL:
			dialog.destroy()
			del dialog
コード例 #14
0
ファイル: rotation_dialog.py プロジェクト: gbtami/innstereo
class RotationDialog(object):

    """
    This class controls the appearance and signals of the data-rotation dialog.

    This class pulls the rotation dialog from the Glade file, intilizes the
    widgets and has methods for the signals defined in Glade.
    """

    def __init__(self, main_window, settings, data, add_layer_dataset, add_feature, redraw_main):
        """
        Initializes the RotationDialog class.

        Requires the main_window object, the settings object (PlotSettings
        class) and the data rows to initialize. All the necessary widgets are
        loaded from the Glade file. A matplotlib figure is set up and added
        to the scrolledwindow. Two axes are set up that show the original and
        rotated data.
        """
        self.builder = Gtk.Builder()
        self.builder.set_translation_domain(i18n().get_ts_domain())
        script_dir = os.path.dirname(__file__)
        rel_path = "gui_layout.glade"
        abs_path = os.path.join(script_dir, rel_path)
        self.builder.add_objects_from_file(abs_path,
            ("dialog_rotation", "adjustment_rotation_dipdir",
             "adjustment_rotation_dip", "adjustment_rotation_angle"))
        self.dialog = self.builder.get_object("dialog_rotation")
        self.dialog.set_transient_for(main_window)
        self.settings = settings
        self.data = data
        self.trans = self.settings.get_transform()
        self.add_layer_dataset = add_layer_dataset
        self.add_feature = add_feature
        self.redraw_main = redraw_main

        self.adjustment_rotation_dipdir = self.builder.get_object("adjustment_rotation_dipdir")
        self.adjustment_rotation_dip = self.builder.get_object("adjustment_rotation_dip")
        self.adjustment_rotation_angle = self.builder.get_object("adjustment_rotation_angle")

        self.spinbutton_rotation_dipdir = self.builder.get_object("spinbutton_rotation_dipdir")
        self.spinbutton_rotation_dip = self.builder.get_object("spinbutton_rotation_dip")
        self.spinbutton_rotation_angle = self.builder.get_object("spinbutton_rotation_angle")

        self.scrolledwindow_rotate = self.builder.get_object("scrolledwindow_rotate")

        self.fig = Figure(dpi=self.settings.get_pixel_density())
        self.canvas = FigureCanvas(self.fig)
        self.scrolledwindow_rotate.add_with_viewport(self.canvas)

        gridspec = GridSpec(1, 2)
        original_sp = gridspec.new_subplotspec((0, 0),
                                             rowspan=1, colspan=1)
        rotated_sp = gridspec.new_subplotspec((0, 1),
                                           rowspan=1, colspan=1)
        self.original_ax = self.fig.add_subplot(original_sp,
                                         projection=self.settings.get_projection())
        self.rotated_ax = self.fig.add_subplot(rotated_sp,
                                         projection=self.settings.get_projection())

        self.canvas.draw()
        self.redraw_plot()
        self.dialog.show_all()
        self.builder.connect_signals(self)
        if sys.platform == "win32":
            translate_gui(self.builder)

    def run(self):
        """
        Runs the dialog.

        Called from the MainWindow class. Initializes and shows the dialog.
        """
        self.dialog.run()

    def on_dialog_rotation_destroy(self, widget):
        """
        Hides the dialog on destroy.

        When the dialog is destroyed it is hidden.
        """
        self.dialog.hide()

    def on_button_cancel_rotation_clicked(self, button):
        """
        Exits the rotation dialog and makes no changes to the project.

        When the user clicks on Cancel the dialog is hidden, and no changes
        are made to the project structure.
        """
        self.dialog.hide()

    def on_button_apply_rotate_clicked(self, button):
        """
        Adds the rotated layers to the project.

        When the user clicks on "apply the rotation", the rotated data is
        added to the project as new datasets.
        """
        raxis_dipdir = self.spinbutton_rotation_dipdir.get_value()
        raxis_dip = self.spinbutton_rotation_dip.get_value()
        raxis = [raxis_dipdir, raxis_dip]
        raxis_angle = self.spinbutton_rotation_angle.get_value()

        for lyr_obj in self.data:
            lyr_type = lyr_obj.get_layer_type()
            lyr_store = lyr_obj.get_data_treestore()

            if lyr_type == "plane":
                dipdir_org, dips_org, dipdir_lst, dips_lst, strat, dipdir_az = \
                    self.parse_plane(lyr_store, raxis, raxis_angle)

                store, new_lyr_obj = self.add_layer_dataset("plane")
                for dipdir, dip, strt in zip(dipdir_az, dips_lst, strat):
                    self.add_feature("plane", store, dipdir, dip, strt)

            elif lyr_type == "line":
                ldipdir_org, ldips_org, ldipdir_lst, ldips_lst, sense = \
                    self.parse_line(lyr_store, raxis, raxis_angle)

                store, new_lyr_obj = self.add_layer_dataset("line")

                for dipdir, dip, sns in zip(ldipdir_lst, ldips_lst, sense):
                    self.add_feature("line", store, dipdir, dip, sns)

            elif lyr_type == "smallcircle":
                ldipdir_org, ldips_org, ldipdir_lst, ldips_lst, angle = \
                    self.parse_line(lyr_store, raxis, raxis_angle)

                store, new_lyr_obj = self.add_layer_dataset("smallcircle")
                for dipdir, dip, ang in zip(ldipdir_lst, ldips_lst, angle):
                    self.add_feature("smallcircle", store, dipdir, dip, ang)

            elif lyr_type == "faultplane":
                rtrn = self.parse_faultplane(lyr_store, raxis, raxis_angle)
                dipdir_org, dips_org, dipdir_lst, dips_lst, ldipdir_org, \
                ldips_org, ldipdir_lst, ldips_lst, sense, dipdir_az = rtrn[0], \
                rtrn[1], rtrn[2], rtrn[3], rtrn[4], rtrn[5], rtrn[6], rtrn[7], \
                rtrn[8], rtrn[9]

                store, new_lyr_obj = self.add_layer_dataset("faultplane")
                for dipdir, dip, ldipdir, ldip, sns in zip(dipdir_az, dips_lst,
                                                             ldipdir_lst, ldips_lst, sense):
                    self.add_feature("faultplane", store, dipdir, dip, ldipdir, ldip, sns)

            new_lyr_obj.set_properties(lyr_obj.get_properties())

        self.dialog.hide()
        self.redraw_main()

    def on_spinbutton_rotation_dipdir_value_changed(self, spinbutton):
        """
        Redraws the plot.

        When the value of the spinbutton is changed, the redraw_plot method
        is called, which rotates the data according to the new setting.
        """
        self.redraw_plot()

    def on_spinbutton_rotation_dip_value_changed(self, spinbutton):
        """
        Redraws the plot.

        When the value of the spinbutton is changed, the redraw_plot method
        is called, which rotates the data according to the new setting.
        """
        self.redraw_plot()

    def on_spinbutton_rotation_angle_value_changed(self, spinbutton):
        """
        Redraws the plot.

        When the value of the spinbutton is changed, the redraw_plot method
        is called, which rotates the data according to the new setting.
        """
        self.redraw_plot()

    def convert_lonlat_to_dipdir(self, lon, lat):
        """
        Converts lat-lon data to dip-direction and dip.

        Expects a longitude and a latitude value. The measurment is forward
        transformed into stereonet-space. Then the azimut (dip-direction) and
        diping angle are calculated. Returns two values: dip-direction and dip.
        """
        #The longitude and latitude have to be forward-transformed to get
        #the corect azimuth angle
        xy = np.array([[lon, lat]])
        xy_trans = self.trans.transform(xy)
        x = float(xy_trans[0,0:1])
        y = float(xy_trans[0,1:2])
        alpha = np.arctan2(x, y)
        alpha_deg = np.degrees(alpha)
        if alpha_deg < 0:
            alpha_deg += 360

        #Longitude and Latitude don't need to be converted for rotation.
        #The correct dip is the array[1] value once the vector has been
        #rotated in north-south position.
        array = mplstereonet.stereonet_math._rotate(np.degrees(lon),
                                                    np.degrees(lat),
                                                    alpha_deg * (-1))
        gamma = float(array[1])
        gamma_deg = 90 - np.degrees(gamma)

        #If the longitude is larger or small than pi/2 the measurment lies
        #on the upper hemisphere and needs to be corrected.
        if lon > (np.pi / 2) or lon < (-np.pi / 2):
            alpha_deg = alpha_deg + 180

        return alpha_deg, gamma_deg

    def rotate_data(self, raxis, raxis_angle, dipdir, dip):
        """
        Rotates a measurment around a rotation axis a set number of degrees.

        Expects a rotation-axis, a rotation-angle, a dip-direction and a
        dip angle. The measurement is converted to latlot and then passed
        to the mplstereonet rotate function.
        """
        lonlat = mplstereonet.line(dip, dipdir)

        #Rotation around x-axis until rotation-axis azimuth is east-west
        rot1 = (90 - raxis[0])
        lon1 = np.degrees(lonlat[0])
        lat1 = np.degrees(lonlat[1])
        lon_rot1, lat_rot1 = mplstereonet.stereonet_math._rotate(lon1, lat1,
                                                      theta=rot1, axis="x")

        #Rotation around z-axis until rotation-axis dip is east-west
        rot2 = -(90 - raxis[1])
        lon2 = np.degrees(lon_rot1)
        lat2 = np.degrees(lat_rot1)
        lon_rot2, lat_rot2 = mplstereonet.stereonet_math._rotate(lon2, lat2,
                                                           theta=rot2, axis="z")
            
        #Rotate around the x-axis for the specified rotation:
        rot3 = raxis_angle
        lon3 = np.degrees(lon_rot2)
        lat3 = np.degrees(lat_rot2)
        lon_rot3, lat_rot3 = mplstereonet.stereonet_math._rotate(lon3, lat3,
                                                           theta=rot3, axis="x")

        #Undo the z-axis rotation
        rot4 = -rot2
        lon4 = np.degrees(lon_rot3)
        lat4 = np.degrees(lat_rot3)
        lon_rot4, lat_rot4 = mplstereonet.stereonet_math._rotate(lon4, lat4,
                                                           theta=rot4, axis="z")

        #Undo the x-axis rotation
        rot5 = -rot1
        lon5 = np.degrees(lon_rot4)
        lat5 = np.degrees(lat_rot4)
        lon_rot5, lat_rot5 = mplstereonet.stereonet_math._rotate(lon5, lat5,
                                                           theta=rot5, axis="x")
        dipdir5, dip5 = self.convert_lonlat_to_dipdir(lon_rot5, lat_rot5)
        return dipdir5, dip5

    def parse_plane(self, lyr_store, raxis, raxis_angle):
        """
        Parses and rotates data of a plane layer.

        Expects a TreeStore of a layer, the rotation axis and the
        angle of rotation. The method returns each column unrotated and rotated.        
        """
        dipdir_org = []
        dips_org = []
        dipdir_lst = []
        dips_lst = []
        dipdir_az = []
        strat = []

        for row in lyr_store:
            dipdir_org.append(row[0] - 90)
            dips_org.append(row[1])
            #Planes and faultplanes are rotated using their poles
            dipdir, dip = self.rotate_data(raxis, raxis_angle, row[0] + 180,
                                           90 - row[1])
            dipdir_lst.append(dipdir + 90)
            dipdir_az.append(dipdir + 180)
            dips_lst.append(90 - dip)
            strat.append(row[2])

        return dipdir_org, dips_org, dipdir_lst, dips_lst, strat, dipdir_az

    def parse_line(self, lyr_store, raxis, raxis_angle):
        """
        Parses and rotates data of a linear or smallcircle layer.

        Expects a TreeStore of a layer, the rotation axis and the
        angle of rotation. The method returns each column unrotated and rotated.        
        """
        ldipdir_org = []
        ldips_org = []
        ldipdir_lst = []
        ldips_lst = []
        third_col = []

        for row in lyr_store:
            ldipdir_org.append(row[0])
            ldips_org.append(row[1])
            ldipdir, ldip = self.rotate_data(raxis, raxis_angle, row[0], row[1])
            ldipdir_lst.append(ldipdir)
            ldips_lst.append(ldip)
            third_col.append(row[2])

        return ldipdir_org, ldips_org, ldipdir_lst, ldips_lst, third_col

    def parse_faultplane(self, lyr_store, raxis, raxis_angle):
        """
        Parses and rotates data of a faultplane layer.

        Expects a TreeStore of a faultplane layer, the rotation axis and the
        angle of rotation. The method returns each column unrotated and rotated.        
        """
        dipdir_org = []
        dips_org = []
        dipdir_lst = []
        dips_lst = []
        ldipdir_org = []
        ldips_org = []
        ldipdir_lst = []
        ldips_lst = []
        dipdir_az = []
        sense = []

        for row in lyr_store:
            dipdir_org.append(row[0] - 90)
            dips_org.append(row[1])
            #Planes and faultplanes are rotated using their poles
            dipdir, dip = self.rotate_data(raxis, raxis_angle, row[0] + 180,
                                           90 - row[1])
            dipdir_lst.append(dipdir + 90)
            dipdir_az.append(dipdir + 270)
            dips_lst.append(90 - dip)

            ldipdir_org.append(row[2])
            ldips_org.append(row[3])
            ldipdir, ldip = self.rotate_data(raxis, raxis_angle, row[2], row[3])
            ldipdir_lst.append(ldipdir)
            ldips_lst.append(ldip)
            sense.append(row[4])

        return (dipdir_org, dips_org, dipdir_lst, dips_lst, ldipdir_org,
                ldips_org, ldipdir_lst, ldips_lst, sense, dipdir_az)
       
    def redraw_plot(self):
        """
        Redraws the plot using the current settings of the dialog's spinbuttons.

        This method clears the two axes and adds the annotations. The current
        values of the rotation axis and rotation angle spinbuttons are
        retrieved. The data is parsed, and the features are then drawn.
        In addition the rotation-axis is drawn.
        """
        self.original_ax.cla()
        self.rotated_ax.cla()
        self.original_ax.grid(False)
        self.rotated_ax.grid(False)
        self.original_ax.set_azimuth_ticks([0], labels=["N"])
        self.rotated_ax.set_azimuth_ticks([0], labels=["N"])

        bar = 0.05
        self.original_ax.annotate("", xy = (-bar, 0),
                                    xytext = (bar, 0),
                                    xycoords = "data",
                                    arrowprops = dict(arrowstyle = "-",
                                                      connectionstyle = "arc3"))
        self.original_ax.annotate("", xy = (0, -bar),
                                    xytext = (0, bar),
                                    xycoords = "data",
                                    arrowprops = dict(arrowstyle = "-",
                                                      connectionstyle = "arc3"))
        self.rotated_ax.annotate("", xy = (-bar, 0),
                                    xytext = (bar, 0),
                                    xycoords = "data",
                                    arrowprops = dict(arrowstyle = "-",
                                                      connectionstyle = "arc3"))
        self.rotated_ax.annotate("", xy = (0, -bar),
                                    xytext = (0, bar),
                                    xycoords = "data",
                                    arrowprops = dict(arrowstyle = "-",
                                                      connectionstyle = "arc3"))

        raxis_dipdir = self.spinbutton_rotation_dipdir.get_value()
        raxis_dip = self.spinbutton_rotation_dip.get_value()
        raxis = [raxis_dipdir, raxis_dip]
        raxis_angle = self.spinbutton_rotation_angle.get_value()

        for lyr_obj in self.data:
            lyr_type = lyr_obj.get_layer_type()
            lyr_store = lyr_obj.get_data_treestore()

            if lyr_type == "plane":
                dipdir_org, dips_org, dipdir_lst, dips_lst, strat, dipdir_az = \
                    self.parse_plane(lyr_store, raxis, raxis_angle)

                self.original_ax.plane(dipdir_org, dips_org, color=lyr_obj.get_line_color(),
                    linewidth=lyr_obj.get_line_width(),
                    linestyle=lyr_obj.get_line_style(),
                    dash_capstyle=lyr_obj.get_capstyle(),
                    alpha=lyr_obj.get_line_alpha(), clip_on=False)
                self.rotated_ax.plane(dipdir_lst, dips_lst, color=lyr_obj.get_line_color(),
                    linewidth=lyr_obj.get_line_width(),
                    linestyle=lyr_obj.get_line_style(),
                    dash_capstyle=lyr_obj.get_capstyle(),
                    alpha=lyr_obj.get_line_alpha(), clip_on=False)

            elif lyr_type == "line":
                ldipdir_org, ldips_org, ldipdir_lst, ldips_lst, sense = \
                    self.parse_line(lyr_store, raxis, raxis_angle)

                self.original_ax.line(ldips_org, ldipdir_org,
                    marker=lyr_obj.get_marker_style(),
                    markersize=lyr_obj.get_marker_size(),
                    color=lyr_obj.get_marker_fill(),
                    markeredgewidth=lyr_obj.get_marker_edge_width(),
                    markeredgecolor=lyr_obj.get_marker_edge_color(),
                    alpha=lyr_obj.get_marker_alpha(), clip_on=False)
                self.rotated_ax.line(ldips_lst, ldipdir_lst,
                    marker=lyr_obj.get_marker_style(),
                    markersize=lyr_obj.get_marker_size(),
                    color=lyr_obj.get_marker_fill(),
                    markeredgewidth=lyr_obj.get_marker_edge_width(),
                    markeredgecolor=lyr_obj.get_marker_edge_color(),
                    alpha=lyr_obj.get_marker_alpha(), clip_on=False)

            elif lyr_type == "smallcircle":
                ldipdir_org, ldips_org, ldipdir_lst, ldips_lst, angle = \
                    self.parse_line(lyr_store, raxis, raxis_angle)

                self.original_ax.cone(ldips_org, ldipdir_org, angle, facecolor="None",
                            color=lyr_obj.get_line_color(),
                            linewidth=lyr_obj.get_line_width(),
                            label=lyr_obj.get_label(),
                            linestyle=lyr_obj.get_line_style())
                self.rotated_ax.cone(ldips_lst, ldipdir_lst, angle, facecolor="None",
                            color=lyr_obj.get_line_color(),
                            linewidth=lyr_obj.get_line_width(),
                            label=lyr_obj.get_label(),
                            linestyle=lyr_obj.get_line_style())

            elif lyr_type == "faultplane":
                rtrn = self.parse_faultplane(lyr_store, raxis, raxis_angle)
                dipdir_org, dips_org, dipdir_lst, dips_lst, ldipdir_org, \
                ldips_org, ldipdir_lst, ldips_lst, sense = rtrn[0], rtrn[1], \
                rtrn[2], rtrn[3], rtrn[4], rtrn[5], rtrn[6], rtrn[7], rtrn[8]

                self.original_ax.plane(dipdir_org, dips_org, color=lyr_obj.get_line_color(),
                                        linewidth=lyr_obj.get_line_width(),
                                        linestyle=lyr_obj.get_line_style(),
                                        dash_capstyle=lyr_obj.get_capstyle(),
                                        alpha=lyr_obj.get_line_alpha(), clip_on=False)
                self.rotated_ax.plane(dipdir_lst, dips_lst, color=lyr_obj.get_line_color(),
                                        linewidth=lyr_obj.get_line_width(),
                                        linestyle=lyr_obj.get_line_style(),
                                        dash_capstyle=lyr_obj.get_capstyle(),
                                        alpha=lyr_obj.get_line_alpha(), clip_on=False)

                self.original_ax.line(ldips_org, ldipdir_org,
                                    marker=lyr_obj.get_marker_style(),
                                    markersize=lyr_obj.get_marker_size(),
                                    color=lyr_obj.get_marker_fill(),
                                    markeredgewidth=lyr_obj.get_marker_edge_width(),
                                    markeredgecolor=lyr_obj.get_marker_edge_color(),
                                    alpha=lyr_obj.get_marker_alpha(), clip_on=False)
                self.rotated_ax.line(ldips_lst, ldipdir_lst,
                                    marker=lyr_obj.get_marker_style(),
                                    markersize=lyr_obj.get_marker_size(),
                                    color=lyr_obj.get_marker_fill(),
                                    markeredgewidth=lyr_obj.get_marker_edge_width(),
                                    markeredgecolor=lyr_obj.get_marker_edge_color(),
                                    alpha=lyr_obj.get_marker_alpha(), clip_on=False)

        #Plot rotation axis
        self.original_ax.line(raxis_dip, raxis_dipdir, marker="o",
                    markersize=10, color="#ff0000",
                    markeredgewidth=1, markeredgecolor="#000000",
                    alpha=1, clip_on=False)

        self.canvas.draw()
コード例 #15
0
ファイル: spcinspect.py プロジェクト: pytrip/SPCinspector
class Handler:

    def __init__(self):
        global ppp

        self.window1 = builder.get_object("window1")
        self.window1.set_title("SPCinspector - No file loaded")

        self.vbox1 = builder.get_object("vbox1")
        
        self.label0 = builder.get_object("label0")
        self.label1 = builder.get_object("label1")
        self.label2 = builder.get_object("label2")
        self.label3 = builder.get_object("label3")
        self.label4 = builder.get_object("label4")
        self.label5 = builder.get_object("label5")
        self.label6 = builder.get_object("label6")
        self.label7 = builder.get_object("label7")
        self.label8 = builder.get_object("label8")
#        self.label9 = builder.get_object("label9")
#        self.label10 = builder.get_object("label10")
#        self.label11 = builder.get_object("label11")
        self.label12 = builder.get_object("label12")
        self.label13 = builder.get_object("label13")
        self.label14 = builder.get_object("label14")
        self.label15 = builder.get_object("label15")
        self.label16 = builder.get_object("label16")
        self.label17 = builder.get_object("label17")
        self.label18 = builder.get_object("label18")
        self.label19 = builder.get_object("label19")
        self.label20 = builder.get_object("label20")
        self.label21 = builder.get_object("label21")
        self.label22 = builder.get_object("label22")
        self.label23 = builder.get_object("label23")
        self.label24 = builder.get_object("label24")
        self.label25 = builder.get_object("label25")
        self.label26 = builder.get_object("label26")
        
        self.spin1 = builder.get_object("spin1") # depth
        self.spin2 = builder.get_object("spin2") # species
        self.spin3 = builder.get_object("spin3") # E-bins

        self.spin1.set_sensitive(False)
        self.spin2.set_sensitive(False)
        self.spin3.set_sensitive(False)
        
        self.button1 = builder.get_object("button1")
        self.button2 = builder.get_object("button2")
        self.button1.set_sensitive(False)
        
        self.cur_depth = 0
        self.cur_species = 0
        self.cur_ebin = 0
        
        self.spc = []
        self.path = ""
        
        fig = Figure(figsize=(5,5), dpi=100)
        #ax = fig.add_subplot(111, projection='polar')
        self.ax = fig.add_subplot(111)
        #x = [1, 2, 3, 4, 5]
        #y = [1, 4, 9, 16, 25]
        #self.ax.plot(x,y)
        self.ax.set_xlabel('Energy [MeV/u]')
        self.ax.set_ylabel('Histories')

        
        #sw = Gtk.ScrolledWindow()
        #myfirstwindow.add(sw)

        self.canvas = FigureCanvas(fig)
        self.canvas.set_size_request(600,600)
        self.vbox1.pack_end(self.canvas,True,True,True)

        self.zlut = {
            1:'H',2:'He',
            3:'Li',4:'Be',5:'B',6:'C',7:'N', 8:'O',9:'F',10:'Ne',
            11:'Na',12:'Mg',13:'Al',14:'Si',15:'P',16:'S',17:'Cl',18:'Ar',
            19:'K',20:'Ca'
        }

        print(ppp)
        if os.path.isfile(ppp):
            self.load_spc(ppp)



        
    def update_plot(self):

        d = self.spc.data[self.cur_depth]
        ds = d.species[self.cur_species]

        dse = ds.ebindata
        dsh = ds.histdata
        dsc = ds.rcumdata

        #print("NB:",len(dse),len(dsh),len(dsc))        
        
        self.ax.cla()
        self.ax.set_xlabel('Energy [MeV/u]')
        self.ax.set_ylabel('Histories')

        # plot legent in upper right corner
        text = r'$\mathregular{^{'+str(ds.la)+'}}$'+self.zlut.get(ds.lz,'?')
        self.ax.text(0.90, 0.94, text, fontsize=15,transform=self.ax.transAxes)

        #self.ax.plot(dse[1:],dsc[1:]) # cumulative sum
        self.ax.bar(dse[1:],dsh)
        self.canvas.draw()
        self.canvas.show()
        
    def onDeleteWindow(self, *args):
        Gtk.main_quit(*args)

    def onButtonPressed(self, button1):
        print("Hello World!")
        
    def main_quit(self, *args):
        print("Call Gtk.main_quit")
        Gtk.main_quit(*args)

    def on_spin1_value_changed(self,*args):
        self.cur_depth = self.spin1.get_value_as_int()-1       
        self.set_labels(self.spc)
        self.update_plot()
        
    def on_spin2_value_changed(self,*args):
        self.cur_species = self.spin2.get_value_as_int()-1
        self.set_labels(self.spc)
        self.update_plot()
        
    def on_spin3_value_changed(self,*args):
        self.cur_ebin = self.spin3.get_value_as_int()-1
        self.set_labels(self.spc)
        #self.update_plot() # no need to, as the energy marker is missing.

    def on_menuopen_activate(self,*args):
        dialog = Gtk.FileChooserDialog("Please choose a file", None,
            Gtk.FileChooserAction.OPEN,
            (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
             Gtk.STOCK_OPEN, Gtk.ResponseType.OK))

        #self.add_filters(dialog)

        response = dialog.run()
        if response == Gtk.ResponseType.OK:
            print("Open clicked")
            print("File selected: " + dialog.get_filename())
            path = dialog.get_filename()
            dialog.destroy()
            self.load_spc(path)
        elif response == Gtk.ResponseType.CANCEL:
            print("Cancel clicked")
            dialog.destroy()
        
    def load_spc(self,path):
        spc = SPC(path)
        spc.read_spc()

        self.filename = os.path.split(path)[1]
        self.window1.set_title("SPCinspector - "+ self.filename)
        
        self.spin1.set_range(1,spc.ndsteps)
        self.spin2.set_range(1,spc.data[self.cur_depth].nparts)
        self.spin3.set_range(1,spc.data[self.cur_depth].species[self.cur_species].ne)

        self.spin1.set_sensitive(True)
        self.spin2.set_sensitive(True)
        self.spin3.set_sensitive(True)

        self.button1.set_sensitive(False) # Todo: currently disabled
        self.set_labels(spc)
        self.spc = spc

        self.update_plot()
        
    def set_labels(self,spc):
        self.label0.set_text(self.filename)
        self.label1.set_text(spc.filetype)
        self.label2.set_text(spc.fileversion)
        self.label3.set_text(spc.filedate)
        self.label4.set_text(spc.targname)
        self.label5.set_text(spc.projname)
        self.label6.set_text('{:f}'.format(spc.energy))
        self.label7.set_text('{:f}'.format(spc.peakpos))
        self.label8.set_text('{:f}'.format(spc.norm))
        # - depth
        self.label12.set_text('{:d}'.format(spc.ndsteps))

        d = spc.data[self.cur_depth]
        self.label13.set_text('{:f}'.format(d.depth))
        self.label14.set_text('{:f}'.format(d.dsnorm))

        # - species 
        self.label15.set_text('{:d}'.format(d.nparts))
        ds = d.species[self.cur_species]
        self.label16.set_text('{:f} {:f}'.format(ds.z,ds.a))
        self.label17.set_text('{:d} {:d}'.format(ds.lz,ds.la))
        self.label18.set_text('{:f}'.format(ds.dscum)) # running cum.sum over species
        self.label19.set_text('{:d}'.format(ds.nc))
        
        # - energy
        self.label20.set_text('{:d}'.format(ds.ne))
        dse = ds.ebindata[self.cur_ebin]
        if self.cur_ebin == 0:
            dsel = dse
        else:
            dsel = ds.ebindata[self.cur_ebin-1]            
        dsh = ds.histdata[self.cur_ebin]
        dsc = ds.rcumdata[self.cur_ebin]
        self.label21.set_text('{:.4f} {:.4f} {:.4f}'.format(dsel,(dsel+dse)*0.5,dse))
        self.label22.set_text('{:f}'.format(dse - dsel))
        self.label23.set_text('{:f}'.format(dsh))
        self.label24.set_text('{:f}'.format(dsh*(dse-dsel)))
        self.label25.set_text('{:f}'.format(dsc)) #cummulative sum
        self.label26.set_text('{:.2f} {:.2f}'.format(ds.ebindata.min(),ds.ebindata.max()))

    def _do_expose(self, widget, event):
        print("_do_expose")
        self.canvas.draw()
        self.canvas.show()
コード例 #16
0
ファイル: plot.py プロジェクト: moritz31/WattmanGTK
class Plot:
    # TODO scaling of size when resizing
    # TODO tighter fit of plot
    # TODO BUG: weird redrawing issue on changing panes, probably should not redraw graph on changing panes
    # Plot object used GUI
    def __init__(self, builder, GPU, maxpoints, precision, linux_kernelmain,
                 linux_kernelsub):
        # Can used for kernel specific workarounds
        self.linux_kernelmain = linux_kernelmain
        self.linux_kernelsub = linux_kernelsub

        self.precision = precision
        self.builder = builder
        self.GPU = GPU
        self.maxpoints = maxpoints
        self.fig = Figure(figsize=(1000, 150), dpi=100, facecolor="#00000000")
        self.fig.set_tight_layout(True)
        self.ax = self.fig.add_subplot(111)
        # enable, name, unit, mean, max, current
        self.signalstore = Gtk.ListStore(bool, bool, str, str, str, str, str,
                                         str)
        self.Plotsignals = self.init_signals(self.GPU)
        self.init_treeview()
        self.update_signals()
        self.canvas = FigureCanvas(self.fig)
        self.canvas.set_size_request(1000, 150)
        self.object = self.builder.get_object("matplot")
        self.object.add(self.canvas)
        self.object.show_all()

    def init_signals(self, GPU):
        Plotsignals = []

        # Define signals with: names units max min path plotenable plotnormalise plotcolor parser and outputargument used from parser
        Plotsignals.append(
            Plotsignal("GPU Clock", "[MHz]", GPU.pstate_clock[-1],
                       GPU.pstate_clock[0], "/pp_dpm_sclk", True, True,
                       "#1f77b4", GPU.get_current_clock, 0))
        Plotsignals.append(
            Plotsignal("GPU State", "[-]",
                       len(GPU.pstate_clock) - 1, 0, "/pp_dpm_sclk", True,
                       True, "#ff7f0e", GPU.get_current_clock, 1))
        Plotsignals.append(
            Plotsignal("MEM Clock", "[MHz]", GPU.pmem_clock[-1],
                       GPU.pmem_clock[0], "/pp_dpm_mclk", True, True,
                       "#d62728", GPU.get_current_clock, 0))
        Plotsignals.append(
            Plotsignal("MEM State", "[-]",
                       len(GPU.pmem_clock) - 1, 0, "/pp_dpm_mclk", True, True,
                       "#9467bd", GPU.get_current_clock, 1))
        if GPU.fanpwmsensors is not None:
            Plotsignals.append(
                Plotsignal("FAN Speed", "[0-255]",
                           GPU.fanpwmsensors.read_attribute('_max', True), 0,
                           GPU.fanpwmsensors.path, True, True, "#8c564b",
                           GPU.fanpwmsensors.read))
        if GPU.tempsensors is not None:
            Plotsignals.append(
                Plotsignal("TEMP 1", "[m°C]",
                           GPU.tempsensors.read_attribute('_crit', True), 0,
                           GPU.tempsensors.path, True, True, "#e377c2",
                           GPU.tempsensors.read))
        if GPU.powersensors is not None:
            Plotsignals.append(
                Plotsignal("POWER", "[µW]",
                           GPU.powersensors.read_attribute('_cap', True), 0,
                           GPU.powersensors.path, True, True, "#7f7f7f",
                           GPU.powersensors.read))

        # GPU busy percent only properly available in linux version 4.19+
        if (self.linux_kernelmain == 4
                and self.linux_kernelsub > 18) or (self.linux_kernelmain >= 5):
            Plotsignals.append(
                Plotsignal("GPU Usage",
                           "[-]",
                           100,
                           0,
                           "/gpu_busy_percent",
                           True,
                           True,
                           "#2ca02c",
                           parser=GPU.read_sensor))

        return Plotsignals

    def init_treeview(self):
        textrenderer = Gtk.CellRendererText()
        plotrenderer = Gtk.CellRendererToggle()
        plotrenderer.connect("toggled", self.on_plot_toggled)
        normaliserenderer = Gtk.CellRendererToggle()
        normaliserenderer.connect("toggled", self.on_normalise_toggled)
        self.tree = self.builder.get_object("Signal Selection")
        self.tree.append_column(
            Gtk.TreeViewColumn("Plot", plotrenderer, active=0))
        self.tree.append_column(
            Gtk.TreeViewColumn("Scale", normaliserenderer, active=1))
        columnnames = ["Name", "Unit", "mean", "max", "current"]
        for i, column in enumerate(columnnames):
            tcolumn = Gtk.TreeViewColumn(column,
                                         textrenderer,
                                         text=i + 2,
                                         foreground=7)
            self.tree.append_column(tcolumn)

        for plotsignal in self.Plotsignals:
            self.signalstore.append([
                plotsignal.plotenable, plotsignal.plotnormalise,
                plotsignal.name,
                convert_to_si(plotsignal.unit)[0], '0', '0', '0',
                plotsignal.plotcolor
            ])
        self.tree.set_model(self.signalstore)

    def update_signals(self):
        # Retrieve signal and set appropriate values in signalstore to update left pane in GUI
        for i, Plotsignal in enumerate(self.Plotsignals):
            Plotsignal.retrieve_data(self.maxpoints)
            self.signalstore[i][4] = str(
                np.around(
                    convert_to_si(Plotsignal.unit, Plotsignal.get_mean())[1],
                    self.precision))
            self.signalstore[i][5] = str(
                np.around(
                    convert_to_si(Plotsignal.unit, Plotsignal.get_max())[1],
                    self.precision))
            self.signalstore[i][6] = str(
                np.around(
                    convert_to_si(Plotsignal.unit,
                                  Plotsignal.get_last_value())[1],
                    self.precision))

    def on_plot_toggled(self, widget, path):
        self.signalstore[path][0] = not self.signalstore[path][0]
        self.Plotsignals[int(
            path)].plotenable = not self.Plotsignals[int(path)].plotenable
        self.update_plot()

    def on_normalise_toggled(self, widget, path):
        self.signalstore[path][1] = not self.signalstore[path][1]
        self.Plotsignals[int(path)].plotnormalise = not self.Plotsignals[int(
            path)].plotnormalise
        self.update_plot()

    def update_plot(self):
        self.ax.clear()
        for Plotsignal in self.Plotsignals:
            if Plotsignal.plotenable:
                if Plotsignal.plotnormalise:
                    data = Plotsignal.get_normalised_values()
                    self.ax.plot(data, color=Plotsignal.plotcolor)
                else:
                    data = Plotsignal.get_values()
                    self.ax.plot(convert_to_si(Plotsignal.unit, data)[1],
                                 color=Plotsignal.plotcolor)

        self.ax.grid(True)
        self.ax.get_yaxis().tick_right()
        self.ax.get_yaxis().set_visible(True)
        self.ax.get_xaxis().set_visible(False)
        all_normalised = True
        iter = self.signalstore.get_iter(0)
        while iter is not None:
            if self.signalstore[iter][1] == False:
                all_normalised = False
                break
            iter = self.signalstore.iter_next(iter)
        if all_normalised:
            self.ax.set_yticks(np.arange(0, 1.1, step=0.1))
        else:
            self.ax.yaxis.set_major_locator(AutoLocator())
        self.canvas.draw()
        self.canvas.flush_events()

    def refresh(self):
        # This is run in thread
        self.update_signals()
        self.update_plot()
コード例 #17
0
ファイル: graphs.py プロジェクト: junk13/king-phisher
class CampaignGraph(object):
    """
	A basic graph provider for using :py:mod:`matplotlib` to create graph
	representations of campaign data. This class is meant to be subclassed
	by real providers.
	"""
    title = 'Unknown'
    """The title of the graph."""
    _graph_id = None
    table_subscriptions = []
    """A list of tables from which information is needed to produce the graph."""
    def __init__(self, config, parent, size_request=None):
        """
		:param dict config: The King Phisher client configuration.
		:param parent: The parent window for this object.
		:type parent: :py:class:`Gtk.Window`
		:param tuple size_request: The size to set for the canvas.
		"""
        self.config = config
        """A reference to the King Phisher client configuration."""
        self.parent = parent
        """The parent :py:class:`Gtk.Window` instance."""
        self.figure, ax = pyplot.subplots()
        self.axes = self.figure.get_axes()
        self.canvas = FigureCanvas(self.figure)
        self.manager = None
        if size_request:
            self.canvas.set_size_request(*size_request)
        self.canvas.mpl_connect('button_press_event',
                                self.mpl_signal_canvas_button_pressed)
        self.canvas.show()
        self.navigation_toolbar = NavigationToolbar(self.canvas, self.parent)
        self.navigation_toolbar.hide()
        self.popup_menu = Gtk.Menu.new()

        menu_item = Gtk.MenuItem.new_with_label('Export')
        menu_item.connect('activate', self.signal_activate_popup_menu_export)
        self.popup_menu.append(menu_item)

        menu_item = Gtk.MenuItem.new_with_label('Refresh')
        menu_item.connect('activate', lambda action: self.refresh())
        self.popup_menu.append(menu_item)

        menu_item = Gtk.CheckMenuItem.new_with_label('Show Toolbar')
        menu_item.connect('toggled',
                          self.signal_toggled_popup_menu_show_toolbar)
        self.popup_menu.append(menu_item)
        self.popup_menu.show_all()

    @classmethod
    def get_graph_id(klass):
        """
		The graph id of an exported :py:class:`.CampaignGraph`.

		:param klass: The class to return the graph id of.
		:type klass: :py:class:`.CampaignGraph`
		:return: The id of the graph.
		:rtype: int
		"""
        return klass._graph_id

    def make_window(self):
        """
		Create a window from the figure manager.

		:return: The graph in a new, dedicated window.
		:rtype: :py:class:`Gtk.Window`
		"""
        if self.manager == None:
            self.manager = FigureManager(self.canvas, 0)
        window = self.manager.window
        window.set_transient_for(self.parent)
        window.set_title(self.title)
        return window

    def mpl_signal_canvas_button_pressed(self, event):
        if event.button != 3:
            return
        self.popup_menu.popup(None, None, None, None, event.button,
                              Gtk.get_current_event_time())
        return True

    def signal_activate_popup_menu_export(self, action):
        dialog = gui_utilities.UtilityFileChooser('Export Graph', self.parent)
        file_name = self.config['campaign_name'] + '.png'
        response = dialog.run_quick_save(file_name)
        dialog.destroy()
        if not response:
            return
        destination_file = response['target_path']
        self.figure.savefig(destination_file, format='png')

    def signal_toggled_popup_menu_show_toolbar(self, widget):
        if widget.get_property('active'):
            self.navigation_toolbar.show()
        else:
            self.navigation_toolbar.hide()

    def load_graph(self):
        """Load the graph information via :py:meth:`.refresh`."""
        self.refresh()

    def refresh(self, info_cache=None, stop_event=None):
        """
		Refresh the graph data by retrieving the information from the
		remote server.

		:param dict info_cache: An optional cache of data tables.
		:param stop_event: An optional object indicating that the operation should stop.
		:type stop_event: :py:class:`threading.Event`
		:return: A dictionary of cached tables from the server.
		:rtype: dict
		"""
        info_cache = (info_cache or {})
        if not self.parent.rpc:
            return info_cache
        for table in self.table_subscriptions:
            if stop_event and stop_event.is_set():
                return info_cache
            if not table in info_cache:
                info_cache[table] = list(
                    self.parent.rpc.remote_table('campaign/' + table,
                                                 self.config['campaign_id']))
        map(lambda ax: ax.clear(), self.axes)
        self._load_graph(info_cache)
        self.canvas.draw()
        return info_cache
コード例 #18
0
class Plot:
    # TODO scaling of size when resizing
    # TODO tighter fit of plot
    # TODO BUG: weird redrawing issue on changing panes, probably should not redraw graph on changing panes
    # Plot object used GUI
    def __init__(self, builder, GPU, maxpoints, precision, linux_kernelmain,
                 linux_kernelsub):
        # Can used for kernel specific workarounds
        self.linux_kernelmain = linux_kernelmain
        self.linux_kernelsub = linux_kernelsub

        self.precision = precision
        self.builder = builder
        self.GPU = GPU
        self.maxpoints = maxpoints
        self.fig = Figure(figsize=(1000, 150), dpi=100)
        self.fig.set_tight_layout(True)
        self.ax = self.fig.add_subplot(111)
        # enable, name, unit, mean, max, current
        self.signalstore = Gtk.ListStore(bool, str, str, str, str, str)
        self.Plotsignals = self.init_signals(self.GPU)
        self.init_treeview()
        self.update_signals()
        self.canvas = FigureCanvas(self.fig)
        self.canvas.set_size_request(1000, 150)
        self.object = self.builder.get_object("matplot")
        self.object.add(self.canvas)
        self.object.show_all()

    def init_signals(self, GPU):
        Plotsignals = []

        # Define signals with: names units min max path plotenable plotcolor parser and outputargument used from parser
        Plotsignals.append(
            Plotsignal("GPU Clock", "[MHz]", GPU.pstate_clock[-1],
                       GPU.pstate_clock[0], "/pp_dpm_sclk", True, "#1f77b4",
                       GPU.get_current_clock, 0))
        Plotsignals.append(
            Plotsignal("GPU State", "[-]", 0, len(GPU.pstate_clock),
                       "/pp_dpm_sclk", True, "#ff7f0e", GPU.get_current_clock,
                       1))
        Plotsignals.append(
            Plotsignal("MEM Clock", "[MHz]", GPU.pmem_clock[-1],
                       GPU.pmem_clock[0], "/pp_dpm_mclk", True, "#d62728",
                       GPU.get_current_clock, 0))
        Plotsignals.append(
            Plotsignal("MEM State", "[-]", 0, len(GPU.pmem_clock),
                       "/pp_dpm_mclk", True, "#9467bd", GPU.get_current_clock,
                       1))
        Plotsignals.append(
            Plotsignal("FAN Speed", "[RPM]", 0, 255,
                       "/hwmon/hwmon0/subsystem/hwmon0/fan1_input", True,
                       "#8c564b", GPU.read_sensor))
        Plotsignals.append(
            Plotsignal(
                "TEMP 1", "[m°C]", 0,
                GPU.read_sensor("/hwmon/hwmon0/subsystem/hwmon0/temp1_crit"),
                "/hwmon/hwmon0/subsystem/hwmon0/temp1_input", True, "#e377c2",
                GPU.read_sensor))
        Plotsignals.append(
            Plotsignal("POWER", "[µW]", 0,
                       GPU.read_sensor("/hwmon/hwmon0/power1_cap_max"),
                       "/hwmon/hwmon0/power1_average", True, "#7f7f7f",
                       GPU.read_sensor))

        # GPU busy percent only properly available in linux version 4.19+
        if (self.linux_kernelmain == 4
                and self.linux_kernelsub > 18) or (self.linux_kernelmain >= 5):
            Plotsignals.append(
                Plotsignal("GPU Usage",
                           "[-]",
                           1,
                           0,
                           "/gpu_busy_percent",
                           True,
                           "#2ca02c",
                           parser=GPU.read_sensor))

        return Plotsignals

    def init_treeview(self):
        textrenderer = Gtk.CellRendererText()
        boolrenderer = Gtk.CellRendererToggle()
        boolrenderer.connect("toggled", self.on_cell_toggled)
        self.tree = self.builder.get_object("Signal Selection")
        self.tree.append_column(
            Gtk.TreeViewColumn("Plot", boolrenderer, active=0))
        columnnames = ["Name", "Unit", "mean", "max", "current"]
        for i, column in enumerate(columnnames):
            tcolumn = Gtk.TreeViewColumn(column, textrenderer, text=i + 1)
            self.tree.append_column(tcolumn)
            #if i == 0:
            #    tcolumn.set_sort_column_id(i+1)

        for plotsignal in self.Plotsignals:
            self.signalstore.append([
                plotsignal.plotenable, plotsignal.name,
                convert_to_si(plotsignal.unit)[0], '0', '0', '0'
            ])
        self.tree.set_model(self.signalstore)

    def update_signals(self):
        # Retrieve signal and set appropriate values in signalstore to update left pane in GUI
        for i, Plotsignal in enumerate(self.Plotsignals):
            Plotsignal.retrieve_data(self.maxpoints)
            self.signalstore[i][3] = str(
                np.around(
                    convert_to_si(Plotsignal.unit, Plotsignal.get_mean())[1],
                    self.precision))
            self.signalstore[i][4] = str(
                np.around(
                    convert_to_si(Plotsignal.unit, Plotsignal.get_max())[1],
                    self.precision))
            self.signalstore[i][5] = str(
                np.around(
                    convert_to_si(Plotsignal.unit,
                                  Plotsignal.get_last_value())[1],
                    self.precision))

    def on_cell_toggled(self, widget, path):
        self.signalstore[path][0] = not self.signalstore[path][0]
        self.Plotsignals[int(
            path)].plotenable = not self.Plotsignals[int(path)].plotenable
        self.update_plot()

    def update_plot(self):
        self.ax.clear()
        for Plotsignal in self.Plotsignals:
            if Plotsignal.plotenable:
                self.ax.plot(convert_to_si(Plotsignal.unit,
                                           Plotsignal.get_values())[1],
                             color=Plotsignal.plotcolor)
        #self.plots = [self.ax.plot(values, color=plotcolor) for values, plotcolor in zip(self.y.T, self.signalcolors)]
        self.ax.get_yaxis().set_visible(True)
        self.ax.get_xaxis().set_visible(True)
        self.canvas.draw()
        self.canvas.flush_events()

    def refresh(self):
        # This is run in thread
        self.update_signals()
        self.update_plot()
コード例 #19
0
ファイル: kfit.py プロジェクト: rhroberts/kfit
class App(Gtk.Application):

    def __init__(self):
        '''
        Build GUI
        '''
        # build GUI from glade file
        self.builder = Gtk.Builder()
        self.glade_file = os.path.join(curr_dir, 'kfit.glade')
        self.builder.add_from_file(self.glade_file)
        # get the necessary ui objects
        self.main_window = self.builder.get_object('main_window')
        self.graph_box = self.builder.get_object('graph_box')
        self.gau_sw = self.builder.get_object('param_scroll_gau')
        self.lor_sw = self.builder.get_object('param_scroll_lor')
        self.voi_sw = self.builder.get_object('param_scroll_voi')
        self.lin_sw = self.builder.get_object('param_scroll_lin')
        self.param_viewport_gau = self.builder.get_object('param_viewport_gau')
        self.param_viewport_lor = self.builder.get_object('param_viewport_lor')
        self.param_viewport_voi = self.builder.get_object('param_viewport_voi')
        self.param_viewport_lin = self.builder.get_object('param_viewport_lin')
        self.statusbar_viewport = self.builder.get_object('statusbar_viewport')
        self.data_treeview = self.builder.get_object('data_treeview')
        self.column_entry_x = self.builder.get_object('column_entry_x')
        self.column_entry_y = self.builder.get_object('column_entry_y')
        self.graph_box = self.builder.get_object('graph_box')
        self.fname_textview = self.builder.get_object('fname_textview')
        self.fit_button = self.builder.get_object('fit_button')
        self.reset_button = self.builder.get_object('reset_button')
        self.settings_button = self.builder.get_object('settings_button')
        self.import_button = self.builder.get_object('import_button')
        self.export_button = self.builder.get_object('export_button')
        self.help_button = self.builder.get_object('help_button')
        self.output_textview = self.builder.get_object('output_textview')
        self.settings_dialog = self.builder.get_object('settings_dialog')
        self.sep_entry = self.builder.get_object('sep_entry')
        self.header_entry = self.builder.get_object('header_entry')
        self.skiprows_entry = self.builder.get_object('skiprows_entry')
        self.dtype_entry = self.builder.get_object('dtype_entry')
        self.encoding_entry = self.builder.get_object('encoding_entry')
        self.fit_method_entry = self.builder.get_object('fit_method_entry')
        self.add_gau = self.builder.get_object('add_gau')
        self.rem_gau = self.builder.get_object('rem_gau')
        self.add_lor = self.builder.get_object('add_lor')
        self.rem_lor = self.builder.get_object('rem_lor')
        self.add_voi = self.builder.get_object('add_voi')
        self.rem_voi = self.builder.get_object('rem_voi')
        self.add_lin = self.builder.get_object('add_lin')
        self.rem_lin = self.builder.get_object('rem_lin')

        # define other class attributes
        self.title = 'kfit'
        self.file_name = ''
        self.xcol_idx = 0
        self.ycol_idx = 1
        self.cmode_state = 0
        self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)

        # configure help button
        self.help_button.set_label(' Help')
        help_image = Gtk.Image()
        help_image.set_from_file(
            os.path.join(curr_dir, '../images/dialog-question-symbolic.svg')
        )
        self.help_button.set_image(help_image)
        self.help_button.set_always_show_image(True)

        # for graph...
        x = np.linspace(0, 10, 500)
        y = models.gauss(x, 0.5, 4, 0.4) + \
            models.gauss(x, 0.8, 5, 0.2) + \
            models.gauss(x, 0.4, 6, 0.3) + 0.2
        self.data = pd.DataFrame([x, y]).T
        self.data.columns = ['x', 'y']
        self.x = self.data['x'].values
        self.y = self.data['y'].values
        self.xmin = self.data['x'].min()
        self.xmax = self.data['x'].max()
        plt.style.use(os.path.join(curr_dir, 'kfit.mplstyle'))
        self.figure = Figure(figsize=(10, 4), dpi=60)
        self.canvas = FigureCanvas(self.figure)
        self.canvas.set_size_request(900, 400)
        self.toolbar = NavigationToolbar(self.canvas, self.main_window)
        self.graph_box.pack_start(self.toolbar, True, True, 0)
        self.graph_box.pack_start(self.canvas, True, True, 0)
        self.cmode_toolitem = Gtk.ToolItem()
        self.cmode_box = Gtk.Box()
        self.cmode_box.set_margin_start(24)
        self.cmode_box.set_margin_end(36)
        self.cmode_radio_off = Gtk.RadioButton.new_with_label_from_widget(
            None, label='off'
        )
        self.cmode_radio_off.connect('toggled', self.toggle_copy_mode)
        self.cmode_radio_x = Gtk.RadioButton.new_from_widget(
            self.cmode_radio_off
        )
        self.cmode_radio_x.set_label('x')
        self.cmode_radio_x.connect('toggled', self.toggle_copy_mode)
        self.cmode_radio_y = Gtk.RadioButton.new_from_widget(
            self.cmode_radio_off
        )
        self.cmode_radio_y.set_label('y')
        self.cmode_radio_y.connect('toggled', self.toggle_copy_mode)
        self.cmode_box.pack_start(
            Gtk.Label(label='Copy mode:'), False, False, 0
        )
        self.cmode_box.pack_start(self.cmode_radio_off, False, False, 0)
        self.cmode_box.pack_start(self.cmode_radio_x, False, False, 0)
        self.cmode_box.pack_start(self.cmode_radio_y, False, False, 0)
        self.cmode_toolitem.add(self.cmode_box)
        self.toolbar.insert(self.cmode_toolitem, -1)

        # for fit...
        self.fit_method = 'least_squares'
        self.model = None
        self.result = None
        self.yfit = None
        self.ngau = 0
        self.nlor = 0
        self.nvoi = 0
        self.nlin = 1
        self.curves_df = None
        self.params_df = None
        self.params = Parameters()
        self.guesses = {
            'value': {},
            'min': {},
            'max': {}
        }
        self.usr_vals = {
            'value': {},
            'min': {},
            'max': {}
        }
        self.usr_entry_widgets = {}
        self.cid = None

        # for data view...
        self.fname_buffer = Gtk.TextBuffer()
        self.display_data()

        # for output...
        self.output_buffer = Gtk.TextBuffer()
        self.output_textview.set_buffer(self.output_buffer)

        # file import settings
        self.sep = ','
        self.header = 'infer'
        self.index_col = None
        self.skiprows = None
        self.dtype = None
        self.encoding = None

        # show initial plot
        self.plot()

        # add statusbar
        self.statusbar = Gtk.Statusbar()
        self.statusbar.set_margin_top(0)
        self.statusbar.set_margin_bottom(0)
        self.statusbar.set_margin_start(0)
        self.statusbar.set_margin_end(0)
        self.statusbar_viewport.add(self.statusbar)

        # connect signals
        events = {
            'on_fit_button_clicked': self.fit,
            'on_import_button_clicked': self.get_data,
            'on_settings_button_clicked': self.run_settings_dialog,
            'on_reset_button_clicked': self.hard_reset,
            'on_add_gau_clicked': self.on_add_gau_clicked,
            'on_rem_gau_clicked': self.on_rem_gau_clicked,
            'on_add_lor_clicked': self.on_add_lor_clicked,
            'on_rem_lor_clicked': self.on_rem_lor_clicked,
            'on_add_voi_clicked': self.on_add_voi_clicked,
            'on_rem_voi_clicked': self.on_rem_voi_clicked,
            'on_add_lin_clicked': self.on_add_lin_clicked,
            'on_rem_lin_clicked': self.on_rem_lin_clicked,
            'on_column_entry_changed': self.get_column_index,
            'on_export_button_clicked': self.export_data,
        }
        self.builder.connect_signals(events)

        # add accelerators / keyboard shortcuts
        self.accelerators = Gtk.AccelGroup()
        self.main_window.add_accel_group(self.accelerators)
        self.add_accelerator(self.fit_button, '<Control>f')
        self.add_accelerator(self.reset_button, '<Control>r')
        self.add_accelerator(self.settings_button, '<Control>p')
        self.add_accelerator(self.import_button, '<Control>o')
        self.add_accelerator(self.export_button, '<Control>s')
        self.add_accelerator(self.add_gau, 'g')
        self.add_accelerator(self.rem_gau, '<Shift>g')
        self.add_accelerator(self.add_lor, 'l')
        self.add_accelerator(self.rem_lor, '<Shift>l')
        self.add_accelerator(self.add_voi, 'v')
        self.add_accelerator(self.rem_voi, '<Shift>v')
        self.add_accelerator(self.add_lin, 'n')
        self.add_accelerator(self.rem_lin, '<Shift>n')

        # configure interface
        self.main_window.connect('destroy', Gtk.main_quit)

        self.init_param_widgets()
        # show the app window
        self.main_window.show_all()

    def plot(self):
        self.figure.clear()
        self.axis = self.figure.add_subplot(111)
        self.set_xlims()
        if len(self.x) >= 1000:
            self.axis.plot(
                self.x, self.y, c='#af87ff',
                linewidth=12, label='data'
            )
        else:
            self.axis.scatter(
                self.x, self.y, s=200, c='#af87ff',
                edgecolors='black', linewidth=1,
                label='data'
            )
        if self.result is not None:
            self.yfit = self.result.best_fit
            self.axis.plot(self.x, self.yfit, c='r', linewidth=2.5)
            cmap = cm.get_cmap('gnuplot')
            components = self.result.eval_components()
            for i, comp in enumerate(components):
                self.axis.plot(
                    self.x, components[comp],
                    linewidth=2.5, linestyle='--',
                    c=cmap(i/len(components)),
                    label=comp[:comp.find('_')]
                )
        self.axis.set_xlabel(self.data.columns[self.xcol_idx])
        self.axis.set_ylabel(self.data.columns[self.ycol_idx])
        self.axis.legend(loc='best')
        self.axis.set_xlim([self.xmin, self.xmax])
        self.canvas.draw()

    def fit(self, source=None, event=None):
        self.cmode_radio_off.set_active(True)
        self.toggle_copy_mode(self.cmode_radio_off)
        self.set_xrange_to_zoom()
        self.filter_nan()
        self.set_params()
        self.result = self.model.fit(
            data=self.y, params=self.params, x=self.x,
            method=self.fit_method
        )
        self.output_buffer.set_text(self.result.fit_report())
        self.plot()
        # overwrite widgets to clear input (not ideal method..)
        self.init_param_widgets()

    def init_model(self):
        # note: increment() ensures nlin >= 1
        self.model = models.line_mod(self.nlin)
        if self.ngau != 0:
            self.model += models.gauss_mod(self.ngau)
        if self.nlor != 0:
            self.model += models.lor_mod(self.nlor)
        if self.nvoi != 0:
            self.model += models.voigt_mod(self.nvoi)
        self.statusbar.push(
                self.statusbar.get_context_id('info'),
                "Model updated: " +
                str([self.ngau, self.nlor, self.nvoi, self.nlin])
        )

    def init_param_widgets(self):
        self.init_model()
        self.usr_entry_widgets = {
            'value': {},
            'min': {},
            'max': {}
        }
        labels = {}
        rnd = 3  # decimals to round to in placeholder text
        self.clear_param_viewports()

        # main boxes to hold user entry widgets
        self.vbox_gau = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        self.vbox_lor = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        self.vbox_voi = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        self.vbox_lin = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        for param_name in self.model.param_names:
            # set param label text
            labels[param_name] = Gtk.Label()
            labels[param_name].set_text(param_name)

            # make user entry widgets
            for key in self.usr_entry_widgets:
                self.usr_entry_widgets[key][param_name] = Gtk.Entry()
                if param_name in self.usr_vals[key]:
                    self.usr_entry_widgets[key][param_name]\
                        .set_placeholder_text(
                            str(round(self.usr_vals[key][param_name], rnd))
                        )
                else:
                    self.usr_entry_widgets[key][param_name]\
                        .set_placeholder_text(key)
                # set up connections
                self.usr_entry_widgets[key][param_name].connect(
                    'changed', self.update_usr_vals, self.usr_entry_widgets
                )

            # add widgets to respective layouts
            vbox_sub = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
            for key in self.usr_entry_widgets:
                vbox_sub.pack_start(
                    self.usr_entry_widgets[key][param_name],
                    False, False, pad
                )
            if param_name.find('gau') != -1:
                self.vbox_gau.pack_start(labels[param_name], False, False, pad)
                self.vbox_gau.pack_start(vbox_sub, False, False, pad)
                self.vbox_gau.set_halign(Gtk.Align.CENTER)
            if param_name.find('lor') != -1:
                self.vbox_lor.pack_start(labels[param_name], False, False, pad)
                self.vbox_lor.pack_start(vbox_sub, False, False, pad)
                self.vbox_lor.set_halign(Gtk.Align.CENTER)
            if param_name.find('voi') != -1:
                self.vbox_voi.pack_start(labels[param_name], False, False, pad)
                self.vbox_voi.pack_start(vbox_sub, False, False, pad)
                self.vbox_voi.set_halign(Gtk.Align.CENTER)
            if param_name.find('lin') != -1:
                self.vbox_lin.pack_start(labels[param_name], False, False, pad)
                self.vbox_lin.pack_start(vbox_sub, False, False, pad)
                self.vbox_lin.set_halign(Gtk.Align.CENTER)

        # Resize all of the entry widgets
        for key in self.usr_entry_widgets:
            for param, widget in self.usr_entry_widgets[key].items():
                widget.set_width_chars(7)

        # add/replace box in viewport
        self.param_viewport_gau.add(self.vbox_gau)
        self.param_viewport_lor.add(self.vbox_lor)
        self.param_viewport_voi.add(self.vbox_voi)
        self.param_viewport_lin.add(self.vbox_lin)
        for viewport in [self.param_viewport_gau, self.param_viewport_lor,
                         self.param_viewport_voi, self.param_viewport_lin]:
            viewport.show_all()

        if self.result is not None:
            self.set_params()
            self.update_param_widgets()

    def update_usr_vals(self, widget, entry_widget_dict):
        # get text input from each usr_entry_widget
        for val_type, param_dict in entry_widget_dict.items():
            for param, param_widget in param_dict.items():
                try:
                    self.usr_vals[val_type][param] = \
                        float(param_widget.get_text())
                except Exception:
                    pass

    def update_param_widgets(self):
        rnd = 3
        # the 'value' placeholder text is the result for that param
        # taken from self.result
        # the 'min' and 'max' text is from either the self.guesses
        # or from self.usr_vals
        for param in self.params:
            if param in self.result.best_values:
                self.usr_entry_widgets['value'][param].set_placeholder_text(
                    str(round(self.result.best_values[param], rnd))
                )
                self.usr_entry_widgets['min'][param].set_placeholder_text(
                    str(round(self.params[param].min, rnd))
                )
                self.usr_entry_widgets['max'][param].set_placeholder_text(
                    str(round(self.params[param].max, rnd))
                )

    def guess_params(self, source=None, event=None):
        for comp in self.model.components:
            if comp.prefix.find('gau') != -1 or \
                    comp.prefix.find('lor') != -1 or \
                    comp.prefix.find('voi') != -1:

                # need to define explicitly to make proper guesses
                c = comp.prefix + 'center'
                a = comp.prefix + 'amplitude'
                s = comp.prefix + 'sigma'
                f = comp.prefix + 'fraction'

                self.guesses['value'][c] = \
                    self.data.iloc[:, self.xcol_idx].mean()
                self.guesses['value'][a] = \
                    self.data.iloc[:, self.ycol_idx].mean()
                self.guesses['value'][s] = \
                    self.data.iloc[:, self.xcol_idx].std()
                self.guesses['min'][c] = None
                self.guesses['min'][a] = 0
                self.guesses['min'][s] = 0
                self.guesses['max'][c] = None
                self.guesses['max'][a] = None
                self.guesses['max'][s] = None

                if comp.prefix.find('voi') != -1:
                    self.guesses['value'][f] = 0.5
                    self.guesses['min'][f] = 0
                    self.guesses['max'][f] = 1
            else:
                slope = comp.prefix + 'slope'
                intc = comp.prefix + 'intercept'
                for p in [slope, intc]:
                    self.guesses['value'][p] = \
                        self.data.iloc[:, self.ycol_idx].mean()
                    self.guesses['min'][p] = None
                    self.guesses['max'][p] = None

    def set_params(self, source=None, event=None):
        self.params = Parameters()
        self.guess_params()
        self.update_usr_vals(None, self.usr_entry_widgets)
        vals = {}

        # fill params with any user-entered values
        # fill in blanks with guesses
        for param_name in self.model.param_names:
            for val_type in ['value', 'min', 'max']:
                if param_name in self.usr_vals[val_type]:
                    vals[val_type] = self.usr_vals[val_type][param_name]
                else:
                    vals[val_type] = self.guesses[val_type][param_name]
            self.params.add(
                name=param_name, value=vals['value'], vary=True,
                min=vals['min'], max=vals['max']
            )

    def set_xlims(self, source=None, event=None):
        self.xmin = np.min(self.x) - 0.02*(np.max(self.x) - np.min(self.x))
        self.xmax = np.max(self.x) + 0.02*(np.max(self.x) - np.min(self.x))

    def set_xrange_to_zoom(self):
        self.xmin, self.xmax = self.axis.get_xlim()
        range_bool = (self.x >= self.xmin) & (self.x <= self.xmax)
        self.x = self.x[range_bool]
        self.y = self.y[range_bool]

    def filter_nan(self):
        if True in np.isnan(self.x) or True in np.isnan(self.y):
            nanbool = (~np.isnan(self.x) & ~np.isnan(self.y))
            self.x = self.x[nanbool]
            self.y = self.y[nanbool]

    def increment(self, val, add):
        if add:
            if val == 'gau':
                self.ngau += 1
            if val == 'lor':
                self.nlor += 1
            if val == 'voi':
                self.nvoi += 1
            if val == 'lin':
                self.nlin += 1
        if not add:
            if val == 'gau':
                self.ngau -= 1
            if val == 'lor':
                self.nlor -= 1
            if val == 'voi':
                self.nvoi -= 1
            if val == 'lin':
                self.nlin -= 1

        # make sure value doesn't go below zero
        if self.ngau < 0:
            self.ngau = 0
        if self.nlor < 0:
            self.nlor = 0
        if self.nvoi < 0:
            self.nvoi = 0
        if self.nlin < 1:
            self.nlin = 1

    def clear_param_viewports(self):
        # clear any existing widgets from viewports
        for viewport in [self.param_viewport_gau, self.param_viewport_lin,
                         self.param_viewport_lor, self.param_viewport_voi]:
            if viewport.get_child():
                viewport.remove(viewport.get_child())

    def hard_reset(self, source=None, event=None):
        self.clear_param_viewports()
        self.ngau = 0
        self.nlor = 0
        self.nvoi = 0
        self.nlin = 1
        self.init_model()
        self.params = Parameters()
        self.result = None
        self.params_df = None
        self.curves_df = None
        self.guesses = {
            'value': {},
            'min': {},
            'max': {}
        }
        self.usr_vals = {
            'value': {},
            'min': {},
            'max': {}
        }
        self.output_buffer.set_text('')
        self.init_param_widgets()
        self.get_column_index()
        self.plot()
        self.cmode_radio_off.set_active(True)
        self.toggle_copy_mode(self.cmode_radio_off)

    def on_add_gau_clicked(self, source=None, event=None):
        self.increment('gau', True)
        self.init_param_widgets()

    def on_rem_gau_clicked(self, source=None, event=None):
        self.increment('gau', False)
        self.init_param_widgets()

    def on_add_lor_clicked(self, source=None, event=None):
        self.increment('lor', True)
        self.init_param_widgets()

    def on_rem_lor_clicked(self, source=None, event=None):
        self.increment('lor', False)
        self.init_param_widgets()

    def on_add_voi_clicked(self, source=None, event=None):
        self.increment('voi', True)
        self.init_param_widgets()

    def on_rem_voi_clicked(self, source=None, event=None):
        self.increment('voi', False)
        self.init_param_widgets()

    def on_add_lin_clicked(self, source=None, event=None):
        self.increment('lin', True)
        self.init_param_widgets()

    def on_rem_lin_clicked(self, source=None, event=None):
        self.increment('lin', False)
        self.init_param_widgets()

    def get_data(self, source=None, event=None):
        self.cmode_radio_off.set_active(True)
        self.toggle_copy_mode(self.cmode_radio_off)
        # reset column indices
        self.xcol_idx = 0
        self.column_entry_x.set_text(str(self.xcol_idx))
        self.ycol_idx = 1
        self.column_entry_y.set_text(str(self.ycol_idx))
        # open file dialog
        self.dialog = Gtk.FileChooserDialog(
            title='Import data file...', parent=self.main_window,
            action=Gtk.FileChooserAction.OPEN,
        )
        self.dialog.add_buttons(
            Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
            Gtk.STOCK_OPEN, Gtk.ResponseType.OK
        )
        filter_csv = Gtk.FileFilter()
        filter_csv.set_name('.csv files')
        filter_csv.add_mime_type('text/csv')
        self.dialog.add_filter(filter_csv)

        filter_any = Gtk.FileFilter()
        filter_any.set_name('All files')
        filter_any.add_pattern("*")
        self.dialog.add_filter(filter_any)
        self.dialog.set_default_size(800, 400)

        response = self.dialog.run()
        if response == Gtk.ResponseType.OK:
            self.file_name = self.dialog.get_filename()
            try:
                df = tools.to_df(
                    self.file_name, sep=self.sep, header=self.header,
                    index_col=self.index_col, skiprows=self.skiprows,
                    dtype=self.dtype, encoding=self.encoding
                )
                df.iloc[:, self.xcol_idx]
                df.iloc[:, self.ycol_idx]
            except Exception:
                self.statusbar.push(
                    self.statusbar.get_context_id('import_error'),
                    file_import_error_msg
                )
                self.dialog.destroy()
                return
        else:
            self.file_name = None
            self.statusbar.push(
                self.statusbar.get_context_id('import_canceled'),
                'Import canceled.'
            )
            self.dialog.destroy()
            return

        self.dialog.destroy()

        self.data = df
        self.display_data()
        self.result = None
        # reset x, y, and xlim
        self.x = self.data.iloc[:, self.xcol_idx].values
        self.y = self.data.iloc[:, self.ycol_idx].values
        self.filter_nan()
        self.set_xlims()
        self.plot()
        self.statusbar.push(
            self.statusbar.get_context_id('import_finished'),
            'Imported {}'.format(self.file_name)
        )

    def display_data(self):
        # remove any pre-existing columns from treeview
        for col in self.data_treeview.get_columns():
            self.data_treeview.remove_column(col)
        # create model
        # TODO: allow for other types, and infer from data
        col_types = [float for col in self.data.columns]
        list_store = Gtk.ListStore(*col_types)

        # fill model with data
        for row in self.data.itertuples():
            list_store.append(
                [row[i+1] for i, col in enumerate(self.data.columns)]
            )
        # set it as TreeView model
        self.data_treeview.set_model(list_store)
        # Create and append columns
        for i, col in enumerate(self.data.columns):
            renderer = Gtk.CellRendererText()
            column = Gtk.TreeViewColumn(col, renderer, text=i)
            self.data_treeview.append_column(column)
        self.fname_buffer.set_text('Source:  {}'.format(self.file_name))
        self.fname_textview.set_buffer(self.fname_buffer)

    def export_data(self, source=None, event=None):
        '''
        Export fit data and parameters to .csv
        '''
        self.file_export_dialog = Gtk.FileChooserDialog(
            title='Export results file...', parent=self.main_window,
            action=Gtk.FileChooserAction.SAVE,
        )
        self.file_export_dialog.add_buttons(
            Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
            Gtk.STOCK_OK, Gtk.ResponseType.OK
        )
        filter_csv = Gtk.FileFilter()
        filter_csv.set_name('.csv files')
        filter_csv.add_mime_type('text/csv')
        self.file_export_dialog.add_filter(filter_csv)
        response = self.file_export_dialog.run()

        if response == Gtk.ResponseType.OK:
            export_filename = self.file_export_dialog.get_filename()
            if export_filename.find('.csv') == -1:
                export_filename += '.csv'
            self.process_results()
            self.curves_df.to_csv(export_filename)
            self.params_df.to_csv(
                '{}.params.csv'.format(
                    export_filename[:export_filename.find('.csv')]
                )
            )
            self.statusbar.push(
                self.statusbar.get_context_id('export_results'),
                'Exported: {}'.format(export_filename)
            )
        else:
            self.statusbar.push(
                self.statusbar.get_context_id('export_canceled'),
                'Export canceled.'
            )
        self.file_export_dialog.hide()

    def process_results(self):
        if self.result is not None:
            self.params_df = pd.DataFrame.from_dict(
                self.result.best_values, orient='index'
            )
            self.params_df.index.name = 'parameter'
            self.params_df.columns = ['value']
            curves_dict = {
                'data': self.y,
                'total_fit': self.result.best_fit,
            }
            components = self.result.eval_components()
            for i, comp in enumerate(components):
                curves_dict[comp[:comp.find('_')]] = components[comp]
            self.curves_df = pd.DataFrame.from_dict(curves_dict)
            self.curves_df.index = self.x
            self.curves_df.index.name = self.data.columns[self.xcol_idx]
        else:
            self.statusbar.push(
                self.statusbar.get_context_id('no_fit_results'),
                'No fit results to export!'
            )
            self.file_export_dialog.hide()

    def get_column_index(self, source=None, event=None):
        # make sure user enters index that can be converted to int
        try:
            idx_x = int(self.column_entry_x.get_text())
        except ValueError:
            self.statusbar.push(
                self.statusbar.get_context_id('idx_type_error'),
                idx_type_error_msg
            )
            self.column_entry_x.set_text('')
            return
        try:
            idx_y = int(self.column_entry_y.get_text())
        except ValueError:
            self.statusbar.push(
                self.statusbar.get_context_id('idx_type_error'),
                idx_type_error_msg
                )
            self.column_entry_y.set_text('')
            return
        self.xcol_idx = idx_x
        self.ycol_idx = idx_y
        self.result = None
        # make sure user enters an index that's in the data range
        try:
            self.x = self.data.iloc[:, self.xcol_idx]
        except IndexError:
            self.statusbar.push(
                self.statusbar.get_context_id('idx_range_error'),
                idx_range_error_msg
            )
            self.column_entry_x.set_text(None)
            return
        try:
            self.y = self.data.iloc[:, self.ycol_idx]
        except IndexError:
            self.statusbar.push(
                self.statusbar.get_context_id('idx_range_error'),
                idx_range_error_msg
            )
            self.column_entry_y.set_text(None)
            return
        self.xmin = np.min(self.x)
        self.xmax = np.max(self.x)
        self.statusbar.push(
            self.statusbar.get_context_id('new_idx_success'),
            'Column Index (X) = ' + str(self.xcol_idx) + ', ' +
            'Column Index (Y) = ' + str(self.ycol_idx)
        )
        self.plot()

    def run_settings_dialog(self, source=None, event=None):
        '''
        Opens the settings dialog window and controls its behavior.
        '''
        # set label text for help button
        # couldn't do this in glade for some reason...
        import_help_button = self.builder.get_object('import_help_button')
        import_help_button.set_label('help')
        fit_help_button = self.builder.get_object('fit_help_button')
        fit_help_button.set_label('help')
        # run the dialog
        response = self.settings_dialog.run()

        if response == Gtk.ResponseType.APPLY:
            self.sep = self.sep_entry.get_text()
            if self.header_entry.get_text() != 'infer':
                self.header = int(self.header_entry.get_text())
            else:
                self.header = 'infer'
            if self.skiprows_entry.get_text() == 'None':
                self.skiprows = None
            else:
                self.skiprows = int(self.skiprows_entry.get_text())
            if self.dtype_entry.get_text() == 'None':
                self.dtype = None
            else:
                self.dtype = self.dtype_entry.get_text()
            if self.encoding_entry.get_text() == 'None':
                self.encoding = None
            else:
                self.encoding = self.encoding_entry.get_text()
            if self.fit_method_entry.get_text() != 'least_squares':
                self.fit_method = self.fit_method_entry.get_text()
            else:
                self.fit_method = 'least_squares'
        else:
            self.settings_dialog.hide()

        self.settings_dialog.hide()

    def toggle_copy_mode(self, button):
        state_messages = {
            0: 'Copy mode off',
            1: 'Copy mode on | x-value',
            2: 'Copy mode on | y-value',
        }
        if button.get_active():
            if button.get_label() == 'x':
                self.cmode_state = 1
                self.mpl_cursor = Cursor(
                    self.axis, lw=1, c='red', linestyle='--'
                )
                self.cid = self.canvas.mpl_connect(
                    'button_press_event', self.get_coord_click
                )
            elif button.get_label() == 'y':
                self.cmode_state = 2
                self.mpl_cursor = Cursor(
                    self.axis, lw=1, c='red', linestyle='--'
                )
                self.cid = self.canvas.mpl_connect(
                    'button_press_event', self.get_coord_click
                )
            else:
                # copy mode off
                self.cmode_state = 0
                self.mpl_cursor = None
                self.canvas.mpl_disconnect(self.cid)

            self.statusbar.push(
                self.statusbar.get_context_id('cmode_state'),
                state_messages[self.cmode_state]
            )

    def get_coord_click(self, event):
        x_copy, y_copy = str(round(event.xdata, 3)), str(round(event.ydata, 3))
        if self.cmode_state == 1:
            self.clipboard.set_text(x_copy, -1)
            self.statusbar.push(
                    self.statusbar.get_context_id('copied_x'),
                    'Copied X=' + str(x_copy) + ' to clipboard!'
            )
        if self.cmode_state == 2:
            self.clipboard.set_text(y_copy, -1)
            self.statusbar.push(
                    self.statusbar.get_context_id('copied_y'),
                    'Copied Y=' + str(y_copy) + ' to clipboard!'
            )

    def add_accelerator(self, widget, accelerator, signal="activate"):
        '''
        Adds keyboard shortcuts
        '''
        if accelerator is not None:
            key, mod = Gtk.accelerator_parse(accelerator)
            widget.add_accelerator(
                signal, self.accelerators, key, mod, Gtk.AccelFlags.VISIBLE
            )
コード例 #20
0
class ConanReportGraphsPresenter(Presenter[Gtk.Stack]):
    spinner: TemplateChild[Gtk.Spinner] = TemplateChild('spinner')
    figure_container = TemplateChild('figure_container')  # type: TemplateChild[Gtk.Container]

    _analyses = ()

    @inject
    def __init__(self, graphs_service: ConanReportGraphsService) -> None:
        self.graphs_service = graphs_service

    def after_view_init(self) -> None:
        self.figure = Figure(tight_layout=False)

        self.figure_canvas = FigureCanvas(self.figure)
        self.figure_canvas.props.hexpand = True
        self.figure_canvas.props.vexpand = True
        self.figure_canvas.props.visible = True
        self.figure_container.add(self.figure_canvas)

        self.figure_canvas_mapped = False

        self.figure_canvas.connect('map', self.canvas_map)
        self.figure_canvas.connect('unmap', self.canvas_unmap)
        self.figure_canvas.connect('size-allocate', self.canvas_size_allocate)

        left_ca_ax, right_ca_ax = self.figure.subplots(2, 1, sharex='col')

        left_ca_ax.set_ylabel('Left CA [°]')
        left_ca_ax.tick_params(axis='x', direction='inout')

        right_ca_ax.xaxis.set_ticks_position('both')
        right_ca_ax.set_ylabel('Right CA [°]')
        right_ca_ax.tick_params(axis='x', direction='inout')

        left_ca_ax.tick_params(axis='y', left=False, labelleft=False, right=True, labelright=True)
        right_ca_ax.tick_params(axis='y', left=False, labelleft=False, right=True, labelright=True)

        # Format the labels to scale to the right units.
        left_ca_ax.get_yaxis().set_major_formatter(
            FuncFormatter(lambda x, _: '{:.4g}'.format(math.degrees(x)))
        )
        right_ca_ax.get_yaxis().set_major_formatter(
            FuncFormatter(lambda x, _: '{:.4g}'.format(math.degrees(x)))
        )

        left_ca_ax.grid(axis='x', linestyle='--', color="#dddddd")
        left_ca_ax.grid(axis='y', linestyle='-', color="#dddddd")

        right_ca_ax.grid(axis='x', linestyle='--', color="#dddddd")
        right_ca_ax.grid(axis='y', linestyle='-', color="#dddddd")

        self._left_ca_ax = left_ca_ax
        self._left_ca_line = left_ca_ax.plot([], marker='o', color='#0080ff')[0]
        self._right_ca_line = right_ca_ax.plot([], marker='o', color='#ff8000')[0]

        self.graphs_service.connect('notify::left-angle', self.data_changed)
        self.graphs_service.connect('notify::right-angle', self.data_changed)

        self.data_changed()

    def canvas_map(self, *_) -> None:
        self.figure_canvas_mapped = True
        self.figure_canvas.draw_idle()

    def canvas_unmap(self, *_) -> None:
        self.figure_canvas_mapped = False

    def canvas_size_allocate(self, *_) -> None:
        self.figure.tight_layout(pad=2.0, h_pad=0)
        self.figure.subplots_adjust(hspace=0)

    @install
    @GObject.Property
    def analyses(self) -> Sequence[ConanAnalysisJob]:
        return self._analyses

    @analyses.setter
    def analyses(self, analyses: Iterable[ConanAnalysisJob]) -> None:
        self._analyses = tuple(analyses)
        self.graphs_service.analyses = analyses

    def data_changed(self, *_) -> None:
        left_angle_data = self.graphs_service.left_angle
        right_angle_data = self.graphs_service.right_angle

        if left_angle_data.shape[1] <= 1 or right_angle_data.shape[1] <=1:
            self.show_waiting_placeholder()
            return

        self.hide_waiting_placeholder()

        self._left_ca_line.set_data(left_angle_data)
        self._right_ca_line.set_data(right_angle_data)

        self.update_xlim()

        self._left_ca_line.axes.relim()
        self._left_ca_line.axes.margins(y=0.1)
        self._right_ca_line.axes.relim()
        self._right_ca_line.axes.margins(y=0.1)

        self.figure_canvas.draw()

    def update_xlim(self) -> None:
        all_xdata = (
            *self._left_ca_line.get_xdata(),
            *self._right_ca_line.get_xdata(),
        )

        if len(all_xdata) <= 1:
            return

        xmin = min(all_xdata)
        xmax = max(all_xdata)

        if xmin == xmax:
            return

        self._left_ca_ax.set_xlim(xmin, xmax)

    def show_waiting_placeholder(self) -> None:
        self.host.set_visible_child(self.spinner)
        self.spinner.start()

    def hide_waiting_placeholder(self) -> None:
        self.host.set_visible_child(self.figure_container)
        self.spinner.stop()
コード例 #21
0
ファイル: graphs.py プロジェクト: wflk/king-phisher
class CampaignGraph(object):
	"""
	A basic graph provider for using :py:mod:`matplotlib` to create graph
	representations of campaign data. This class is meant to be subclassed
	by real providers.
	"""
	name = 'Unknown'
	"""The name of the graph provider."""
	name_human = 'Unknown'
	"""The human readable name of the graph provider used for UI identification."""
	graph_title = 'Unknown'
	"""The title that will be given to the graph."""
	table_subscriptions = []
	"""A list of tables from which information is needed to produce the graph."""
	is_available = True
	def __init__(self, application, size_request=None, style_context=None):
		"""
		:param tuple size_request: The size to set for the canvas.
		"""
		self.application = application
		self.style_context = style_context
		self.config = application.config
		"""A reference to the King Phisher client configuration."""
		self.figure, _ = pyplot.subplots()
		self.figure.set_facecolor(self.get_color('bg', ColorHexCode.WHITE))
		self.axes = self.figure.get_axes()
		self.canvas = FigureCanvas(self.figure)
		self.manager = None
		self.minimum_size = (380, 200)
		"""An absolute minimum size for the canvas."""
		if size_request is not None:
			self.resize(*size_request)
		self.canvas.mpl_connect('button_press_event', self.mpl_signal_canvas_button_pressed)
		self.canvas.show()
		self.navigation_toolbar = NavigationToolbar(self.canvas, self.application.get_active_window())
		self.popup_menu = Gtk.Menu.new()

		menu_item = Gtk.MenuItem.new_with_label('Export')
		menu_item.connect('activate', self.signal_activate_popup_menu_export)
		self.popup_menu.append(menu_item)

		menu_item = Gtk.MenuItem.new_with_label('Refresh')
		menu_item.connect('activate', lambda action: self.refresh())
		self.popup_menu.append(menu_item)

		menu_item = Gtk.CheckMenuItem.new_with_label('Show Toolbar')
		menu_item.connect('toggled', self.signal_toggled_popup_menu_show_toolbar)
		self._menu_item_show_toolbar = menu_item
		self.popup_menu.append(menu_item)
		self.popup_menu.show_all()
		self.navigation_toolbar.hide()
		self._legend = None

	@property
	def rpc(self):
		return self.application.rpc

	@staticmethod
	def _ax_hide_ticks(ax):
		for tick in ax.yaxis.get_major_ticks():
			tick.tick1On = False
			tick.tick2On = False

	@staticmethod
	def _ax_set_spine_color(ax, spine_color):
		for pos in ('top', 'right', 'bottom', 'left'):
			ax.spines[pos].set_color(spine_color)

	def _load_graph(self, info_cache):
		raise NotImplementedError()

	def add_legend_patch(self, legend_rows, fontsize=None):
		if self._legend is not None:
			self._legend.remove()
			self._legend = None
		if fontsize is None:
			scale = self.markersize_scale
			if scale < 5:
				fontsize = 'xx-small'
			elif scale < 7:
				fontsize = 'x-small'
			elif scale < 9:
				fontsize = 'small'
			else:
				fontsize = 'medium'
		legend_bbox = self.figure.legend(
			tuple(patches.Patch(color=patch_color) for patch_color, _ in legend_rows),
			tuple(label for _, label in legend_rows),
			borderaxespad=1.25,
			fontsize=fontsize,
			frameon=True,
			handlelength=1.5,
			handletextpad=0.75,
			labelspacing=0.3,
			loc='lower right'
		)
		legend_bbox.legendPatch.set_linewidth(0)
		self._legend = legend_bbox

	def get_color(self, color_name, default):
		"""
		Get a color by its style name such as 'fg' for foreground. If the
		specified color does not exist, default will be returned. The underlying
		logic for this function is provided by
		:py:func:`~.gui_utilities.gtk_style_context_get_color`.

		:param str color_name: The style name of the color.
		:param default: The default color to return if the specified one was not found.
		:return: The desired color if it was found.
		:rtype: tuple
		"""
		color_name = 'theme_color_graph_' + color_name
		sc_color = gui_utilities.gtk_style_context_get_color(self.style_context, color_name, default)
		return (sc_color.red, sc_color.green, sc_color.blue)

	def make_window(self):
		"""
		Create a window from the figure manager.

		:return: The graph in a new, dedicated window.
		:rtype: :py:class:`Gtk.Window`
		"""
		if self.manager is None:
			self.manager = FigureManager(self.canvas, 0)
		self.navigation_toolbar.destroy()
		self.navigation_toolbar = self.manager.toolbar
		self._menu_item_show_toolbar.set_active(True)
		window = self.manager.window
		window.set_transient_for(self.application.get_active_window())
		window.set_title(self.graph_title)
		return window

	@property
	def markersize_scale(self):
		bbox = self.axes[0].get_window_extent().transformed(self.figure.dpi_scale_trans.inverted())
		return bbox.width * self.figure.dpi * 0.01

	def mpl_signal_canvas_button_pressed(self, event):
		if event.button != 3:
			return
		self.popup_menu.popup(None, None, None, None, event.button, Gtk.get_current_event_time())
		return True

	def signal_activate_popup_menu_export(self, action):
		dialog = extras.FileChooserDialog('Export Graph', self.application.get_active_window())
		file_name = self.config['campaign_name'] + '.png'
		response = dialog.run_quick_save(file_name)
		dialog.destroy()
		if not response:
			return
		destination_file = response['target_path']
		self.figure.savefig(destination_file, format='png')

	def signal_toggled_popup_menu_show_toolbar(self, widget):
		if widget.get_property('active'):
			self.navigation_toolbar.show()
		else:
			self.navigation_toolbar.hide()

	def load_graph(self):
		"""Load the graph information via :py:meth:`.refresh`."""
		self.refresh()

	def refresh(self, info_cache=None, stop_event=None):
		"""
		Refresh the graph data by retrieving the information from the
		remote server.

		:param dict info_cache: An optional cache of data tables.
		:param stop_event: An optional object indicating that the operation should stop.
		:type stop_event: :py:class:`threading.Event`
		:return: A dictionary of cached tables from the server.
		:rtype: dict
		"""
		info_cache = (info_cache or {})
		if not self.rpc:
			return info_cache
		for table in self.table_subscriptions:
			if stop_event and stop_event.is_set():
				return info_cache
			if not table in info_cache:
				query_filter = None
				if 'campaign_id' in client_rpc.database_table_objects[table].__slots__:
					query_filter = {'campaign_id': self.config['campaign_id']}
				info_cache[table] = tuple(self.rpc.remote_table(table, query_filter=query_filter))
		for ax in self.axes:
			ax.clear()
		if self._legend is not None:
			self._legend.remove()
			self._legend = None
		self._load_graph(info_cache)
		self.figure.suptitle(
			self.graph_title,
			color=self.get_color('fg', ColorHexCode.BLACK),
			size=14,
			weight='bold',
			y=0.97
		)
		self.canvas.draw()
		return info_cache

	def resize(self, width=0, height=0):
		"""
		Attempt to resize the canvas. Regardless of the parameters the canvas
		will never be resized to be smaller than :py:attr:`.minimum_size`.

		:param int width: The desired width of the canvas.
		:param int height: The desired height of the canvas.
		"""
		min_width, min_height = self.minimum_size
		width = max(width, min_width)
		height = max(height, min_height)
		self.canvas.set_size_request(width, height)
コード例 #22
0
class Test:
    x1 = []
    y1 = []
    x2 = []
    y2 = []

    def __init__(self):
        self.interface = Gtk.Builder()
        self.interface.add_from_file('UI.glade')
        self.interface.connect_signals(self)
        self.window = self.interface.get_object('Main')

        # first
        self.sw1 = self.interface.get_object('firstScrolled')
        self.fig1 = Figure()
        self.a1 = self.fig1.add_subplot(111)
        self.a1.plot(self.x1, self.y1)
        self.canvas1 = FigureCanvas(self.fig1)
        self.sw1.add_with_viewport(self.canvas1)

        # second
        self.sw2 = self.interface.get_object('secondScrolled')
        self.fig2 = Figure(figsize=(5, 5), dpi=100)
        self.a2 = self.fig2.add_subplot(111)
        self.a2.plot(self.x2, self.y2)
        self.canvas2 = FigureCanvas(self.fig2)
        self.sw2.add_with_viewport(self.canvas2)

        self.window.show_all()

    def on_button1_clicked(self, widget):
        print("Exit")
        sys.exit()

    def on_button2_clicked(self, widget):
        print("Plot2")
        self.x1.clear()
        self.y1.clear()
        i = 0
        while i < 20:
            self.x1.append(random.random() * 100)
            self.y1.append(random.random() * 100)
            i = i + 1
        print(self.x1)
        print(self.y1)
        self.a1.clear()
        self.a1.plot(self.x1, self.y1)
        self.canvas1 = FigureCanvas(self.fig1)
        self.canvas1.draw()
        self.window.show_all()
        self.window.queue_draw()

    def on_button3_clicked(self, widget):
        self.x2.clear()
        self.y2.clear()
        print("Plot1")
        i = 0
        while i < 20:
            self.x2.append(random.random() * 100)
            self.y2.append(random.random() * 100)
            i = i + 1
        print(self.x2)
        print(self.y2)
        self.a2.clear()
        self.a2.plot(self.x2, self.y2)
        self.canvas2 = FigureCanvas(self.fig2)
        self.canvas2.draw()
        self.window.show_all()
        self.window.queue_draw()
コード例 #23
0
class Signal:
	'''Creates integration signal plot.'''
	X_Data               = []
	Y_Data               = []
	LifeZero             = 0.0
	IntegrationStart     = 0.0
	LifeZero             = 0.0
	
	def __init__(self):
		n = 1000        
		#print X
		#dataY = c.execute("SELECT data_value FROM MktSensorData WHERE data_creator = 1 and data_trigger = 1")
		#X =[]
		#Y =[]
		#
		#	X.append(row[0])
		#	Y.append(row[1])
		
		#print X
		#xsin = linspace(-pi, pi, n, endpoint=True)
		#xcos = linspace(-pi, pi, n, endpoint=True)
		#ysin = sin(xsin)
		#ycos = cos(xcos)
		#sinwave = ax.plot(dataX, dataY, color='blue', label='Signal')
		#formatter = DateFormatter('%S')
		self.fig = Figure(figsize=(10,10), dpi=80, facecolor='white')
		
		self.ax = self.fig.add_subplot(111)
		
		#ax.xaxis.set_major_formatter(formatter)

		#ax.set_xlim(-pi,pi)
		#ax.set_ylim(-1.2,1.2)
		#ax.fill_between(xsin, 0, ysin, (ysin - 1) > -1, color='blue', alpha=.3)
		#ax.fill_between(xsin, 0, ysin, (ysin - 1) < -1, color='red',  alpha=.3)
		#ax.fill_between(xcos, 0, ycos, (ycos - 1) > -1, color='blue', alpha=.3)
		#ax.fill_between(xcos, 0, ycos, (ycos - 1) < -1, color='red',  alpha=.3)
		#print "test 1!"
		#self.ax.legend(loc='upper left')
		#print "test 2!"
		#ax = fig.gca()
		#ax.spines['right'].set_color('none')
		#ax.spines['top'].set_color('none')
		#ax.xaxis.set_ticks_position('bottom')
		#ax.spines['bottom'].set_position(('data',0))
		#ax.yaxis.set_ticks_position('left')
		#ax.spines['left'].set_position(('data',0))
		#
		self.canvas = FigureCanvas(self.fig)
		#GLib.timeout_add_seconds(1, self.fast_update)
		#self.read = ReadStdin(self)
		#self.read.start()
	
	def clean_data(self):
		self.X_Data.clean()
		

	def auto_update(self):
		
		Cursor = self.Conn.cursor()
		print "SELECT ref_id,data_changed,data_value,data_type FROM "+self.data_base+" WHERE ref_id > "+str(self.last_id)+" and data_creator = "+str(self.data_creator)+" and data_trigger = "+str(self.data_trigger)+" LIMIT 6"
		data = Cursor.execute("SELECT ref_id,data_changed,data_value,data_type FROM "+self.data_base+" WHERE ref_id > "+str(self.last_id)+" and data_creator = "+str(self.data_creator)+" and data_trigger = "+str(self.data_trigger)+" LIMIT 6")
		life_zero     = 0.0
		starti        = 0.0
		stopi         = 0.0
		is_zero       = False
		r = data.fetchone()
		if r != None :
			for row in data:
				self.last_id=row[0]
				self.X.append(row[1]-self.start_time)
				self.Y.append(row[2])
				if row[3] == self.ULTIMATE_SIGNAL_JUSTIFICATED:
					life_zero = r[2]
					is_zero   = True
				if row[3] == self.ULTIMATE_SIGNAL_INTEGRATION_START:
					starti = row[1]-self.start_time
				if row[3] == self.ULTIMATE_SIGNAL_INTEGRATION_STOP:
					stopi  = row[1]-self.start_time
			
			self.ax.plot(self.X, self.Y, color='blue', label='Signal', linewidth=2)
			if is_zero == True:
				l = self.ax.axhline(y=life_zero,linewidth=1, color='r')
			if starti > 0.0:
				lsi = self.ax.axvline(x=starti,linewidth=1, color='g')
			if stopi > 0.0:
				lsti = self.ax.axvline(x=stopi,linewidth=2, color='r')
			self.canvas.draw()
		return True

			
	def update(self):

		print "Update signal plot"
		self.last_id       = 0
		self.start_time    = 0.0
		self.data_base     = ManSettings.get_value(self.DATABASE).get_string()
		self.data_creator  = ManSettings.get_value(self.REFERENCE).get_uint64()
		self.data_trigger  = ManSettings.get_value(self.TRIGGER).get_uint32()
		self.ax.clear()
		self.ax.grid(True)
		
		Cursor = self.Conn.cursor()
		data = Cursor.execute("SELECT ref_id,data_changed,data_value,data_type FROM "+self.data_base+" WHERE data_creator = "+str(self.data_creator)+" and data_trigger = "+str(self.data_trigger))
		#print "selected "+str(len(data.rowcount))+" data"
		#if data.rowcount > 0 :
		#	print "selected "+str(data.rowcoun)+" data"
		r = data.fetchone()
		life_zero     = 0.0
		starti        = 0.0
		stopi         = 0.0
		is_zero       = False
		self.X = array('f',[])
		self.Y = array('f',[])
		print "search data... "+self.data_base+" data creator="+str(self.data_creator)+" data_trigger="+str(self.data_trigger)
		if r != None :
			print "Find data ... "
			self.start_time = r[1]
			print str(self.start_time) + "test " + str(self.start_time-r[1])
			for row in data:
				self.last_id=row[0]
				self.X.append(row[1]-self.start_time)
				self.Y.append(row[2])
				if row[3] == self.ULTIMATE_SIGNAL_JUSTIFICATED:
					life_zero = r[2]
					is_zero   = True
				if row[3] == self.ULTIMATE_SIGNAL_INTEGRATION_START:
					starti = row[1]-self.start_time
				if row[3] == self.ULTIMATE_SIGNAL_INTEGRATION_STOP:
					stopi  = row[1]-self.start_time
			
			print "Stop I = "+str(starti)+"Stop I = "+str(stopi)+" data ... "
			self.ax.plot(self.X, self.Y, color='blue', label='Signal', linewidth=2)
			self.ax.set_ylim(-0.05,1.0)
			self.ax.set_ylabel("Signal [fsr]")
			self.ax.set_xlabel("Time [sec]")
			if is_zero == True:
				l = self.ax.axhline(y=life_zero,linewidth=1, color='r')
			if starti > 0.0:
				lsi = self.ax.axvline(x=starti,linewidth=1, color='g')
			if stopi > 0.0:
				lsti = self.ax.axvline(x=stopi,linewidth=2, color='r')

		else :
			self.ax.plot(self.X, self.Y, color='blue', label='Signal', linewidth=2)
			self.ax.set_ylim(-0.05,1.0)
			self.ax.set_ylabel("Signal [fsr]")
			self.ax.set_xlabel("Time [sec]")


		self.canvas.draw()


	def changed_main_settings(self,setting,property):
		if property == 'signal-trigger':
			self.auto_update()
		elif property != 'plug-id':
			self.update()
		print "change settings property "+property
コード例 #24
0
ファイル: graphs.py プロジェクト: baubaubau/king-phisher
class CampaignGraph(object):
	"""
	A basic graph provider for using :py:mod:`matplotlib` to create graph
	representations of campaign data. This class is meant to be subclassed
	by real providers.
	"""
	name = 'Unknown'
	"""The name of the graph provider."""
	name_human = 'Unknown'
	"""The human readable name of the graph provider used for UI identification."""
	graph_title = 'Unknown'
	"""The title that will be given to the graph."""
	table_subscriptions = []
	"""A list of tables from which information is needed to produce the graph."""
	is_available = True
	def __init__(self, config, parent, size_request=None):
		"""
		:param dict config: The King Phisher client configuration.
		:param parent: The parent window for this object.
		:type parent: :py:class:`Gtk.Window`
		:param tuple size_request: The size to set for the canvas.
		"""
		self.config = config
		"""A reference to the King Phisher client configuration."""
		self.parent = parent
		"""The parent :py:class:`Gtk.Window` instance."""
		self.figure, _ = pyplot.subplots()
		self.axes = self.figure.get_axes()
		self.canvas = FigureCanvas(self.figure)
		self.manager = None
		if size_request:
			self.canvas.set_size_request(*size_request)
		self.canvas.mpl_connect('button_press_event', self.mpl_signal_canvas_button_pressed)
		self.canvas.show()
		self.navigation_toolbar = NavigationToolbar(self.canvas, self.parent)
		self.popup_menu = Gtk.Menu.new()

		menu_item = Gtk.MenuItem.new_with_label('Export')
		menu_item.connect('activate', self.signal_activate_popup_menu_export)
		self.popup_menu.append(menu_item)

		menu_item = Gtk.MenuItem.new_with_label('Refresh')
		menu_item.connect('activate', lambda action: self.refresh())
		self.popup_menu.append(menu_item)

		menu_item = Gtk.CheckMenuItem.new_with_label('Show Toolbar')
		menu_item.connect('toggled', self.signal_toggled_popup_menu_show_toolbar)
		self._menu_item_show_toolbar = menu_item
		self.popup_menu.append(menu_item)
		self.popup_menu.show_all()
		self.navigation_toolbar.hide()

	def _load_graph(self, info_cache):
		raise NotImplementedError()

	def _graph_bar_set_yparams(self, top_lim):
		min_value = top_lim + (top_lim * 0.075)
		if min_value <= 25:
			scale = 5
		else:
			scale = scale = 10 ** (len(str(int(min_value))) - 1)
		inc_scale = scale
		while scale <= min_value:
			scale += inc_scale
		top_lim = scale

		ax = self.axes[0]
		yticks = set((round(top_lim * 0.5), top_lim))
		ax.set_yticks(tuple(yticks))
		ax.set_ylim(top=top_lim)
		return

	def _graph_null_pie(self, title):
		ax = self.axes[0]
		ax.pie((100,), labels=(title,), colors=(MPL_COLOR_NULL,), autopct='%1.0f%%', shadow=True, startangle=90)
		ax.axis('equal')
		return

	def add_legend_patch(self, legend_rows, fontsize=None):
		handles = []
		if not fontsize:
			scale = self.markersize_scale
			if scale < 5:
				fontsize = 'xx-small'
			elif scale < 7:
				fontsize = 'x-small'
			elif scale < 9:
				fontsize = 'small'
			else:
				fontsize = 'medium'
		for row in legend_rows:
			handles.append(patches.Patch(color=row[0], label=row[1]))
		self.axes[0].legend(handles=handles, fontsize=fontsize, loc='lower right')

	def graph_bar(self, bars, color=None, xticklabels=None, ylabel=None):
		"""
		Create a standard bar graph with better defaults for the standard use
		cases.

		:param list bars: The values of the bars to graph.
		:param color: The color of the bars on the graph.
		:type color: list, str
		:param list xticklabels: The labels to use on the x-axis.
		:param str ylabel: The label to give to the y-axis.
		:return: The bars created using :py:mod:`matplotlib`
		:rtype: `matplotlib.container.BarContainer`
		"""
		color = color or MPL_COLOR_NULL
		width = 0.25
		ax = self.axes[0]
		self._graph_bar_set_yparams(max(bars) if bars else 0)
		bars = ax.bar(range(len(bars)), bars, width, color=color)
		ax.set_xticks([float(x) + (width / 2) for x in range(len(bars))])
		if xticklabels:
			ax.set_xticklabels(xticklabels, rotation=30)
			for col in bars:
				height = col.get_height()
				ax.text(col.get_x() + col.get_width() / 2.0, height, "{0:,}".format(height), ha='center', va='bottom')
		if ylabel:
			ax.set_ylabel(ylabel)
		self.figure.subplots_adjust(bottom=0.25)
		return bars

	def make_window(self):
		"""
		Create a window from the figure manager.

		:return: The graph in a new, dedicated window.
		:rtype: :py:class:`Gtk.Window`
		"""
		if self.manager == None:
			self.manager = FigureManager(self.canvas, 0)
		self.navigation_toolbar.destroy()
		self.navigation_toolbar = self.manager.toolbar
		self._menu_item_show_toolbar.set_active(True)
		window = self.manager.window
		window.set_transient_for(self.parent)
		window.set_title(self.graph_title)
		return window

	@property
	def markersize_scale(self):
		bbox = self.axes[0].get_window_extent().transformed(self.figure.dpi_scale_trans.inverted())
		return max(bbox.width, bbox.width) * self.figure.dpi * 0.01

	def mpl_signal_canvas_button_pressed(self, event):
		if event.button != 3:
			return
		self.popup_menu.popup(None, None, None, None, event.button, Gtk.get_current_event_time())
		return True

	def signal_activate_popup_menu_export(self, action):
		dialog = gui_utilities.UtilityFileChooser('Export Graph', self.parent)
		file_name = self.config['campaign_name'] + '.png'
		response = dialog.run_quick_save(file_name)
		dialog.destroy()
		if not response:
			return
		destination_file = response['target_path']
		self.figure.savefig(destination_file, format='png')

	def signal_toggled_popup_menu_show_toolbar(self, widget):
		if widget.get_property('active'):
			self.navigation_toolbar.show()
		else:
			self.navigation_toolbar.hide()

	def load_graph(self):
		"""Load the graph information via :py:meth:`.refresh`."""
		self.refresh()

	def refresh(self, info_cache=None, stop_event=None):
		"""
		Refresh the graph data by retrieving the information from the
		remote server.

		:param dict info_cache: An optional cache of data tables.
		:param stop_event: An optional object indicating that the operation should stop.
		:type stop_event: :py:class:`threading.Event`
		:return: A dictionary of cached tables from the server.
		:rtype: dict
		"""
		info_cache = (info_cache or {})
		if not self.parent.rpc:
			return info_cache
		for table in self.table_subscriptions:
			if stop_event and stop_event.is_set():
				return info_cache
			if not table in info_cache:
				info_cache[table] = tuple(self.parent.rpc.remote_table('campaign/' + table, self.config['campaign_id']))
		for ax in self.axes:
			ax.clear()
		self._load_graph(info_cache)
		self.axes[0].set_title(self.graph_title, y=1.03)
		self.canvas.draw()
		return info_cache
コード例 #25
0
ファイル: graphs.py プロジェクト: piratica/king-phisher
class CampaignGraph(object):
	"""
	A basic graph provider for using :py:mod:`matplotlib` to create graph
	representations of campaign data. This class is meant to be subclassed
	by real providers.
	"""
	name = 'Unknown'
	"""The name of the graph provider."""
	name_human = 'Unknown'
	"""The human readable name of the graph provider used for UI identification."""
	graph_title = 'Unknown'
	"""The title that will be given to the graph."""
	table_subscriptions = []
	"""A list of tables from which information is needed to produce the graph."""
	is_available = True
	def __init__(self, application, size_request=None, style_context=None):
		"""
		:param tuple size_request: The size to set for the canvas.
		"""
		self.application = application
		self.style_context = style_context
		self.config = application.config
		"""A reference to the King Phisher client configuration."""
		self.figure, _ = pyplot.subplots()
		self.figure.set_facecolor(self.get_color('bg', ColorHexCode.WHITE))
		self.axes = self.figure.get_axes()
		self.canvas = FigureCanvas(self.figure)
		self.manager = None
		if size_request:
			self.canvas.set_size_request(*size_request)
		self.canvas.mpl_connect('button_press_event', self.mpl_signal_canvas_button_pressed)
		self.canvas.show()
		self.navigation_toolbar = NavigationToolbar(self.canvas, self.application.get_active_window())
		self.popup_menu = Gtk.Menu.new()

		menu_item = Gtk.MenuItem.new_with_label('Export')
		menu_item.connect('activate', self.signal_activate_popup_menu_export)
		self.popup_menu.append(menu_item)

		menu_item = Gtk.MenuItem.new_with_label('Refresh')
		menu_item.connect('activate', lambda action: self.refresh())
		self.popup_menu.append(menu_item)

		menu_item = Gtk.CheckMenuItem.new_with_label('Show Toolbar')
		menu_item.connect('toggled', self.signal_toggled_popup_menu_show_toolbar)
		self._menu_item_show_toolbar = menu_item
		self.popup_menu.append(menu_item)
		self.popup_menu.show_all()
		self.navigation_toolbar.hide()
		self._legend = None

	@property
	def rpc(self):
		return self.application.rpc

	@staticmethod
	def _ax_hide_ticks(ax):
		for tick in ax.yaxis.get_major_ticks():
			tick.tick1On = False
			tick.tick2On = False

	@staticmethod
	def _ax_set_spine_color(ax, spine_color):
		for pos in ('top', 'right', 'bottom', 'left'):
			ax.spines[pos].set_color(spine_color)

	def _load_graph(self, info_cache):
		raise NotImplementedError()

	def add_legend_patch(self, legend_rows, fontsize=None):
		if self._legend is not None:
			self._legend.remove()
			self._legend = None
		if fontsize is None:
			scale = self.markersize_scale
			if scale < 5:
				fontsize = 'xx-small'
			elif scale < 7:
				fontsize = 'x-small'
			elif scale < 9:
				fontsize = 'small'
			else:
				fontsize = 'medium'
		legend_bbox = self.figure.legend(
			tuple(patches.Patch(color=patch_color) for patch_color, _ in legend_rows),
			tuple(label for _, label in legend_rows),
			borderaxespad=1.25,
			fontsize=fontsize,
			frameon=True,
			handlelength=1.5,
			handletextpad=0.75,
			labelspacing=0.3,
			loc='lower right'
		)
		legend_bbox.legendPatch.set_linewidth(0)
		self._legend = legend_bbox

	def get_color(self, color_name, default):
		"""
		Get a color by its style name such as 'fg' for foreground. If the
		specified color does not exist, default will be returned. The underlying
		logic for this function is provided by
		:py:func:`~.gui_utilities.gtk_style_context_get_color`.

		:param str color_name: The style name of the color.
		:param default: The default color to return if the specified one was not found.
		:return: The desired color if it was found.
		:rtype: tuple
		"""
		color_name = 'theme_color_graph_' + color_name
		sc_color = gui_utilities.gtk_style_context_get_color(self.style_context, color_name, default)
		return (sc_color.red, sc_color.green, sc_color.blue)

	def make_window(self):
		"""
		Create a window from the figure manager.

		:return: The graph in a new, dedicated window.
		:rtype: :py:class:`Gtk.Window`
		"""
		if self.manager is None:
			self.manager = FigureManager(self.canvas, 0)
		self.navigation_toolbar.destroy()
		self.navigation_toolbar = self.manager.toolbar
		self._menu_item_show_toolbar.set_active(True)
		window = self.manager.window
		window.set_transient_for(self.application.get_active_window())
		window.set_title(self.graph_title)
		return window

	@property
	def markersize_scale(self):
		bbox = self.axes[0].get_window_extent().transformed(self.figure.dpi_scale_trans.inverted())
		return bbox.width * self.figure.dpi * 0.01

	def mpl_signal_canvas_button_pressed(self, event):
		if event.button != 3:
			return
		self.popup_menu.popup(None, None, None, None, event.button, Gtk.get_current_event_time())
		return True

	def signal_activate_popup_menu_export(self, action):
		dialog = gui_utilities.FileChooser('Export Graph', self.application.get_active_window())
		file_name = self.config['campaign_name'] + '.png'
		response = dialog.run_quick_save(file_name)
		dialog.destroy()
		if not response:
			return
		destination_file = response['target_path']
		self.figure.savefig(destination_file, format='png')

	def signal_toggled_popup_menu_show_toolbar(self, widget):
		if widget.get_property('active'):
			self.navigation_toolbar.show()
		else:
			self.navigation_toolbar.hide()

	def load_graph(self):
		"""Load the graph information via :py:meth:`.refresh`."""
		self.refresh()

	def refresh(self, info_cache=None, stop_event=None):
		"""
		Refresh the graph data by retrieving the information from the
		remote server.

		:param dict info_cache: An optional cache of data tables.
		:param stop_event: An optional object indicating that the operation should stop.
		:type stop_event: :py:class:`threading.Event`
		:return: A dictionary of cached tables from the server.
		:rtype: dict
		"""
		info_cache = (info_cache or {})
		if not self.rpc:
			return info_cache
		for table in self.table_subscriptions:
			if stop_event and stop_event.is_set():
				return info_cache
			if not table in info_cache:
				info_cache[table] = tuple(self.rpc.remote_table(table, query_filter={'campaign_id': self.config['campaign_id']}))
		for ax in self.axes:
			ax.clear()
		if self._legend is not None:
			self._legend.remove()
			self._legend = None
		self._load_graph(info_cache)
		self.figure.suptitle(
			self.graph_title,
			color=self.get_color('fg', ColorHexCode.BLACK),
			size=14,
			weight='bold',
			y=0.97
		)
		self.canvas.draw()
		return info_cache
コード例 #26
0
class UI:
    # ====== Variables de la classe UI ========
    xn, yn = 0, 0

    # =========================================
    def __init__(self):
        # ### Initialise les datas###
        self.array_size = 10
        self.nbr_dots = 1
        # ###########################
        self.builder = Gtk.Builder()  # voir commentaires lignes 21-25
        # self.builder = gtk.Builder()
        self.builder.add_from_file(
            os.path.join(os.getcwd(), 'TBench_GUI_gl3.ui'))
        self.window = self.builder.get_object('dialog1')
        self.aboutdialog = self.builder.get_object('aboutdialog1')
        self.assistant = self.builder.get_object('assistant1')
        self.textview = self.builder.get_object('textview1')
        self.textbuffer = self.builder.get_object('textbuffer1')
        self.bt_exit = self.builder.get_object('bt_exit')
        self.tbt_state0 = self.builder.get_object('tbt_state0')
        self.tbt_state1 = self.builder.get_object('tbt_state1')
        self.tbt_state2 = self.builder.get_object('tbt_state2')
        self.imagemenuitem5 = self.builder.get_object('imagemenuitem5')
        self.imagemenuitem10 = self.builder.get_object('imagemenuitem10')
        self.builder.connect_signals(self)
        self.bufsize = 10  # ajout 20.02
        self.databuffer = collections.deque([0.0] * self.bufsize,
                                            self.bufsize)  # ajout 20.02
        self.x = [1 * i for i in range(-self.bufsize + 1, 1)
                  ]  # ajout 20.02(-self.bufsize+1,1)
        # Matplotlib trucs
        self.figure = Figure(figsize=(100, 100), dpi=100)
        self.ax = self.figure.add_subplot(111)
        self.canvas = FigureCanvas(self.figure)  # une gtk.DrawingArea
        self.line, = self.ax.plot(self.x, self.databuffer)
        # Gtk trucs
        self.canvas.show()
        self.graphview = self.builder.get_object("plot")
        self.graphview.pack_start(self.canvas, True, True, True)
        self.arrow = self.builder.get_object('arrow1')
        self.window.connect('delete-event', self.quit)
        self.tbt_state0.connect('toggled', self.on_button_toggled0)
        self.tbt_state1.connect('toggled', self.on_button_toggled1)
        self.tbt_state2.connect('toggled', self.on_button_toggled2)
        self.bt_exit.connect('clicked', self.quit)
        self.imagemenuitem5.connect('activate', self.quit)
        self.imagemenuitem10.connect('activate', self.show_aboutdialog)
        self.window.show()
        # ================= Recherche du port de l'arduino ====================
        self.sonde = arduino.search()
        if self.sonde == "impossible d'ouvrir un port série":
            info = (
                self.sonde + "!" + '\n' +
                "quitter cette session, vérifier la connexion avec le PLC, puis relancer le programme"
            )
            self.ajout_log_term("TB", info)
        else:
            self.ajout_log_term("PLC", self.sonde)
            self.init_arduino()  # initialise l'arduino
        # =====================================================================

    def updateplot(self):
        self.databuffer.append(UI.yn)
        self.line.set_ydata(self.databuffer)
        self.ax.relim()
        self.ax.autoscale_view(False, False, True)
        self.canvas.draw()

    def on_button_toggled0(self, button):
        if button.get_active():
            state = ['1', 'on']
            button.set_label(state[1].upper())
            self.send_command(state[0])
            self.updateplot()  # pour marquer un temps...
            UI.xn = UI.xn + 1
            UI.yn = 0.8
        else:
            state = ['0', 'off']
            button.set_label(state[1].upper())
            self.send_command(state[0])
            self.updateplot()  # pour marquer un temps...
            UI.xn = UI.xn + 1
            UI.yn = 0
        # print(UI.xn, UI.yn)
        self.updateplot()
        # self.updateplot()
        # print 'Button0 was turned: ', state[1]

    def on_button_toggled1(self, button):
        if button.get_active():
            state = ['1', 'on']
            button.set_label(state[1].upper())
            self.send_command(state[0])
        else:
            state = ['0', 'off']
            button.set_label(state[1].upper())
            self.send_command(state[0])

    def on_button_toggled2(self, button):
        if button.get_active():
            state = ['1', 'on']
            button.set_label(state[1].upper())
            self.send_command(state[0])
        else:
            state = ['0', 'off']
            button.set_label(state[1].upper())
            self.send_command(state[0])

    def show_aboutdialog(self, *args):
        self.aboutdialog.run()
        self.aboutdialog.hide()

    def show_assistant(self, *args):
        self.assistant.show()
        self.assistant.hide()

    def quit(self, *args):
        if self.sonde != "impossible d'ouvrir un port série":
            self.quit_arduino()  # réinitialise l'arduino
        # Gtk.main_quit()    # voir commentaires lignes 21-25
        Gtk.main_quit()

    def init_arduino(self):
        arduino.open()
        time.sleep(4)
        arduino.write('0')  # éteint la led si elle était allumée
        arduino.flush()

    def quit_arduino(self):
        arduino.write('0')  # éteint la led si elle était allumée
        arduino.flush()
        arduino.close()

    def send_command(self, val):
        arduino.write(val)
        self.rec = arduino.reading()
        info = ("Bascule l'état de la led PLC à " + val)
        self.ajout_log_term("TB", info)
        info = self.rec.decode('utf-8').rstrip('\n\r')
        self.ajout_log_term("PLC", info)

    def ajout_log_term(self, src, msg):
        #self.textbuffer.insert_at_cursor(src + ": " + msg + '\n')
        # text_buffer is a gtk.TextBuffer
        start_iter = self.textbuffer.get_start_iter()
        self.textbuffer.insert(start_iter, (src + ": " + msg + '\n'))
コード例 #27
0
ファイル: plot.py プロジェクト: warlock90000/WattmanGTK
class Plot:
    # TODO scaling of size when resizing
    # TODO tighter fit of plot
    # TODO BUG: weird redrawing issue on changing panes, probably should not redraw graph on changing panes
    # Plot object used GUI
    def __init__(self, builder, GPUs, maxpoints, precision, linux_kernelmain,
                 linux_kernelsub):
        # Can used for kernel specific workarounds
        self.linux_kernelmain = linux_kernelmain
        self.linux_kernelsub = linux_kernelsub

        self.precision = precision
        self.builder = builder
        self.GPUs = GPUs
        self.GPU = GPUs[0]
        self.maxpoints = maxpoints
        self.fig = Figure(figsize=(1000, 150), dpi=100, facecolor="#00000000")
        self.fig.set_tight_layout(True)
        self.ax = self.fig.add_subplot(111)
        # enable, name, unit, mean, max, current
        self.signalstore = Gtk.ListStore(bool, bool, bool, str, str, str, str,
                                         str, str, str)
        self.Plotsignals = self.init_signals(self.GPU)

        # Set top panel height in accordance to number of signals (with saturation)
        height_top_panel = len(self.Plotsignals) * 32.5
        if height_top_panel < 150:
            self.builder.get_object("MainPane").set_position(150)
        elif height_top_panel > 235:
            self.builder.get_object("MainPane").set_position(235)
        else:
            self.builder.get_object("MainPane").set_position(height_top_panel)

        self.init_treeview()
        self.update_signals()
        self.canvas = FigureCanvas(self.fig)
        self.canvas.set_size_request(1000, 150)
        self.object = self.builder.get_object("matplot")
        self.object.add(self.canvas)
        self.object.show_all()

    def change_GPU(self, cardnr):
        print(f"Changing plot to GPU {self.GPUs[cardnr].fancyname}")
        self.GPU = self.GPUs[cardnr]
        self.Plotsignals = self.init_signals(self.GPU)
        self.init_treeview()
        self.update_signals()

    def init_signals(self, GPU):
        Plotsignals = []

        # Define signals with: names units max min path plotenable plotnormalise plotcolor parser and outputargument used from parser
        if GPU.gpu_clock != 'N/A':
            Plotsignals.append(
                Plotsignal("GPU Clock", "[MHz]", GPU.pstate_clock[-1],
                           GPU.pstate_clock[0], "/pp_dpm_sclk", True, True,
                           "#1f77b4", GPU.get_current_clock, 0))
            Plotsignals.append(
                Plotsignal("GPU State", "[-]",
                           len(GPU.pstate_clock) - 1, 0, "/pp_dpm_sclk", True,
                           True, "#ff7f0e", GPU.get_current_clock, 1))
        if GPU.mem_clock != 'N/A':
            Plotsignals.append(
                Plotsignal("MEM Clock", "[MHz]", GPU.pmem_clock[-1],
                           GPU.pmem_clock[0], "/pp_dpm_mclk", True, True,
                           "#d62728", GPU.get_current_clock, 0))
            Plotsignals.append(
                Plotsignal("MEM State", "[-]",
                           len(GPU.pmem_clock) - 1, 0, "/pp_dpm_mclk", True,
                           True, "#9467bd", GPU.get_current_clock, 1))

        self.add_available_signal(GPU.sensors,
                                  Plotsignals,
                                  hwmonpath=GPU.hwmonpath)

        # GPU busy percent only properly available in linux version 4.19+
        if (self.linux_kernelmain == 4
                and self.linux_kernelsub > 18) or (self.linux_kernelmain >= 5):
            Plotsignals.append(
                Plotsignal("GPU Usage", "[-]", 100, 0, "/gpu_busy_percent",
                           True, True, "#2ca02c", GPU.read_sensor))
        # as final check remove signals that return None:
        checked_plotlist = []
        for i, signal in enumerate(Plotsignals):
            signal.retrieve_data(self.maxpoints)
            if signal.get_last_value() is not None:
                checked_plotlist.append(signal)
            else:
                print(
                    f"Removing {signal.name} from plotsignals, returning Nonetype"
                )

        if len(checked_plotlist) == 0:
            print("Nothing to plot! Hiding the plot pane.")
            self.builder.get_object("Plot").hide()
        return checked_plotlist

    def add_available_signal(self,
                             signals,
                             Plotsignals,
                             hwmonpath="",
                             subsystem="",
                             stop_recursion=False):
        for key, value in signals.items():
            if key in subsystem_unit_color:
                subsystem = key
                stop_recursion = False
            if "path" in value:
                if subsystem == "":
                    continue
                if any(path_sensor_to_plot in value["path"]
                       for path_sensor_to_plot in sensors_to_plot):
                    signallabel = value["path"][1:].split("_")[0]
                    signalmax = 0
                    signalmin = 0
                    signalpath = hwmonpath + value["path"]
                    if "min" in signals:
                        signalmin = signals['min']['value']
                        stop_recursion = True
                    if "max" in signals:
                        signalmax = signals['max']['value']
                        stop_recursion = True
                    if "crit" in signals:
                        signalmax = signals['crit']['value']
                        stop_recursion = True
                    if "label" in signals:
                        signallabel = signals["label"]["value"]
                        if signallabel == "vddgfx" and len(
                                self.GPU.volt_range) > 0:
                            signalmax = self.GPU.volt_range[1]
                            signalmin = 0
                        stop_recursion = True
                    if "cap" in signals:
                        signalmax = signals["cap"]["value"]
                        stop_recursion = True
                    if "pwm" in value["path"]:
                        signalmax = 255
                        signallabel = "(fan)" + signallabel
                    Plotsignals.append(
                        Plotsignal(signallabel,
                                   subsystem_unit_color[subsystem]["unit"],
                                   signalmax, signalmin, signalpath, True,
                                   True,
                                   subsystem_unit_color[subsystem]["color"],
                                   read))
            else:
                if not stop_recursion:
                    self.add_available_signal(value,
                                              Plotsignals,
                                              hwmonpath=hwmonpath,
                                              subsystem=subsystem,
                                              stop_recursion=stop_recursion)
                else:
                    continue

    def init_treeview(self):
        textrenderer = Gtk.CellRendererText()
        self.plotrenderer = Gtk.CellRendererToggle()
        self.plotrenderer.connect("toggled", self.on_plot_toggled)
        self.normaliserenderer = Gtk.CellRendererToggle()
        self.normaliserenderer.connect("toggled", self.on_normalise_toggled)
        self.tree = self.builder.get_object("Signal Selection")
        self.tree.append_column(
            Gtk.TreeViewColumn("Plot", self.plotrenderer, active=0))
        self.tree.append_column(
            Gtk.TreeViewColumn("Scale",
                               self.normaliserenderer,
                               active=1,
                               activatable=2))
        columnnames = ["Name", "Unit", "min", "mean", "max", "current"]
        for i, column in enumerate(columnnames):
            tcolumn = Gtk.TreeViewColumn(column,
                                         textrenderer,
                                         text=i + 3,
                                         foreground=9)
            self.tree.append_column(tcolumn)

        for plotsignal in self.Plotsignals:
            self.signalstore.append([
                plotsignal.plotenable, plotsignal.plotnormalise, True,
                plotsignal.name,
                convert_to_si(plotsignal.unit)[0], '0', '0', '0', '0',
                plotsignal.plotcolor
            ])
        self.tree.set_model(self.signalstore)

    def update_signals(self):
        # Retrieve signal and set appropriate values in signalstore to update left pane in GUI
        for i, Plotsignal in enumerate(self.Plotsignals):
            Plotsignal.retrieve_data(self.maxpoints)
            disable_scaling = len(
                Plotsignal.get_values()) > 3 and Plotsignal.all_equal(
                ) and Plotsignal.plotnormalise and (Plotsignal.max
                                                    == Plotsignal.min)
            self.signalstore[i][2] = not disable_scaling
            if disable_scaling:
                print(
                    f"cannot scale values of {self.signalstore[i][3]} disabling scaling"
                )
                self.on_normalise_toggled(self.normaliserenderer,
                                          i,
                                          disable_refresh=True)
                if disable_plots_if_scaling_error:
                    print(
                        f"disabling {self.signalstore[i][3]} plot since disable_plots_if_scaling_error is set"
                    )
                    self.on_plot_toggled(self.plotrenderer, i)
            self.signalstore[i][5] = str(
                np.around(
                    convert_to_si(Plotsignal.unit, Plotsignal.get_min())[1],
                    self.precision))
            self.signalstore[i][6] = str(
                np.around(
                    convert_to_si(Plotsignal.unit, Plotsignal.get_mean())[1],
                    self.precision))
            self.signalstore[i][7] = str(
                np.around(
                    convert_to_si(Plotsignal.unit, Plotsignal.get_max())[1],
                    self.precision))
            self.signalstore[i][8] = str(
                np.around(
                    convert_to_si(Plotsignal.unit,
                                  Plotsignal.get_last_value())[1],
                    self.precision))

    def on_plot_toggled(self, widget, path, disable_refresh=False):
        self.signalstore[path][0] = not self.signalstore[path][0]
        self.Plotsignals[int(
            path)].plotenable = not self.Plotsignals[int(path)].plotenable
        if not disable_refresh:
            self.update_plot()

    def on_normalise_toggled(self, widget, path, disable_refresh=False):
        self.signalstore[path][1] = not self.signalstore[path][1]
        self.Plotsignals[int(path)].plotnormalise = not self.Plotsignals[int(
            path)].plotnormalise
        if not disable_refresh:
            self.update_plot()

    def update_plot(self):
        if len(self.Plotsignals) == 0:
            return
        self.ax.clear()
        for Plotsignal in self.Plotsignals:
            if Plotsignal.plotenable:
                if Plotsignal.plotnormalise:
                    data = Plotsignal.get_normalised_values() * 100
                    self.ax.plot(data, color=Plotsignal.plotcolor)
                else:
                    data = Plotsignal.get_values()
                    self.ax.plot(convert_to_si(Plotsignal.unit, data)[1],
                                 color=Plotsignal.plotcolor)

        self.ax.grid(True)
        self.ax.get_yaxis().tick_right()
        self.ax.get_yaxis().set_label_position("right")
        self.ax.get_yaxis().set_visible(True)
        self.ax.get_xaxis().set_visible(False)
        all_normalised = True
        all_same_unit = True
        unit = ""
        iter = self.signalstore.get_iter(0)
        while iter is not None:
            if self.signalstore[iter][0] == True:
                if unit == "":
                    unit = self.signalstore[iter][4]
                if self.signalstore[iter][1] == False:
                    all_normalised = False
                if self.signalstore[iter][4] != unit:
                    all_same_unit = False
            if not all_normalised and not all_same_unit:
                break
            iter = self.signalstore.iter_next(iter)
        if all_normalised:
            self.ax.set_yticks(np.arange(0, 101, step=25))
            self.ax.set_ylabel('Percent [%]')
        else:
            self.ax.yaxis.set_major_locator(AutoLocator())
            if all_same_unit:
                self.ax.set_ylabel(unit)
            else:
                self.ax.set_ylabel("")
        self.canvas.draw()
        self.canvas.flush_events()

    def refresh(self):
        # This is run in thread
        self.update_signals()
        self.update_plot()
コード例 #28
0
class UI:
    # ====== Variables de la classe UI ========
    xn, yn = 0, 0

    # =========================================
    def __init__(self):
        # ### Initialise les datas###
        self.array_size = 10
        self.nbr_dots = 1
        # ###########################
        self.builder = Gtk.Builder()  # voir commentaires lignes 21-25
        # self.builder = gtk.Builder()
        self.builder.add_from_file(os.path.join(os.getcwd(), 'TBench_GUI_gl3.ui'))
        self.window = self.builder.get_object('dialog1')
        self.aboutdialog = self.builder.get_object('aboutdialog1')
        self.assistant = self.builder.get_object('assistant1')
        self.textview = self.builder.get_object('textview1')
        self.textbuffer = self.builder.get_object('textbuffer1')
        self.bt_exit = self.builder.get_object('bt_exit')
        self.tbt_state0 = self.builder.get_object('tbt_state0')
        self.tbt_state1 = self.builder.get_object('tbt_state1')
        self.tbt_state2 = self.builder.get_object('tbt_state2')
        self.imagemenuitem5 = self.builder.get_object('imagemenuitem5')
        self.imagemenuitem10 = self.builder.get_object('imagemenuitem10')
        self.builder.connect_signals(self)
        self.bufsize = 10  # ajout 20.02
        self.databuffer = collections.deque([0.0] * self.bufsize, self.bufsize)  # ajout 20.02
        self.x = [1 * i for i in range(-self.bufsize + 1, 1)]  # ajout 20.02(-self.bufsize+1,1)
        # Matplotlib trucs
        self.figure = Figure(figsize=(100, 100), dpi=100)
        self.ax = self.figure.add_subplot(111)
        self.canvas = FigureCanvas(self.figure)  # une gtk.DrawingArea
        self.line, = self.ax.plot(self.x, self.databuffer)
        # Gtk trucs
        self.canvas.show()
        self.graphview = self.builder.get_object("plot")
        self.graphview.pack_start(self.canvas, True, True, True)
        self.arrow = self.builder.get_object('arrow1')
        self.window.connect('delete-event', self.quit)
        self.tbt_state0.connect('toggled', self.on_button_toggled0)
        self.tbt_state1.connect('toggled', self.on_button_toggled1)
        self.tbt_state2.connect('toggled', self.on_button_toggled2)
        self.bt_exit.connect('clicked', self.quit)
        self.imagemenuitem5.connect('activate', self.quit)
        self.imagemenuitem10.connect('activate', self.show_aboutdialog)
        self.window.show()
        # ================= Recherche du port de l'arduino ====================
        self.sonde = arduino.search()
        if self.sonde == "impossible d'ouvrir un port série":
            info = (self.sonde + "!" + '\n' +
                    "quitter cette session, vérifier la connexion avec le PLC, puis relancer le programme")
            self.ajout_log_term("TB", info)
        else:
            self.ajout_log_term("PLC", self.sonde)
            self.init_arduino()  # initialise l'arduino
        # =====================================================================

    def updateplot(self):
        self.databuffer.append(UI.yn)
        self.line.set_ydata(self.databuffer)
        self.ax.relim()
        self.ax.autoscale_view(False, False, True)
        self.canvas.draw()

    def on_button_toggled0(self, button):
        if button.get_active():
            state = ['1', 'on']
            button.set_label(state[1].upper())
            self.send_command(state[0])
            self.updateplot()  # pour marquer un temps...
            UI.xn = UI.xn + 1
            UI.yn = 0.8
        else:
            state = ['0', 'off']
            button.set_label(state[1].upper())
            self.send_command(state[0])
            self.updateplot()  # pour marquer un temps...
            UI.xn = UI.xn + 1
            UI.yn = 0
        # print(UI.xn, UI.yn)
        self.updateplot()
        # self.updateplot()
        # print 'Button0 was turned: ', state[1]

    def on_button_toggled1(self, button):
        if button.get_active():
            state = ['1', 'on']
            button.set_label(state[1].upper())
            self.send_command(state[0])
        else:
            state = ['0', 'off']
            button.set_label(state[1].upper())
            self.send_command(state[0])

    def on_button_toggled2(self, button):
        if button.get_active():
            state = ['1', 'on']
            button.set_label(state[1].upper())
            self.send_command(state[0])
        else:
            state = ['0', 'off']
            button.set_label(state[1].upper())
            self.send_command(state[0])

    def show_aboutdialog(self, *args):
        self.aboutdialog.run()
        self.aboutdialog.hide()

    def show_assistant(self, *args):
        self.assistant.show()
        self.assistant.hide()

    def quit(self, *args):
        if self.sonde != "impossible d'ouvrir un port série":
            self.quit_arduino()  # réinitialise l'arduino
        # Gtk.main_quit()    # voir commentaires lignes 21-25
        Gtk.main_quit()

    def init_arduino(self):
        arduino.open()
        time.sleep(4)
        arduino.write('0')  # éteint la led si elle était allumée
        arduino.flush()

    def quit_arduino(self):
        arduino.write('0')  # éteint la led si elle était allumée
        arduino.flush()
        arduino.close()

    def send_command(self, val):
        arduino.write(val)
        self.rec = arduino.reading()
        info = ("Bascule l'état de la led PLC à " + val)
        self.ajout_log_term("TB", info)
        info = self.rec.decode('utf-8').rstrip('\n\r')
        self.ajout_log_term("PLC", info)

    def ajout_log_term(self, src, msg):
        #self.textbuffer.insert_at_cursor(src + ": " + msg + '\n')
        # text_buffer is a gtk.TextBuffer
        start_iter = self.textbuffer.get_start_iter()
        self.textbuffer.insert(start_iter, (src + ": " + msg + '\n'))
コード例 #29
0
ファイル: profile.py プロジェクト: RickCarmichael/set64rs
class Profile(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self, title="Profile")
        #f = Figure(figsize=(5,4), dpi=100)
        f = Figure()
        self.axes = f.add_subplot(111)
        self.axes.set_xlabel('Time (sec.)')
        self.axes.set_ylabel('Temperature (C)')
        self.axes.set_xlim(0, 5*60)
        self.axes.set_ylim(20, 300)
        self.axes.grid()
        self.axes.xaxis.set_major_formatter(FuncFormatter(self.format_xaxis))
        self.x = []
        self.y = []
        self.plot, = self.axes.plot(self.x, self.y, 'o-', picker=5)
        self.minutes = False
        self.file_name = None

        self.canvas = FigureCanvas(f)
        self.canvas.set_size_request(800,600)
        self.canvas.mpl_connect('button_press_event', self.onclick)
        self.canvas.mpl_connect('button_release_event', self.onrelease)
        self.canvas.mpl_connect('pick_event', self.onpick)
        self.canvas.mpl_connect('motion_notify_event', self.onmotion)
        self.picking = None

        self.store = Gtk.ListStore(str, str)
        self.tree = Gtk.TreeView(self.store)

        renderer = Gtk.CellRendererText()
        renderer.set_property("editable", True)
        renderer.connect('edited', self.on_time_edited)
        column = Gtk.TreeViewColumn("Time", renderer, text=0)
        self.tree.append_column(column)

        renderer = Gtk.CellRendererText()
        renderer.set_property("editable", True)
        renderer.connect('edited', self.on_temp_edited)
        column = Gtk.TreeViewColumn("Temperature", renderer, text=1)
        self.tree.append_column(column)

        self.box = Gtk.Box()
        self.box.pack_start(self.canvas, False, False, 0)
        self.box.pack_start(self.tree, True, True, 0)

        action_group = Gtk.ActionGroup("profile_actions")
        action_group.add_actions([
            ("FileMenu", None, "File", None, None, None),
            ("FileNew", Gtk.STOCK_NEW, "_New", "<control>N", None, self.on_file_new),
            ("FileOpen", Gtk.STOCK_OPEN, "_Open", "<control>O", None, self.on_file_open),
            ("FileSave", Gtk.STOCK_SAVE, "_Save", "<control>S", None, self.on_file_save),
            ("FileSaveAs", Gtk.STOCK_SAVE_AS, "Save _As…", "<shift><control>S", None, self.on_file_save_as),
            ("FileQuit", Gtk.STOCK_QUIT, "_Quit", "<control>Q", None, Gtk.main_quit)
        ])

        uimanager = Gtk.UIManager()
        uimanager.add_ui_from_string(UI_INFO)
        accelgroup = uimanager.get_accel_group()
        self.add_accel_group(accelgroup)
        uimanager.insert_action_group(action_group)

        menubar = uimanager.get_widget("/MenuBar")
        self.vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        self.vbox.pack_start(menubar, False, False, 0)
        self.vbox.pack_start(self.box, True, True, 0)
        self.statusbar = Gtk.Statusbar()
        self.status_pos = self.statusbar.get_context_id("position")
        self.vbox.pack_start(self.statusbar, False, False, 0)

        self.add(self.vbox)

    def open_file(self, name):
        reader = csv.reader(open(name, 'rb'))
        x, y = zip(*reader)
        x = [ float(i) for i in x]
        y = [ float(i) for i in y]
        self.x, self.y = x, y
        self.file_name = name
        self.set_title('Profile - ' + name)
        self.update_data()
        self.update_scale()
        self.canvas.draw()

    def save_file(self, name):
        writer = csv.writer(open(name, 'wd'))
        writer.writerows(zip(self.x, self.y))
        self.file_name = name
        self.set_title('Profile - ' + name)

    def on_file_new(self, widget):
        self.file_name = None
        self.set_title('Profile')
        self.x = []
        self.y = []
        self.store.clear()
        self.update_data()
        self.update_scale()
        self.canvas.draw()

    def on_file_open(self, widget):
        dialog = Gtk.FileChooserDialog("", self,
            Gtk.FileChooserAction.OPEN,
            (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
             Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
        dialog.set_current_folder_uri(Gio.file_new_for_path(os.curdir).get_uri())
        response = dialog.run()
        if response == Gtk.ResponseType.OK:
            try:
                self.open_file(dialog.get_filename())
            except:
                pass       
        dialog.destroy()

    def on_file_save(self, widget):
        if self.file_name is None:
            self.on_file_save_as(widget)
        else:
            self.save_file(self.file_name)

    def on_file_save_as(self, widget):
        dialog = Gtk.FileChooserDialog("", self,
            Gtk.FileChooserAction.SAVE,
            (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
             Gtk.STOCK_SAVE_AS, Gtk.ResponseType.OK))
        dialog.set_current_folder_uri(Gio.file_new_for_path(os.curdir).get_uri())
        response = dialog.run()
        if response == Gtk.ResponseType.OK:
            self.save_file(dialog.get_filename())
        dialog.destroy()

    def format_xaxis(self, x, pos):
        return self.format_x(x)

    def format_x(self, val):
        m, s = 0, val
        if self.minutes:
            m = int(val / 60)
            s = val % 60
        if m:
            return '%dm%.1fs'%(m,s)
        else:
            return '%.1fs'%s

    def format_y(self, val):
        return '%.1f°C'%val

    def on_time_edited(self, widget, path, text):
        treeiter = self.store.get_iter(path)
        try:
            m, s = "0", "0"
            if 'm' in text:
                m, text = text.split('m')
            if 's' in text:
                s, text = text.split('s')
            else:
                text = ""
            assert len(text) == 0
            val = int(m) * 60.0 + round(float(s), 1)
        except:
            return

        at = max(0, int(path))
        if at != 0:
            val = max(val, self.x[at-1])
        if at != len(self.x)-1:
            val = min(val, self.x[at+1])
        self.store.set(treeiter, 0, self.format_x(val))
        self.x[int(path)] = val
        self.update_data()
        self.update_scale()
        self.canvas.draw()

    def on_temp_edited(self, widget, path, text):
        treeiter = self.store.get_iter(path)
        try:
            if '°' in text:
                text, _ = text.split('°')
            if 'c' in text.lower():
                text, _ = text.lower().split('c')
            val = round(float(text), 1)
        except:
            return
        val = min(300.0, val)
        val = max(20.0, val)
        self.store.set(treeiter, 1, self.format_y(val))
        self.y[int(path)] = val
        self.update_data()
        self.canvas.draw()

    def update_data(self):
        self.plot.set_data(self.x, self.y)

    def update_scale(self):
        if len(self.x) and self.x[-1] + 30 > 5 * 60:
            minutes = int((self.x[-1] + 90) / 60)
        else:
            minutes = 5
        self.axes.set_xlim(0, minutes*60)

    def onclick(self, event):
        if self.picking is not None or event.button != 1:
            return
        xdata = round(event.xdata, 1)
        ydata = round(event.ydata, 1)
        at = bisect.bisect(self.x, xdata)
        self.x.insert(at, xdata)
        self.y.insert(at, ydata)
        self.store.insert(at, [self.format_x(xdata), self.format_y(ydata)])
        self.update_data()
        self.update_scale()
        self.canvas.draw()

    def onrelease(self, event):
        if self.picking is None:
            return
        self.update_scale()
        self.canvas.draw()
        self.picking = None

    def onpick(self, event):
        on = event.artist
        ind = event.ind[0]
        if event.mouseevent.button == 1:
            self.picking = ind
        elif event.mouseevent.button == 3:
            self.x.pop(ind)
            self.y.pop(ind)
            self.store.remove(self.store.get_iter(Gtk.TreePath(ind)))
            self.update_data()
            self.update_scale()
            self.canvas.draw()

    def onmotion(self, event):
        self.statusbar.remove_all(self.status_pos)
        if event.xdata is None or event.ydata is None:
            return
        self.statusbar.push(self.status_pos,
            self.format_x(event.xdata) + ', ' + self.format_y(event.ydata))
        if self.picking is None:
            return
        xdata = max(0, round(event.xdata, 1))
        ydata = round(event.ydata, 1)
        ydata = min(300.0, ydata)
        ydata = max(20.0, ydata)
        if self.picking != 0:
            xdata = max(xdata, self.x[self.picking-1])
        if self.picking != len(self.x)-1:
            xdata = min(xdata, self.x[self.picking+1])
        self.x[self.picking] = xdata
        self.y[self.picking] = ydata
        treeiter = self.store.get_iter(Gtk.TreePath(self.picking))
        self.store.set(treeiter, 0, self.format_x(xdata), 1, self.format_y(ydata))
        self.update_data()
        self.canvas.draw()
コード例 #30
0
ファイル: views.py プロジェクト: fbocches/PyXRD
class EditCSDSDistributionView(BaseView):
    builder = resource_filename(__name__, "glade/csds.glade")
    top = "tbl_csds_distr"

    def __init__(self, *args, **kwargs):
        BaseView.__init__(self, *args, **kwargs)

        self.graph_parent = self["distr_plot_box"]
        self.setup_matplotlib_widget()

    def setup_matplotlib_widget(self):
        #style = Gtk.Style()
        self.figure = Figure(
            dpi=72)  #, edgecolor=str(style.bg[2]), facecolor=str(style.bg[2]))

        self.plot = self.figure.add_subplot(111)
        self.figure.subplots_adjust(bottom=0.20)

        self.matlib_canvas = FigureCanvasGTK(self.figure)

        self.plot.autoscale_view()

        self.graph_parent.add(self.matlib_canvas)
        self.graph_parent.show_all()

    def update_figure(self, distr):
        self.plot.cla()
        self.plot.hist(list(range(len(distr))),
                       len(distr),
                       weights=distr,
                       normed=1,
                       ec='b',
                       histtype='stepfilled')
        self.plot.set_ylabel('')
        self.plot.set_xlabel('CSDS', size=14, weight="heavy")
        self.plot.relim()
        self.plot.autoscale_view()
        if self.matlib_canvas is not None:
            self.matlib_canvas.draw()

    def reset_params(self):
        tbl = self["tbl_params"]
        for child in tbl.get_children():
            tbl.remove(child)
        tbl.resize(1, 2)

    def add_param_widget(self, name, label, minimum, maximum):
        tbl = self["tbl_params"]
        rows = tbl.get_property("n-rows") + 1
        tbl.resize(rows, 2)

        lbl = Gtk.Label(label=label)
        lbl.set_alignment(1.0, 0.5)
        tbl.attach(lbl, 0, 1, rows - 1, rows, Gtk.AttachOptions.FILL,
                   Gtk.AttachOptions.FILL)

        inp = ScaleEntry(minimum, maximum, enforce_range=True)
        tbl.attach(inp, 1, 2, rows - 1, rows, Gtk.AttachOptions.FILL,
                   Gtk.AttachOptions.FILL)

        tbl.show_all()

        self[name] = inp
        inp.set_name(name)

        return inp
コード例 #31
0
ファイル: hmi.py プロジェクト: tucuongbrt/fire-rs-saop
class SAOPControlWindow(Gtk.Window):
    def __init__(self, model: HMIModel):
        super(SAOPControlWindow, self).__init__(default_width=500,
                                                default_height=400,
                                                title="SAOP HMI")

        self.hmi_model = model
        self.hmi_model.set_controller(self)

        ## Actions
        self.plan_button = Gtk.Button(label="Create")
        self.plan_button.connect("clicked", self.on_plan_clicked)

        self.cancel_button = Gtk.Button(label="Stop")
        self.cancel_button.connect("clicked", self.on_cancel_clicked)

        self.home_button = Gtk.Button(label="Go home")
        self.home_button.connect("clicked", self.on_home_clicked, None)
        self.home_button.set_sensitive(False)

        self.home_more_button = Gtk.MenuButton.new()
        self.home_more_button.set_direction(Gtk.ArrowType.UP)
        self.home_more_button.set_use_popover(True)

        self.propagate_button = Gtk.Button(label="Propagate")
        self.propagate_button.connect("clicked", self.on_propagate_clicked)

        self.action_bar = Gtk.ActionBar()
        self.action_bar.pack_start(Gtk.Label("Plan:"))
        self.action_bar.pack_start(self.plan_button)
        self.action_bar.pack_start(self.cancel_button)
        home_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        Gtk.StyleContext.add_class(home_box.get_style_context(), "linked")
        home_box.pack_start(self.home_button, False, False, 0)
        home_box.pack_start(self.home_more_button, False, False, 0)
        self.action_bar.pack_start(home_box)
        self.action_bar.pack_start(
            Gtk.Separator(orientation=Gtk.Orientation.VERTICAL))
        self.action_bar.pack_start(Gtk.Label("Wildfire:"))
        self.action_bar.pack_start(self.propagate_button)

        ## Visualization control
        # Empty drawing area that will be replaced by a matplotlib figure
        default_fig = matplotlib.figure.Figure()
        self.canvas = FigureCanvas(default_fig)
        self.navigation_toolbar = NavigationToolbar(self.canvas, self)

        # Visualization Checkboxes
        scrolled_flowbox = Gtk.ScrolledWindow()
        scrolled_flowbox.set_policy(Gtk.PolicyType.NEVER,
                                    Gtk.PolicyType.AUTOMATIC)

        flowbox = Gtk.FlowBox()
        flowbox.set_valign(Gtk.Align.START)
        flowbox.set_max_children_per_line(30)
        flowbox.set_selection_mode(Gtk.SelectionMode.NONE)

        # Checkboxes
        def toggle_pause(button):
            self.set_update_plot(not button.props.active)

        pause_toggle = Gtk.ToggleButton("Pause")
        pause_toggle.props.active = False
        pause_toggle.connect("toggled", toggle_pause)
        pause_toggle.toggled()
        flowbox.add(pause_toggle)

        display_label = Gtk.Label("Display:")
        flowbox.add(display_label)

        def toggle_elevation(button):
            self.hmi_model.elevation_map.drawable = button.get_active()

        elevation_toggle = SAOPControlWindow._check_button_with_action(
            "Elevation", toggle_elevation)
        flowbox.add(elevation_toggle)

        def toggle_wildfire(button):
            self.hmi_model.wildfire_map.drawable = button.get_active()

        wildfire_toggle = SAOPControlWindow._check_button_with_action(
            "Wildfire", toggle_wildfire)
        flowbox.add(wildfire_toggle)

        def toggle_wildfire_observed(button):
            self.hmi_model.wildfire_map_observed.drawable = button.get_active()

        wildfire_observed_toggle = SAOPControlWindow._check_button_with_action(
            "Observed wildfire", toggle_wildfire_observed)
        flowbox.add(wildfire_observed_toggle)

        def toggle_wildfire_predicted(button):
            self.hmi_model.wildfire_map_predicted.drawable = button.get_active(
            )

        wildfire_predicted_toggle = SAOPControlWindow._check_button_with_action(
            "Predicted wildfire", toggle_wildfire_predicted)
        flowbox.add(wildfire_predicted_toggle)

        def toggle_uav(button):
            self.hmi_model.uav_state.drawable = button.get_active()

        uav_toggle = SAOPControlWindow._check_button_with_action(
            "UAV", toggle_uav)
        flowbox.add(uav_toggle)

        def toggle_trails(button):
            self.hmi_model.uav_trail.drawable = button.get_active()

        trail_toggle = SAOPControlWindow._check_button_with_action(
            "UAV trails", toggle_trails)
        flowbox.add(trail_toggle)

        def toggle_plan(button):
            self.hmi_model.trajectories.drawable = button.get_active()

        plan_toggle = SAOPControlWindow._check_button_with_action(
            "Plan", toggle_plan)
        flowbox.add(plan_toggle)

        scrolled_flowbox.add(flowbox)

        self.figure_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL,
                                  spacing=0,
                                  border_width=0)
        self.figure_box.pack_start(self.navigation_toolbar, False, True, 0)
        self.figure_box.pack_start(self.canvas, True, True, 0)
        self.figure_box.pack_start(scrolled_flowbox, False, False, 0)

        ## Side panel
        right_panel = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        # View of ROS logs
        log_textview = Gtk.TextView()
        log_textview.set_editable(False)
        log_textview.set_monospace(True)
        log_textview.set_wrap_mode(Gtk.WrapMode.WORD_CHAR)
        self.log_textbuffer = log_textview.get_buffer()
        self.tag_bold = self.log_textbuffer.create_tag(
            "bold", weight=Pango.Weight.BOLD)
        log_scrolled = Gtk.ScrolledWindow()
        log_scrolled.add(log_textview)
        right_panel.pack_start(log_scrolled, True, True, 0)

        # UAV controls

        # self.content_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6,
        #                            border_width=12)
        self.content_panned = Gtk.Paned(orientation=Gtk.Orientation.HORIZONTAL)
        self.content_panned.pack1(self.figure_box, True, True)
        self.content_panned.pack2(right_panel, False, True)

        box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL,
                      spacing=0,
                      border_width=0)
        box.pack_start(self.content_panned, True, True, 0)
        box.pack_start(self.action_bar, False, False, 0)
        self.add(box)

    @staticmethod
    def _check_button_with_action(name, action):
        toggle = Gtk.CheckButton(name)
        toggle.props.active = True
        toggle.connect("toggled", action)
        toggle.toggled()
        return toggle

    def set_update_plot(self, state: bool):
        self.hmi_model.gdd_drawable = state

    def append_log(self, t: datetime.datetime, name: str, msg: str):
        self._append_text_with_markup(
            "<b>{}</b> <i>{}</i>: <tt>{}</tt>\n".format(
                datetime.datetime.strftime(t, "%x %X"), str(name), str(msg)))

    def _append_text_with_markup(self, text):
        end_iter = self.log_textbuffer.get_end_iter()
        self.log_textbuffer.insert_markup(end_iter, text, -1)

    def set_uav_controls(self):
        """Update UAV control panel"""
        pass

    def update_figure(self):
        self._update_figure()

    def _update_figure(self):
        """Redraw the matplotlib figure"""
        if self.hmi_model.gdd:
            self.canvas.figure = self.hmi_model.gdd.figure  # a Gtk.DrawingArea
            self.canvas.draw()  # TODO: verify whether we need it or not

    def on_propagate_clicked(self, button):
        self.hmi_model.propagate_command()

    def on_plan_clicked(self, button):
        known_uavs = self.hmi_model.known_uavs()
        if known_uavs:
            pdiag = PlanCreationWindow(self, known_uavs)
            if pdiag.run() == Gtk.ResponseType.OK:
                GLib.idle_add(self.hmi_model.plan_command, pdiag.vns_conf,
                              pdiag.planning_duration, pdiag.mission_duration,
                              pdiag.uav_selection, pdiag.trajectory_duration,
                              pdiag.mission_start_delay)
            pdiag.destroy()
        else:
            dialog = Gtk.MessageDialog(self, 0, Gtk.MessageType.INFO,
                                       Gtk.ButtonsType.OK,
                                       "No UAVs available for planning")
            dialog.format_secondary_text(
                "Wait for UAVs to be detected or check Neptus and Dune are running"
            )
            dialog.set_transient_for(self)
            dialog.run()
            dialog.destroy()

    def on_cancel_clicked(self, button):
        for uav in self.hmi_model.known_uavs():
            self.hmi_model.stop_command(uav)

    def on_home_clicked(self, button, uav: ty.Optional[str]):
        # Go home
        self.hmi_model.home_command(uav)

    def on_new_uav(self, uav: str):
        print("Go Home!")
        if len(self.hmi_model.uav_state.data.keys()) < 1:
            return
        self.home_button.set_sensitive(True)
        menu = Gtk.Menu()
        for uav in [*self.hmi_model.uav_state.data.keys()]:

            def cb(menu_item, u):
                self.hmi_model.home_command(u)

            mi = Gtk.MenuItem(label=uav)
            mi.connect("activate", cb, uav)
            mi.show()
            menu.append(mi)
        self.home_more_button.set_use_popover(True)
        self.home_more_button.set_popup(menu)
コード例 #32
0
class StatPerspective(Gtk.Box, Ide.Perspective):
    """
    Sets up the stats perspective and handles the signals.

    This class sets up the containers of the perspective
    and the matplotlib figure and canvas. An asynchronous
    method iterates over the project and gathers the data
    for the plot.
    """
    def __init__(self, workdir, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.workdir = workdir

        # main containers
        scr_win = Gtk.ScrolledWindow(visible=True)
        pad_box = Gtk.Box(visible=True)
        pad_box.pack_start(scr_win, True, True, 20)

        main_box = Gtk.Box(visible=True, orientation=Gtk.Orientation.VERTICAL)
        scr_win.add_with_viewport(main_box)

        # content
        lbl_head = '<span font="36.0"><b>Project Stats</b></span>'
        heading = Gtk.Label(label=lbl_head, expand=True, visible=True)
        heading.set_use_markup(True)
        main_box.pack_start(heading, False, False, 0)
        line = Gtk.Separator(visible=True)
        main_box.pack_start(line, False, False, 0)

        self.fig = Figure(facecolor='none')
        self.ax = self.fig.add_subplot(111, axisbg='#ffffff')
        self.canvas = FigCanvas(self.fig)
        self.canvas.set_size_request(800, 600)
        self.canvas.draw()
        self.canvas.show()
        main_box.pack_start(self.canvas, True, True, 0)

        self.add(pad_box)
        self.titlebar = Ide.WorkbenchHeaderBar(visible=True)

        # Gather stats
        thread = threading.Thread(target=self.gather_stats)
        thread.daemon = True
        thread.start()

    def gather_stats(self):
        file_types = {}

        for root, subfolders, files in os.walk(self.workdir):
            for file in files:
                try:
                    with open(root + "/" + file) as fl:
                        line_count = 0
                        for line in fl:
                            line_count += 1

                        splt_str = file.split(".")
                        if len(splt_str) > 1:
                            file_ext = splt_str[-1]
                        else:
                            continue
                        if file_ext in file_types:
                            # key exists, add line count
                            file_types[
                                file_ext] = file_types[file_ext] + line_count
                        else:
                            # key doesn't exist, create new key
                            file_types[file_ext] = line_count
                except:
                    continue

        keys = []
        values = []

        for key, value in file_types.items():
            keys.append(key)
            values.append(value)

        key_ar = np.array(keys)
        val_ar = np.array(values).astype(int)

        ar = np.vstack((key_ar, val_ar)).T
        ar = ar[ar[:, 1].astype(int).argsort()]
        rows = ar.shape[0]
        val_pos = np.arange(1, ar.shape[0] + 1)

        self.ax.barh(val_pos, ar[:, 1].astype(int), 0.8, align="center")
        # facecolor='yellow'
        self.ax.set_yticks(val_pos)
        self.ax.tick_params(axis="both", which="major", pad=15)
        self.ax.set_yticklabels(ar[:, 0], fontsize="16", weight="bold")
        self.ax.tick_params(axis="x", which="major", labelsize="16")

        self.canvas.set_size_request(800, (rows * 20 + 50))
        self.canvas.draw()

    def do_get_id(self):
        return 'hello-world2'

    def do_get_title(self):
        return 'Hello'

    def do_get_priority(self):
        return 10000

    def do_get_icon_name(self):
        return "utilities-system-monitor-symbolic"

    def do_get_titlebar(self):
        return self.titlebar
コード例 #33
0
ファイル: iem_wbb.py プロジェクト: etvorellana/iem-wbb
class MyWindow(Gtk.Window):
    def __init__(self):

        #Janela
        Gtk.Window.__init__(self, title="IEM-WBB")
        self.set_resizable(False)
        self.set_size_request(600, 600)
        self.set_position(Gtk.WindowPosition.CENTER)
        self.set_border_width(10)

        principal = Gtk.Box(spacing=10)
        principal.set_homogeneous(False)

        vbox_left = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        vbox_left.set_homogeneous(False)

        vbox_right = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        vbox_right.set_homogeneous(False)

        ### Boxes que ficarão dentro da vbox_left ###
        hbox_MDIST = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        hbox_MDIST.set_homogeneous(False)

        hbox_labels = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        hbox_labels.set_homogeneous(False)

        hbox_RDIST = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        hbox_RDIST.set_homogeneous(True)

        hbox_TOTEX = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        hbox_TOTEX.set_homogeneous(True)

        hbox_MVELO = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        hbox_MVELO.set_homogeneous(True)

        #criando os elementos das boxes Mdist, Labels, Rdist, TOTEX, Mvelo
        ##MDIST##
        label_Mdist = Gtk.Label('MDIST')
        self.entry_Mdist = Gtk.Entry()
        self.entry_Mdist.set_editable(False)
        self.entry_Mdist.set_max_length(max=8)

        ##LABELS##
        label_vazia = Gtk.Label('     ')
        label_AP = Gtk.Label('AP')
        label_ML = Gtk.Label('ML')
        label_TOTAL = Gtk.Label('TOTAL')

        ##RDIST##
        label_Rdist = Gtk.Label('RDIST')
        self.entry_Rdist_AP = Gtk.Entry()
        self.entry_Rdist_AP.set_editable(False)
        self.entry_Rdist_AP.set_max_length(max=8)
        self.entry_Rdist_ML = Gtk.Entry()
        self.entry_Rdist_ML.set_editable(False)
        self.entry_Rdist_ML.set_max_length(max=8)
        self.entry_Rdist_TOTAL = Gtk.Entry()
        self.entry_Rdist_TOTAL.set_editable(False)
        self.entry_Rdist_TOTAL.set_max_length(max=8)

        ##TOTEX##
        label_TOTEX = Gtk.Label('TOTEX')
        self.entry_TOTEX_AP = Gtk.Entry()
        self.entry_TOTEX_AP.set_editable(False)
        self.entry_TOTEX_AP.set_max_length(max=8)
        self.entry_TOTEX_ML = Gtk.Entry()
        self.entry_TOTEX_ML.set_editable(False)
        self.entry_TOTEX_ML.set_max_length(max=8)
        self.entry_TOTEX_TOTAL = Gtk.Entry()
        self.entry_TOTEX_TOTAL.set_editable(False)
        self.entry_TOTEX_TOTAL.set_max_length(max=8)

        ##MVELO##
        label_MVELO = Gtk.Label('MVELO')
        self.entry_MVELO_AP = Gtk.Entry()
        self.entry_MVELO_AP.set_editable(False)
        self.entry_MVELO_AP.set_max_length(max=8)
        self.entry_MVELO_ML = Gtk.Entry()
        self.entry_MVELO_ML.set_editable(False)
        self.entry_MVELO_ML.set_max_length(max=8)
        self.entry_MVELO_TOTAL = Gtk.Entry()
        self.entry_MVELO_TOTAL.set_editable(False)
        self.entry_MVELO_TOTAL.set_max_length(max=8)

        #colocando cada elemento dentro da sua box
        hbox_MDIST.pack_start(label_Mdist, True, True, 0)
        hbox_MDIST.pack_start(self.entry_Mdist, True, True, 0)

        hbox_labels.pack_start(label_vazia, True, True, 0)
        hbox_labels.pack_start(label_AP, True, True, 0)
        hbox_labels.pack_start(label_ML, True, True, 0)
        hbox_labels.pack_start(label_TOTAL, True, True, 0)

        hbox_RDIST.pack_start(label_Rdist, True, True, 0)
        hbox_RDIST.pack_start(self.entry_Rdist_AP, True, True, 0)
        hbox_RDIST.pack_start(self.entry_Rdist_ML, True, True, 0)
        hbox_RDIST.pack_start(self.entry_Rdist_TOTAL, True, True, 0)

        hbox_TOTEX.pack_start(label_TOTEX, True, True, 0)
        hbox_TOTEX.pack_start(self.entry_TOTEX_AP, True, True, 0)
        hbox_TOTEX.pack_start(self.entry_TOTEX_ML, True, True, 0)
        hbox_TOTEX.pack_start(self.entry_TOTEX_TOTAL, True, True, 0)

        hbox_MVELO.pack_start(label_MVELO, True, True, 0)
        hbox_MVELO.pack_start(self.entry_MVELO_AP, True, True, 0)
        hbox_MVELO.pack_start(self.entry_MVELO_ML, True, True, 0)
        hbox_MVELO.pack_start(self.entry_MVELO_TOTAL, True, True, 0)

        #colocando as boxes pequenas dentro das box vbox_left
        vbox_left.pack_start(hbox_MDIST, True, True, 0)
        vbox_left.pack_start(hbox_labels, True, True, 0)
        vbox_left.pack_start(hbox_RDIST, True, True, 0)
        vbox_left.pack_start(hbox_TOTEX, True, True, 0)
        vbox_left.pack_start(hbox_MVELO, True, True, 0)

        #elementos da vbox_right)
        #Notebook
        self.notebook = Gtk.Notebook()
        self.fig = plt.figure()

        self.axis = self.fig.add_subplot(111)
        self.axis.set_ylabel('ML')
        self.axis.set_xlabel('AP')
        self.canvas = FigureCanvas(self.fig)
        self.canvas.set_size_request(500, 500)

        self.page1 = Gtk.Box()
        self.page1.set_border_width(10)
        self.page1.add(self.canvas)
        self.notebook.append_page(self.page1, Gtk.Label('Gráfico do CoP'))

        ##aqui fica a segunda janela do notebook
        self.fig2 = plt.figure()
        self.axis2 = self.fig2.add_subplot(111)
        self.axis2.set_ylabel('ML')
        self.axis2.set_xlabel('AP')
        self.canvas2 = FigureCanvas(self.fig2)
        self.canvas2.set_size_request(500, 500)

        self.page2 = Gtk.Box()
        self.page2.set_border_width(10)
        self.page2.add(self.canvas2)
        self.notebook.append_page(self.page2,
                                  Gtk.Label('Gráfico na frequência'))

        #criando os botoes
        hbox_botoes = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        hbox_botoes.set_homogeneous(True)

        self.button1 = Gtk.Button(label="Capturar")
        self.button1.connect("clicked", self.on_button1_clicked)

        self.button2 = Gtk.Button(label="Processar")
        self.button2.connect("clicked", self.on_button2_clicked)

        #colocando os botoes nas boxes
        hbox_botoes.pack_start(self.button1, True, True, 0)
        hbox_botoes.pack_start(self.button2, True, True, 0)

        vbox_right.pack_start(self.notebook, True, True, 0)
        vbox_right.pack_start(hbox_botoes, True, True, 0)

        # colocando as boxes verticais dentro da box principal
        principal.pack_start(vbox_left, True, True, 0)
        principal.pack_start(vbox_right, True, True, 0)

        #Adicionano os elementos na box exterior
        self.add(principal)

    def on_button1_clicked(self, widget):
        global APs, MLs

        balance = calc.readWBB()

        for (x, y) in balance:
            APs.append(x)
            MLs.append(y)

        max_absoluto_AP = calc.valorAbsoluto(min(APs), max(APs))
        max_absoluto_ML = calc.valorAbsoluto(min(MLs), max(MLs))

        print('max_absoluto_AP:', max_absoluto_AP, 'max_absoluto_ML:',
              max_absoluto_ML)

        self.axis.clear()
        self.axis.set_ylabel('ML')
        self.axis.set_xlabel('AP')

        self.axis.set_xlim(-max_absoluto_AP, max_absoluto_AP)
        self.axis.set_ylim(-max_absoluto_ML, max_absoluto_ML)
        self.axis.plot(APs, MLs, '-', color='r')
        self.canvas.draw()

    def on_button2_clicked(self, widget):
        global APs, MLs
        APs, MLs = calc.geraAP_ML(APs, MLs)

        dis_resultante_total = calc.distanciaResultante(APs, MLs)
        dis_resultante_AP = calc.distanciaResultanteParcial(APs)
        dis_resultante_ML = calc.distanciaResultanteParcial(MLs)

        dis_media = calc.distanciaMedia(dis_resultante_total)

        dis_rms_total = calc.dist_RMS(dis_resultante_total)
        dis_rms_AP = calc.dist_RMS(dis_resultante_AP)
        dis_rms_ML = calc.dist_RMS(dis_resultante_ML)

        totex_total = calc.totex(APs, MLs)
        totex_AP = calc.totexParcial(APs)
        totex_ML = calc.totexParcial(MLs)

        mvelo_total = calc.mVelo(totex_total, 20)
        mvelo_AP = calc.mVelo(totex_AP, 20)
        mvelo_ML = calc.mVelo(totex_ML, 20)

        self.entry_Mdist.set_text(str(dis_media))

        self.entry_Rdist_TOTAL.set_text(str(dis_rms_total))
        self.entry_Rdist_AP.set_text(str(dis_rms_AP))
        self.entry_Rdist_ML.set_text(str(dis_rms_ML))

        self.entry_TOTEX_TOTAL.set_text(str(totex_total))
        self.entry_TOTEX_AP.set_text(str(totex_AP))
        self.entry_TOTEX_ML.set_text(str(totex_ML))

        self.entry_MVELO_TOTAL.set_text(str(mvelo_total))
        self.entry_MVELO_AP.set_text(str(mvelo_AP))
        self.entry_MVELO_ML.set_text(str(mvelo_ML))

        max_absoluto_AP = calc.valorAbsoluto(min(APs), max(APs))
        max_absoluto_ML = calc.valorAbsoluto(min(MLs), max(MLs))

        max_absoluto_AP *= 1.25
        max_absoluto_ML *= 1.25

        print('max_absoluto_AP:', max_absoluto_AP, 'max_absoluto_ML:',
              max_absoluto_ML)
        self.axis.clear()

        self.axis.set_xlim(-max_absoluto_AP, max_absoluto_AP)
        self.axis.set_ylim(-max_absoluto_ML, max_absoluto_ML)

        self.axis.plot(APs, MLs, '-', color='g')
        self.axis.set_ylabel('ML')
        self.axis.set_xlabel('AP')
        self.canvas.draw()
コード例 #34
0
class MainClass():
    def __init__(self):
        # Gets all the objects of interest: windows, list boxes, graphviews etc
        self.builder = Gtk.Builder()
        self.builder.add_from_file('gui/igl-app-window.glade')
        self.builder.connect_signals(self)

        self.window = self.builder.get_object('window1')

        self.sw = self.builder.get_object('graphscrollwindow')
        self.sw2 = self.builder.get_object('graphtools')

        self.gtbrevealer = self.builder.get_object('graphtoolsrevealer')
        self.m1revealer = self.builder.get_object('method1revealer')
        self.m2revealer = self.builder.get_object('method2revealer')

        self.fnbox = self.builder.get_object('functioncbtext')
        self.aentry = self.builder.get_object('aentry')
        self.bentry = self.builder.get_object('bentry')

        # Use Headerbar for inputs

        self.hb = Gtk.HeaderBar()
        self.hb.set_show_close_button(True)
        self.hb.set_custom_title(self.builder.get_object('titlebox'))

        self.window.set_titlebar(self.hb)

        # Adds widgets that change the view as per method

        self.m1box = guisetup.MethodDetailsBox()
        self.m2box = guisetup.MethodDetailsBox()
        self.m1revealer.add(self.m1box)
        self.m2revealer.add(self.m2box)
        self.m1box.mc = self
        self.m2box.mc = self
        
        # TODO: Plot as per the defaults to get started

        self.fig = Figure(figsize=(5,5), dpi=80)
        self.ax = self.fig.add_subplot(111)
        self.canvas = FigureCanvas(self.fig)
        self.sw.add_with_viewport(self.canvas)

        self.toolbar = NavigationToolbar(self.canvas, self.window)
        self.sw2.add_with_viewport(self.toolbar)

        self.on_params_changed(None)

    def on_window1_destroy(self, widget):
        Gtk.main_quit()

    def toggle_allreveal(self, widget):
        self.toggle_m1reveal(widget)
        self.toggle_m2reveal(widget)
        self.toggle_gtbreveal(widget)

    # TODO make these change as per the toggle, rather than simply toggling

    def toggle_gtbreveal(self, widget):
        if self.gtbrevealer.get_reveal_child():
            self.gtbrevealer.set_reveal_child(False)
        else:
            self.gtbrevealer.set_reveal_child(True)

    def toggle_m1reveal(self, widget):
        if self.m1revealer.get_reveal_child():
            self.m1revealer.set_reveal_child(False)
        else:
            self.m1revealer.set_reveal_child(True)
        self.plotexact()
            
    def toggle_m2reveal(self, widget):
        if self.m2revealer.get_reveal_child():
            self.m2revealer.set_reveal_child(False)
        else:
            self.m2revealer.set_reveal_child(True)
        self.plotexact()

    def resetplot(self):
        self.ax.cla()
        self.ax.grid(True)

    def plotexact(self):
        self.resetplot()
        n = 1000
        xs = linspace(self.a, self.b, n+1, endpoint=True)
        fxs = self.f(xs)
        fxexact = self.ax.plot(xs, fxs, 'k-', label='f(x)')

        #    def plotapprox(self):
        #        pass
        # TODO: Make these happen somewhere else. Also, make these hide if the method revealer is hidden
        if self.m1revealer.get_reveal_child():
            fxapprox1 = self.ax.plot(xs, self.m1box.fapprox(xs), 'b-', label='Method 1')
        if self.m2revealer.get_reveal_child():
            fxapprox2 = self.ax.plot(xs, self.m2box.fapprox(xs), 'r-', label='Method 2')
        self.ax.legend()
        self.canvas.draw()

    def on_params_changed(self, widget):
        # print 'Integrand changed'
        try:
            self.f = eval('lambda x: '+self.fnbox.get_active_text())
            self.a = eval(self.aentry.get_text())
            self.b = eval(self.bentry.get_text())
            self.m1box.set_exact_function_and_bounds(self.f,self.a,self.b)
            self.m2box.set_exact_function_and_bounds(self.f,self.a,self.b)
            self.plotexact()
        except SyntaxError,NameError:
            pass
        except: