Example #1
0
class GraphPlotter(tk.Frame):
    def __init__(self, master):
        super().__init__(master)
        self.grid(row=0, column=1, sticky='nsew')
        self.load_plotters()
        self.setup_canvas()
        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)

    def setup_canvas(self):
        self.figure = matplotlib.figure.Figure(figsize=(5, 5), dpi=100)
        self.canvas = FigureCanvasTkAgg(self.figure, self)
        self.draw_plot(None)
        self.canvas.get_tk_widget().grid(column=0, row=0, sticky='nsew')

    def load_plotters(self):
        import data_browser.plotting_modules
        self.plotters = {module.FILE_EXTENSION: module.DEFAULT_PLOTTER
                         for module
                         in data_browser.plotting_modules.__all__}

    def draw_plot(self, file):
        self.figure.clf()
        if file is None or os.path.isdir(file):
            plot_dir(file, self.figure)
        elif os.path.splitext(file)[1] in self.plotters:
            try:
                self.plotters[os.path.splitext(file)[1]](file, self.figure)
            except Exception as e:
                plot_error(e, self.figure)
        else:
            plot_error(ValueError('cannot plot {}'.format(file)), self.figure)
        self.canvas.draw_idle()
Example #2
0
class NetIncomeGraph:
    def __init__(self):
        self.canvas = None
        self.fig = Figure(figsize=(12, 5), dpi=80)

    def plot_net_income(self, container, ticker_symbol, Frequency):
        ticker_object = ticker.get_ticker(
            ticker_symbol
        )  ## Gets the ticker object so you can access the various objects
        income_statements_data_drame = income.get_income_statement(
            ticker_object, Frequency)
        income_statement = income.get_net_income(income_statements_data_drame)
        company_name = priceData.get_company_name(ticker_object, ticker_symbol)
        dates = date.get_dates(income_statements_data_drame)
        income_statement_title = 'Net income'

        ax = self.fig.add_subplot(111)

        yLabelText = "Net Income in $"
        graph_title = company_name + " " + income_statement_title
        ax.set_title(graph_title)
        ax.set_xlabel('Period')
        ax.set_ylabel(yLabelText)

        ax.get_yaxis().set_major_formatter(
            matplotlib.ticker.FuncFormatter(lambda x, p: format(int(x), ',')))

        ax.bar(dates,
               income_statement,
               color=['r' if v < 0 else 'g' for v in income_statement])
        for i, v in enumerate(income_statement):
            ax.text(i,
                    v * 0.75,
                    f'${v:,.0f}',
                    fontweight='bold',
                    va='center',
                    ha='center',
                    color='#0A0A0A')

        legend_handles = [
            Line2D([0], [0],
                   linewidth=0,
                   marker='o',
                   markerfacecolor=color,
                   markersize=12,
                   markeredgecolor='none') for color in ['g', 'r']
        ]
        ax.legend(legend_handles,
                  ['positive net income', 'negative net income'])

        if not self.canvas:
            self.canvas = FigureCanvasTkAgg(self.fig, container)
            self.canvas.get_tk_widget().pack(side="top",
                                             fill="both",
                                             expand=True)
        self.canvas.draw_idle()

    def clearPlotPage(self):
        self.fig.clear()  # clear your figure
        self.canvas.draw_idle()  # redraw your canvas so it becomes empty
Example #3
0
class Fund(BaseFrame):
    def __init__(self, parent=None):
        super().__init__(parent)
        # 设置光标样式
        # self.config(cursor='sb_h_double_arrow')
        self.make_widgets()
        self.handle = EventHandler(self.fig, self.canvas, self.ax)
        self.handle.connect()

    def make_widgets(self):
        self.fig, self.ax = plt.subplots()
        self.ax.yaxis.grid(linestyle="-.", color='silver')
        self.canvas = FigureCanvasTkAgg(self.fig, self)
        # self.draw()
        self.canvas.get_tk_widget().pack(side=tk.TOP,
                                         fill=tk.BOTH,
                                         expand=tk.YES)

    def display(self, data):
        self.ax.cla()
        # self.ax.clear()
        # 根据回测日期选择显示的时间格式fmt
        # temp = [f['Time'] for f in data["Fund"]]
        x = [pd.Timestamp(int2date(f['Time'])) for f in data['Fund']]
        y = [f['DynamicEquity'] for f in data['Fund']]
        self.ax.set_xlim(0, len(y) - 1)
        self.handle.set_border()
        self.handle.set_x_labels(x)
        if data['KLineType'] == EEQU_KLINE_DAY:
            fmt = mdate.DateFormatter('%Y-%m')
        elif data['KLineType'] == EEQU_KLINE_MINUTE:
            fmt = mdate.DateFormatter('%Y-%m-%d')
        else:  # 有待更改
            fmt = mdate.DateFormatter('%Y-%m-%d')
        self.ax.plot(y, marker='.', color='red', linewidth=2.0, linestyle='-')
        self.ax.set_xticklabels(x)

        def format_date(x_, pos=None):
            if x_ < 0 or x_ > len(x) - 1:
                return
            return x[int(x_)]

        #TODO: length先暂时这样处理吧!
        length = 0
        if len(x) > 0 and len(x) <= 100:
            length = 30
        elif len(x) > 100 and len(x) <= 1000:
            length = 200
        elif len(x) > 1000 and len(x) < 10000:
            length = 2000
        else:
            length = 20000

        self.ax.xaxis.set_major_formatter(ticker.FuncFormatter(format_date))
        self.ax.xaxis.set_major_locator(ticker.MultipleLocator(length))
        # 此处使用self.canvas.draw()会使程序崩溃
        self.canvas.draw_idle()
class StatisticBarGUI(BaseFrame):
    @staticmethod
    def default_gui_config():
        default_config = BaseFrame.default_gui_config()
        default_config.figure = {'figsize': (6, 5), 'dpi': 100}
        default_config.legend = {'loc': 'upper right'}
        default_config.statistics = ad.Config()
        return default_config

    def __init__(self, master=None, gui_config=None, **kwargs):
        super().__init__(master=master, gui_config=gui_config, **kwargs)

        self.create_gui()

    def create_gui(self):

        # make the treeview in the frame resizable
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

        self.figure = plt.Figure(**self.gui_config['figure'])
        self.ax = self.figure.add_subplot(111)
        self.legend = None

        self.figure_canvas = FigureCanvasTkAgg(self.figure, master=self)
        self.figure_canvas.get_tk_widget().grid(sticky=tk.NSEW)

        self.master.update_idletasks()

    def display_exploration_data(self, exploration_data, run_id):
        self.display_data(exploration_data.runs[run_id].statistics)

    def display_data(self, statistics):

        if not isinstance(statistics, collections.abc.Sequence):
            self.statistics = [statistics]
        else:
            self.statistics = statistics

        self.ax.clear()

        stat_names = []
        for stat_config_idx in range(len(self.gui_config.statistics)):
            stat_config = self.gui_config.statistics[stat_config_idx]
            stat_name = stat_config['name']
            disp_name = stat_config.get('disp_name', stat_name)
            stats_idx = stat_config.get('stats_idx', 0)

            stat_data = self.statistics[stats_idx][stat_name]

            stat_names.append(disp_name)
            self.ax.bar(stat_config_idx, stat_data, align='center')

        self.ax.set_xticks(range(len(stat_names)))
        self.ax.set_xticklabels(stat_names)

        self.figure_canvas.draw_idle()
Example #5
0
class CashBasedEarningGraph:
    def __init__(self):
        self.canvas = None
        self.fig = Figure(figsize=(12, 5), dpi=80)

    def plotCashToEarnings(self, container, ticker_symbol, frequency):
        ticker_object = ticker.get_ticker(
            ticker_symbol
        )  # Gets the ticker object so you can access the various objects
        income_statements_data_frame = income.get_income_statement(
            ticker_object, frequency)
        net_income = income.get_net_income(income_statements_data_frame)
        cash_flow_data_frame = cash_flow_page.get_cash_flow_data(
            ticker_object, frequency)
        operating_cash_flow = cash_flow_page.get_operating_cash_flow(
            cash_flow_data_frame)

        company_name = price_data.get_company_name(ticker_object,
                                                   ticker_symbol)
        all_dates = dates.get_dates(cash_flow_data_frame)

        if operating_cash_flow.iloc[-1] > net_income.iloc[-1]:
            print(f'{company_name} has high quality earnings')
        else:
            print(f'{company_name} has low quality earnings')

        title = 'Cash Based Earnings'

        ax = self.fig.add_subplot(111)
        yLabelText = "Amount in $"
        graph_title = company_name + " " + title
        ax.set_title(graph_title)
        ax.set_xlabel('Period')
        ax.set_ylabel(yLabelText)

        ax.get_yaxis().set_major_formatter(
            matplotlib.ticker.FuncFormatter(lambda x, p: format(int(x), ',')))

        ax.plot(all_dates,
                operating_cash_flow,
                '-o',
                label='Cash From Operations')
        ax.plot(all_dates, net_income, '-o', label='Net Income')

        ax.legend()

        if not self.canvas:
            self.canvas = FigureCanvasTkAgg(self.fig, container)
            self.canvas.get_tk_widget().pack(side="top",
                                             fill="both",
                                             expand=True)
        self.canvas.draw_idle()

    def clearPlotPage(self):
        self.fig.clear()  # clear your figure
        self.canvas.draw_idle()  # redraw your canvas so it becomes empty
Example #6
0
class PieChartView(tk.Frame):
    canvas = None
    controller = None
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        label = tk.Label(self, text="Pie chart", font=LARGE_FONT)
        label.pack(pady=10, padx=10)
        labels = 'Positive', 'Neutral', 'Negative'
        amount = [pos, neut, neg]
        print(amount)
        colors = ['green', 'lightskyblue', 'red']
        explode = (0, 0.05, 0)  # proportion with which to offset each
        # wedge
        entry1 = ttk.Entry(self)
        entry1.pack()
        button3 = ttk.Button(self, text="Start stream ",
                             command=lambda: controller.start_stream(
                                 entry1.get()))
        button3.pack()

        piechart.pie(amount,  # data
                     explode=explode,  # offset parameters
                     labels=labels,  # slice labels
                     colors=colors,  # array of colours
                     autopct='%1.1f%%',  # print the values inside the wedges
                     shadow=True,  # enable shadow
                     startangle=70  # starting angle
                     )
        piechart.axis('equal')
        button1 = ttk.Button(self, text="Back to Home",
                             command=lambda: self.stop())
        button1.pack()
        self.canvas = FigureCanvasTkAgg(figure2, self)
        self.canvas.draw()

        self.canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH,
                                         expand=True)

        self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
    '''
    Roept de stop functie aan op de controller, en gaat terug naar de
    startpagina
    '''
    def stop(self):
        self.controller.show_frame(WelcomePage)
        self.controller.controller.stop_stream()
    '''
    Zorgt ervoor dat de pie chart de nieuwe waarden gebruikt
    '''
    def update(self):
        piechart.clear()
        piechart.pie([pos, neut, neg])
        self.canvas.draw_idle()
Example #7
0
class Graph(Frame):
    """
    Graph class that creates a linegraph and updates every 40 seconds
    Source: https://pythonprogramming.net/how-to-embed-matplotlib-graph-tkinter-gui/
    """
    def __init__(self, parent=None, shutter=None):
        super().__init__(parent)
        self.config(bg="ghost white")
        self.shutter = shutter

        f = Figure(figsize=(6, 6), dpi=100, facecolor='#f8f8ff')
        self.ax = f.add_subplot(111)

        # Sets for the plot
        self.timeset = []
        self.valueset = []

        self.ax.clear()
        self.ax.set_ylabel("Temperatuur in °C")
        self.ax.plot(self.timeset, self.valueset)

        # The graph magic
        self.canvas = FigureCanvasTkAgg(f, self)
        self.canvas.draw()
        self.canvas.get_tk_widget().pack(side="bottom",
                                         fill="both",
                                         expand=True)

        # Start 40 second update loop
        self.update_graph()

    def update_graph(self):
        # Append new value to plots
        self.timeset.append(datetime.now().strftime('%H:%M:%S'))
        self.valueset.append(self.shutter.get_temp())

        # If there is more than 5 time entries, remove the oldest value
        if len(self.timeset) > 5:
            self.timeset.remove(self.timeset[0])
            self.valueset.remove(self.valueset[0])

        # Redraw the graph
        self.ax.clear()
        self.ax.set_title("Temperatuur over de tijd")
        self.ax.set_ylabel("Temperatuur in °C")
        self.ax.set_xticklabels(self.timeset, rotation='45')
        self.ax.plot(self.timeset, self.valueset)

        self.canvas.draw_idle()

        self.after(40000, self.update_graph)
Example #8
0
 def get_frame_for_figure(master, figure_function):
     frame = tk.Frame(master)
     fig = plt.figure(figsize=plt.figaspect(0.6))
     canvas = FigureCanvasTkAgg(fig, frame)
     figure_function(fig=fig)
     canvas.draw_idle()
     canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
     toolbar = NavigationToolbar2Tk(canvas, frame)
     toolbar.update()
     fig.savefig = ExperimentPlot.save_figure(fig.savefig.__func__, fig,
                                              frame)
     canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
     frame.pack(fill=tk.BOTH, expand=True)
     return frame
Example #9
0
def ecualizar():
    global imageLoad
    global estilo
    global actual

    actual = "ecualizada"
    imageLoad = equalize(imageLoad)
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.axis('off')
    ax.imshow(imageLoad, cmap=estilo)
    canvas = FigureCanvasTkAgg(fig, ventana)
    canvas.get_tk_widget().grid(row=5, column=0, columnspan=3)
    canvas.draw_idle()
Example #10
0
class DebtGraph:
    def __init__(self):
        self.canvas = None
        self.fig = Figure(figsize=(12, 5), dpi=80)

    def plot_debt_graph(self, container, ticker_symbol, frequency):
        ticker_object = ticker.get_ticker(
            ticker_symbol
        )  ## Gets the ticker object so you can access the various objects
        balance_sheet_data_frame = balancesheet.get_balance_sheet_data(
            ticker_object, frequency)
        long_term_debt = balancesheet.get_long_term_debt(
            balance_sheet_data_frame)
        company_name = price_data.get_company_name(ticker_object,
                                                   ticker_symbol)
        dates = date.get_dates(balance_sheet_data_frame)
        graph_title = 'Long Term Debt'

        ax = self.fig.add_subplot(111)

        yLabelText = "Long term Debt $"
        graph_title = company_name + " " + graph_title
        ax.set_title(graph_title)
        ax.set_xlabel('Period')
        ax.set_ylabel(yLabelText)

        ax.get_yaxis().set_major_formatter(
            matplotlib.ticker.FuncFormatter(lambda x, p: format(int(x), ',')))

        ax.bar(dates, long_term_debt, color='r')
        for i, v in enumerate(long_term_debt):
            ax.text(i,
                    v * 0.75,
                    f'${v:,.0f}',
                    fontweight='bold',
                    va='center',
                    ha='center')

        if not self.canvas:
            self.canvas = FigureCanvasTkAgg(self.fig, container)
            self.canvas.get_tk_widget().pack(side="top",
                                             fill="both",
                                             expand=True)
        self.canvas.draw_idle()

    def clearPlotPage(self):
        self.fig.clear()  # clear your figure
        self.canvas.draw_idle()  # redraw your canvas so it becomes empty
Example #11
0
def conv():
    global imageLoad
    global filtro
    global estilo
    global actual
    global output

    output = convolucion(imageLoad, filtro)
    actual = "conv"
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.axis('off')
    ax.imshow(output, cmap=estilo)
    canvas = FigureCanvasTkAgg(fig, ventana)
    canvas.get_tk_widget().grid(row=5, column=0, columnspan=3)
    canvas.draw_idle()
Example #12
0
class PlottingCanvas():
    def __init__(self,master,fig, grid_pos):
        container = ttk.LabelFrame(master, text='플로터')
        container.grid(row=grid_pos[0], column=grid_pos[1], rowspan=2)

        self.canvas = FigureCanvasTkAgg(fig, master=container)
        self.canvas.get_tk_widget().grid(row=0, column=0)

    def update(self):
        self.canvas.draw_idle()

    def cbind(self, id, func):
        self.canvas.mpl_connect(id, func)

    def __del__(self):
        print('PlottingCanvas has been deleted')
Example #13
0
def textoCaja(textoEntrada):
    global imageLoad
    global estilo
    global actual

    actual = "original"
    imageLoad = cv2.imread(str(textoEntrada.get()))

    if len(imageLoad.shape) == 3:
        imageLoad = cv2.cvtColor(imageLoad, cv2.COLOR_BGR2GRAY)

    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.axis('off')
    ax.imshow(imageLoad, cmap=estilo)
    canvas = FigureCanvasTkAgg(fig, ventana)
    canvas.get_tk_widget().grid(row=5, column=0, columnspan=3)
    canvas.draw_idle()
Example #14
0
def cambiarEstilo(style):
    global estilo
    global actual
    global output

    estilo = style

    if (actual == "original"):
        textoCaja(textoEntrada)
    elif (actual == "ecualizada"):
        ecualizar()
    elif (actual == "conv"):
        fig = plt.figure()
        ax = fig.add_subplot(111)
        ax.axis('off')
        ax.imshow(output, cmap=estilo)
        canvas = FigureCanvasTkAgg(fig, ventana)
        canvas.get_tk_widget().grid(row=5, column=0, columnspan=3)
        canvas.draw_idle()
Example #15
0
class RevenueGraph:
    def __init__(self):
        self.canvas = None
        self.fig = Figure(figsize=(12, 5), dpi=80)

    def plot_revenue(self, container, ticker_symbol, frequency):
        ticker_object = ticker.get_ticker(
            ticker_symbol
        )  # Gets the ticker object so you can access the various objects
        earnings_data = earning.get_earnings_data(ticker_object)
        company_name = price_data.get_company_name(ticker_object,
                                                   ticker_symbol)

        data = self.get_freqency(earnings_data, ticker_symbol, frequency)
        earnings_data_frame = pd.DataFrame(data)
        dates = earnings_data_frame['date'].astype(str)
        revenue = earnings_data_frame['revenue']
        revenue = revenue / 100  # This scales the earnings value to Millions or Billions depends on how you want to read the chart

        ax = self.fig.add_subplot(111)
        yLabelText = "Amount in $"
        graph_title = company_name + " " + 'Revenue'
        ax.set_title(graph_title)
        ax.set_xlabel('Period')
        ax.set_ylabel(yLabelText)

        ax.get_yaxis().set_major_formatter(
            matplotlib.ticker.FuncFormatter(lambda x, p: format(int(x), ',')))

        ax.bar(dates, revenue,
               color=['r' if v < 0 else 'g'
                      for v in revenue])  ## adding color to bar graphs
        for i, v in enumerate(revenue):
            ax.text(i,
                    v * 0.75,
                    f'${v:,.0f}',
                    fontweight='bold',
                    va='center',
                    ha='center')  ## printing values into the bar graphs

        legend_handles = [
            Line2D([0], [0],
                   linewidth=0,
                   marker='o',
                   markerfacecolor=color,
                   markersize=12,
                   markeredgecolor='none') for color in ['g', 'r']
        ]
        ax.legend(legend_handles, ['positive revenue', 'negative revenue'])

        # ax.legend()

        if not self.canvas:
            self.canvas = FigureCanvasTkAgg(self.fig, container)
            self.canvas.get_tk_widget().pack(side="top",
                                             fill="both",
                                             expand=True)
        self.canvas.draw_idle()

    def get_freqency(self, earnings_data, ticker_symbol, frequency):
        if frequency == 'yearly':
            yearly_finaincal_earnings = earnings_data[ticker_symbol][
                'financialsChart'][frequency]
            return yearly_finaincal_earnings
        else:
            quarterly_finaincal_earnings = earnings_data[ticker_symbol][
                'financialsChart'][frequency]
            return quarterly_finaincal_earnings

    def clear_plot(self):
        self.fig.clear()  # clear your figure
        self.canvas.draw_idle()  # redraw your canvas so it becomes empty
Example #16
0
class Aplicacion:
    ANCHO_CANVAS = 200
    ALTO_CANVAS = 200

    NUM_FILAS = 10
    NUM_COLUMNAS = 10

    ANCHO_CURSOR = ANCHO_CANVAS // NUM_COLUMNAS
    ALTO_CURSOR = ALTO_CANVAS // NUM_FILAS

    TEMPERATURA = 1
    PRESION = 2
    HUMEDAD = 3

    PERIODO_INICIAL = 1000

    def __init__(self):
        self.sense = SenseHat()

        self.midiendo = True  # Mediciones activas
        self.data_points = list()  # Puntos para la gráfica

        self.queue = queue.Queue()  # Para comunicacion con hebra worker
        self.cuadrados = dict(
        )  # Para ahorrar recursos GUI guardamos los cuadrados

        self.list_max = [105, 1260, 100]  # Temp, pres, hum
        self.periodo = self.PERIODO_INICIAL

        self.ventana1 = tk.Tk()
        self.ventana1.title("Práctica GUI SenseHat")

        self.agregar_menu()

        self.cuaderno1 = ttk.Notebook(self.ventana1)
        self.pagina1 = ttk.Frame(self.cuaderno1)
        self.cuaderno1.add(self.pagina1, text="Monitorización")

        self.pagina2 = ttk.Frame(self.cuaderno1)
        self.cuaderno1.add(self.pagina2, text="Gráfica")

        self.cuaderno1.grid(column=0, row=0)

        # Página 1
        self.control()
        self.mediciones()
        self.canvas()
        self.historico()

        # Página 2
        self.matplotlib()

        # Ya no utilizado. Controlando posición desde el emulador
        #self.ventana1.bind("<KeyPress>", self.presion_tecla)
        #self.ventana1.bind("<Button-1>", self.presion_raton)

        # Lento
        # while True:
        #    self.medir()
        #    self.ventana1.update()
        #    time.sleep(1)

        self.ventana1.after(self.periodo, self.llamada_medir)
        self.ventana1.after(1000, self.comprobar_joystick)
        self.ventana1.mainloop()

    # Métodos para colocar controles en interfaz gráfica

    def agregar_menu(self):
        self.menubar1 = tk.Menu(self.ventana1)
        self.ventana1.config(menu=self.menubar1)
        self.opciones1 = tk.Menu(self.menubar1, tearoff=0)
        self.opciones1.add_command(label="Configurar periodo",
                                   command=self.configurar)
        self.opciones1.add_command(label="Ver Contribuidores",
                                   command=self.contribuidores)

        self.menubar1.add_cascade(label="Opciones", menu=self.opciones1)

    def mediciones(self):
        self.labelframe1 = ttk.LabelFrame(self.pagina1, text="Medidas")
        self.labelframe1.grid(column=0, row=1)

        self.seleccion_tipo_dato = tk.IntVar(value=self.TEMPERATURA)

        self.radio1 = tk.Radiobutton(self.labelframe1,
                                     text="Temperatura",
                                     variable=self.seleccion_tipo_dato,
                                     value=self.TEMPERATURA)
        self.radio1.grid(column=0, row=1, padx=4, pady=4)

        self.datoSense = tk.StringVar()
        self.entryTemp = ttk.Entry(self.labelframe1,
                                   textvariable=self.datoSense)
        self.entryTemp.grid(column=1, row=0, padx=4, pady=4)

        self.radio2 = tk.Radiobutton(self.labelframe1,
                                     text="Presión",
                                     variable=self.seleccion_tipo_dato,
                                     value=self.PRESION)
        self.radio2.grid(column=1, row=1, padx=4, pady=4)

        self.radio3 = tk.Radiobutton(self.labelframe1,
                                     text="Humedad",
                                     variable=self.seleccion_tipo_dato,
                                     value=self.HUMEDAD)
        self.radio3.grid(column=2, row=1, padx=4, pady=4)

    def canvas(self):
        self.canvas1 = tk.Canvas(self.pagina1,
                                 width=self.ANCHO_CANVAS,
                                 height=self.ALTO_CANVAS,
                                 background="black")
        self.canvas1.grid(column=1, row=0, rowspan=2)
        self.columna_cursor = 0
        self.fila_cursor = 0

        self.crear_cuadrado()

    def control(self):
        self.labelframe2 = ttk.LabelFrame(self.pagina1, text="Control")
        self.labelframe2.grid(column=0, row=0)

        self.boton_start_stop = ttk.Button(self.labelframe2,
                                           text="Parar",
                                           command=self.start_stop)
        self.boton_start_stop.pack(side=tk.TOP)

        self.label_periodo = ttk.Label(self.labelframe2, text="Periodo: ")
        self.label_periodo.pack(side=tk.LEFT, padx=4, pady=4)

        self.label_periodo2 = ttk.Label(self.labelframe2,
                                        text=str(self.periodo))
        self.label_periodo2.pack(side=tk.RIGHT, padx=4, pady=4)

    def historico(self):
        self.labelframe3 = ttk.LabelFrame(self.pagina1, text="Histórico")
        self.labelframe3.grid(column=0,
                              row=2,
                              columnspan=2,
                              sticky=tk.W + tk.E)

        self.frame2 = tk.Frame(self.labelframe3)
        self.frame2.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
        #self.listbox1=tk.Listbox(self.frame2)
        #self.listbox1.pack(side = tk.LEFT, fill = tk.BOTH, expand=True)
        self.tree = ttk.Treeview(self.frame2)
        self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        self.scroll1 = tk.Scrollbar(self.frame2, orient=tk.VERTICAL)
        self.scroll1.configure(command=self.tree.yview)
        self.scroll1.pack(side=tk.RIGHT, fill=tk.Y)
        self.tree.config(
            yscrollcommand=self.scroll1.set)  # 2 conexiones tree <-> scroll

        self.tree['columns'] = ('value', 'when', 'type')

        self.tree.heading('#0', text='#Num')
        self.tree.heading('value', text='Valor')
        self.tree.heading('when', text='Fecha/Hora')
        self.tree.heading('type', text='Tipo')

        self.seleccion = tk.IntVar()
        self.check1 = tk.Checkbutton(self.labelframe3,
                                     text="Añadir a lista",
                                     variable=self.seleccion)
        self.check1.pack(side=tk.BOTTOM)

        self.frame_historico = tk.Frame(self.labelframe3)
        self.frame_historico.pack(side=tk.BOTTOM)

        self.boton_limpiar = tk.Button(self.frame_historico,
                                       text="Limpiar",
                                       command=self.limpiar_historico)
        self.boton_limpiar.pack(side=tk.LEFT)

        self.boton_exportar = tk.Button(self.frame_historico,
                                        text="Exportar",
                                        command=self.exportar_historico)
        self.boton_exportar.pack(side=tk.RIGHT)

        self.boton3 = ttk.Button(self.frame_historico,
                                 text="Calcular Media",
                                 command=self.comenzar_calculo)
        self.boton3.pack(side=tk.RIGHT)

    def matplotlib(self):
        tk.Label(self.pagina2, text="Temperatura", bg='white').pack()
        self.fig = Figure()

        self.ax = self.fig.add_subplot(
            111
        )  # https://matplotlib.org/3.1.3/api/_as_gen/matplotlib.pyplot.subplot.html: nºfilas, nºcolumnas, índice subplotcd
        self.ax.set_xlabel("X axis")
        self.ax.set_ylabel("Y axis")
        self.ax.cla()  # clear axis
        self.ax.grid()  # configura grid
        self.ax.set_xlim(0, 9)
        self.ax.set_ylim(0, 100)

        self.line, = self.ax.plot([], [], marker='o', color='orange')

        self.graph = FigureCanvasTkAgg(
            self.fig,
            master=self.pagina2)  # Agg: Anti-Grain geometry rendering engine
        self.graph.get_tk_widget().pack(side="top", fill='both', expand=True)

        self.ani = animation.FuncAnimation(self.fig,
                                           self.pinta_grafica,
                                           interval=1000,
                                           blit=False)
        self.graph.draw_idle()  # para comenzar refresco grafica
        #self.ventana1.after(1000,self.pinta_grafica)

    def configurar(self):
        dialogo1 = DialogoPeriodo(self.ventana1)
        self.periodo = dialogo1.mostrar()
        self.label_periodo2.configure(text=str(self.periodo))

    def contribuidores(self):
        dialogo1 = DialogoContribuidores(self.ventana1)
        dialogo1.mostrar()

    # Esta función utiliza las coordenadas actuales del cursor para crear el
    # cuadrado con marco rojo
    def crear_cuadrado(self):
        # Solo se crea una vez. No se "desperdician" recursos
        self.cuadrado = self.canvas1.create_rectangle(
            self.columna_cursor * self.ANCHO_CURSOR,
            self.fila_cursor * self.ALTO_CURSOR,
            (self.columna_cursor + 1) * self.ANCHO_CURSOR,
            (self.fila_cursor + 1) * self.ALTO_CURSOR,
            outline='red')

    # Métodos relacionados con mediciones periódicas

    def start_stop(self):
        if self.midiendo:
            self.midiendo = False
            self.boton_start_stop.configure(text='Comenzar')
        else:
            self.midiendo = True
            self.boton_start_stop.configure(text='Parar')

    def limpiar_historico(self):
        self.tree.delete(
            *self.tree.get_children())  # * "desempaqueta" argumento

    def get_datos_historico(self):
        l = list()

        for med in self.tree.get_children():
            # {'text': '0', 'image': '', 'values': ['25.0', '2020-03-04 21:17:44', 'Temperatura'], 'open': 0, 'tags': ''}
            id = self.tree.item(med)['text']
            values = self.tree.item(med)['values']
            l.append(Medicion(id, values[0], values[1], values[2]))

        return l

    def exportar_historico(self):
        ldatos = self.get_datos_historico()
        filename = tk.filedialog.asksaveasfilename(
            initialdir=".",
            title="Select file",
            filetypes=(("text files", "*.txt"), ("all files", "*.*")))
        worker_exportar.ExporterTask(filename, ldatos).start()

        # Bloquea interfaz si hay muchos datos
        #for l in ldatos:
        #    print(l)

    def str_tipo_medicion(self, tipo_medicion):
        if tipo_medicion == self.TEMPERATURA:
            res = "Temperatura"
        elif tipo_medicion == self.PRESION:
            res = "Presión"
        else:
            res = "Humedad"

        return res

    # Esta operación crea un cuadrado relleno según la temperatura en la posición
    # actual del cursor.
    # Actualiza también el cuadro de texto con la temperatura
    #
    # TODO: Comprobar si llamadas continuas a create_rectangle agotan recursos
    def medir(self):
        if self.seleccion_tipo_dato.get() == self.TEMPERATURA:
            self.datoSense.set(str(self.sense.temp))
        elif self.seleccion_tipo_dato.get() == self.PRESION:
            self.datoSense.set(str(self.sense.pressure))
        else:
            self.datoSense.set(str(self.sense.humidity))

        #print(self.datoSense.get())
        #self.canvas1.itemconfig(self.cuadrado,fill='red')

        # Evitamos crear rectángulos indefinidamente
        clave = (self.fila_cursor, self.columna_cursor)
        if clave in self.cuadrados:
            cuadrado = self.cuadrados[clave]
            self.canvas1.itemconfig(cuadrado,
                                    fill=self.color(
                                        float(self.datoSense.get()),
                                        self.seleccion_tipo_dato.get()))
        else:
            self.cuadrados[clave] = self.canvas1.create_rectangle(
                self.columna_cursor * self.ANCHO_CURSOR,
                self.fila_cursor * self.ALTO_CURSOR,
                (self.columna_cursor + 1) * self.ANCHO_CURSOR,
                (self.fila_cursor + 1) * self.ALTO_CURSOR,
                fill=self.color(float(self.datoSense.get()),
                                self.seleccion_tipo_dato.get()))

        self.canvas1.tag_raise(
            self.cuadrado)  # Para que el cursor siempre esté en primer plano

        if self.seleccion.get() == 1:
            #    self.listbox1.insert(0,self.datoSense.get())
            now = datetime.datetime.now()
            self.tree.insert('',
                             0,
                             text=str(len(self.tree.get_children())),
                             values=(self.datoSense.get(),
                                     now.strftime("%Y-%m-%d %H:%M:%S"),
                                     self.str_tipo_medicion(
                                         self.seleccion_tipo_dato.get())))

    # def presion_tecla(self, evento):
    #     if evento.keysym=='Right':
    #         self.columna_cursor=self.columna_cursor+1
    #         self.canvas1.move(self.cuadrado, self.ANCHO_CURSOR, 0)
    #     if evento.keysym=='Left':
    #         self.columna_cursor=self.columna_cursor-1
    #         self.canvas1.move(self.cuadrado, -self.ANCHO_CURSOR, 0)
    #     if evento.keysym=='Down':
    #         self.fila_cursor=self.fila_cursor+1
    #         self.canvas1.move(self.cuadrado, 0, self.ALTO_CURSOR)
    #     if evento.keysym=='Up':
    #         self.fila_cursor=self.fila_cursor-1
    #         self.canvas1.move(self.cuadrado, 0, -self.ALTO_CURSOR)

    # # TODO: deshabilitar cuando está en otra ventana
    # def presion_raton(self, evento):
    #     nueva_fila=int(evento.y/self.ANCHO_CURSOR)
    #     nueva_columna=int(evento.x/self.ALTO_CURSOR)

    #     difc = nueva_columna-self.columna_cursor
    #     diff = nueva_fila-self.fila_cursor

    #     self.fila_cursor=nueva_fila
    #     self.columna_cursor=nueva_columna

    #     self.canvas1.move(self.cuadrado, difc*self.ANCHO_CURSOR,
    #                                      diff*self.ALTO_CURSOR)

    def color(self, valor, tipo):
        if valor < 0.25 * self.list_max[tipo - 1]:
            return 'cyan'
        elif valor < 0.5 * self.list_max[tipo - 1]:
            return 'blue'
        elif valor < 0.75 * self.list_max[tipo - 1]:
            return 'yellow'
        else:
            return 'red'

    def pinta_grafica(self, i):
        #    def pinta_grafica(self):
        #self.ventana1.after(1000,self.pinta_grafica)
        self.data_points.append(self.sense.temp)
        if len(self.data_points) > 10:
            del self.data_points[0]
        self.line.set_data(range(len(self.data_points)), self.data_points)
        self.ax.set_ylim(min(self.data_points) - 1, max(self.data_points) + 1)
        #self.graph.draw_idle()  # para refrescar grafica

    def llamada_medir(self):
        self.ventana1.after(self.periodo, self.llamada_medir)
        if self.midiendo:
            self.medir()

    # Métodos relacionados con movimiento cursor

    def move_dot(self, event):
        #print(event)
        if event.action in ('pressed', 'held'):
            if event.direction == 'right':
                self.columna_cursor = self.columna_cursor + 1
                self.canvas1.move(self.cuadrado, self.ANCHO_CURSOR, 0)
            if event.direction == 'left':
                self.columna_cursor = self.columna_cursor - 1
                self.canvas1.move(self.cuadrado, -self.ANCHO_CURSOR, 0)
            if event.direction == 'down':
                self.fila_cursor = self.fila_cursor + 1
                self.canvas1.move(self.cuadrado, 0, self.ALTO_CURSOR)
            if event.direction == 'up':
                self.fila_cursor = self.fila_cursor - 1
                self.canvas1.move(self.cuadrado, 0, -self.ALTO_CURSOR)

    def comprobar_joystick(self):
        self.ventana1.after(1000, self.comprobar_joystick)
        for event in self.sense.stick.get_events():
            self.move_dot(event)

    # Metodos relacionados con "tarea larga duración"

    def process_queue(self):
        try:
            msg = self.queue.get(0)
            tk.messagebox.showinfo("Media", msg)
        except queue.Empty:
            self.ventana1.after(1000, self.process_queue)

    def comenzar_calculo(self):
        ldatos = self.get_datos_historico()  # Lista mediciones
        worker_media.ThreadedTask(self.queue, ldatos).start()
        self.ventana1.after(1000, self.process_queue)
Example #17
0
class Cut:
    def __init__(self, nb, app):
        self.nb = nb
        self.app = app
        self.frame = ttk.Frame(self.nb)
        self.levelCut = 30
        #self.frame2 = ttk.Frame(self.nb)
        self.nb.add(self.frame, text='   Cut   ')
        self.lastGcodeFileName = ""
        r = 0
        self.cutBtn = tk.Button(self.frame,
                                text='Cut',
                                width=25,
                                command=self.cut,
                                state='disabled')
        self.cutBtn.grid(column=0, row=r, padx=1, pady=(20, 1))
        r += 1
        self.cancelBtn = tk.Button(self.frame,
                                   text='Cancel',
                                   command=self.app.tGrbl.resetGrbl,
                                   width=25,
                                   state='disabled')
        self.cancelBtn.grid(column=0,
                            columnspan=2,
                            row=r,
                            pady=(10, 1),
                            sticky=W)
        r += 1
        self.button2 = tk.Button(self.frame,
                                 text='Save Gcode',
                                 width=25,
                                 command=self.saveGcode)
        self.button2.grid(column=0, row=r, padx=1, pady=(20, 1))
        r += 1
        tk.Label(self.frame,
                 text="Usual cutting speed (mm/sec)").grid(column=0,
                                                           row=r,
                                                           pady=(20, 1),
                                                           sticky=W)
        EntryFloat(self.frame,
                   self.app.vCut,
                   0.1,
                   10,
                   self.levelCut,
                   width='6').grid(column=1,
                                   row=r,
                                   padx=1,
                                   pady=(20, 1),
                                   sticky=W)

        r += 1
        tk.Label(self.frame, text="Errors").grid(column=0,
                                                 row=r,
                                                 pady=(20, 1),
                                                 padx=(10, 1),
                                                 sticky=W)
        r += 1
        tk.Label(self.frame, textvariable=self.app.cutMsg,
                 height=10).grid(column=0,
                                 columnspan=2,
                                 row=r,
                                 pady=(1, 1),
                                 padx=(10, 1),
                                 sticky=NW)

        self.figRoot = Figure(figsize=(10, 3), dpi=100)
        self.axesRoot = self.figRoot.add_subplot(1, 1, 1)
        self.axesRoot.autoscale(enable=False)
        self.axesRoot.set_xlim(0, 1300)
        self.axesRoot.set_ybound(0, 400)
        self.axesRoot.set_title('Root')
        self.lineRoot1, = self.axesRoot.plot([], [])
        self.lineRoot2, = self.axesRoot.plot([], [])
        self.canvasRoot = FigureCanvasTkAgg(
            self.figRoot, master=self.frame)  # A tk.DrawingArea.
        self.canvasRoot.draw()
        self.canvasRoot.get_tk_widget().grid(column=2,
                                             row=0,
                                             rowspan=20,
                                             padx=10,
                                             pady=(10, 2))

        self.figTip = Figure(figsize=(10, 3), dpi=100)
        self.axesTip = self.figTip.add_subplot(1, 1, 1)
        self.axesTip.autoscale(enable=False)
        self.axesTip.set_xlim(0, 1300)
        self.axesTip.set_ybound(0, 400)
        self.axesTip.set_title('Tip')
        self.lineTip1, = self.axesTip.plot([], [])
        self.lineTip2, = self.axesTip.plot([], [])
        self.canvasTip = FigureCanvasTkAgg(
            self.figTip, master=self.frame)  # A tk.DrawingArea.
        self.canvasTip.draw()
        self.canvasTip.get_tk_widget().grid(column=2,
                                            row=20,
                                            rowspan=20,
                                            padx=10,
                                            pady=(10, 2))

    def updateOProfil(
            self):  #update plotting the bloc (2 canvas: Top and Back)
        self.lineRoot1.set_xdata(self.oSimRX)
        self.lineRoot1.set_ydata(self.oSimRY)
        self.lineRoot2.set_xdata(self.app.pRootX)
        self.lineRoot2.set_ydata(self.app.pRootY)
        self.canvasRoot.draw_idle()

        self.lineTip1.set_xdata(self.oSimTX)
        self.lineTip1.set_ydata(self.oSimTY)
        self.lineTip2.set_xdata(self.app.pTipX)
        self.lineTip2.set_ydata(self.app.pTipY)
        self.canvasTip.draw_idle()

    def cut(self):
        self.app.tGrbl.stream(self.gcode)
        pass

    def saveGcode(self):
        gcodeFileName = filedialog.asksaveasfilename(title="Save as...", defaultextension="*.gcode",\
            filetypes=[("Gcode files","*.gcode"),("All files", "*")], initialfile=self.lastGcodeFileName)
        if len(gcodeFileName) > 0:
            f = open(gcodeFileName, 'w')
            f.write(self.gcode)
            f.close()
            self.lastGcodeFileName = gcodeFileName

    def calculateRedraw(self):
        self.calculate()
        self.updateOProfil()

    def calculate(self):
        #it start from PRoot and pTip (= profile taking care of bloc and margin)
        #add enty and exit points in bloc
        #applies offset for radiance
        #simplifies the profiles if possible = simRoot and Tip
        #calculate the projection GX GY DX and DY

        #Vérifier la présence et l'égalité du nombre de points dans les 2 profils
        #to do control number of synchro points
        if (len(self.app.tRootX) > 0) and (
                len(self.app.tTipX) >
                0):  # and (len(self.app.tRootX) == len(self.app.tTipX)):
            # create eRoot and eTip and add entry and exit point in the bloc (before applying heating offset)
            #print("pRootX pTipX", self.app.pRootX , self.app.pTipX)
            eRootX = self.app.pRootX.tolist()
            eRootY = self.app.pRootY.tolist()
            eRootS = list(self.app.pRootS)
            eTipX = self.app.pTipX.tolist()
            eTipY = self.app.pTipY.tolist()
            eTipS = list(self.app.pTipS)
            eRootX.insert(0, self.app.blocToTableTrailingRoot.get())
            eRootY.insert(0, self.app.pRootY[0])
            eTipX.insert(0, self.app.blocToTableTrailingTip.get())
            eTipY.insert(0, self.app.pTipY[0])
            eRootX.append(self.app.blocToTableTrailingRoot.get())
            eRootY.append(self.app.pRootY[-1])
            eTipX.append(self.app.blocToTableTrailingTip.get())
            eTipY.append(self.app.pTipY[-1])
            eRootS.insert(0, 10)  # add a Synchro and no radiance point
            eTipS.insert(0, 10)  # add a Synchro and no radiance point
            eRootS[
                -1] = 10  # mark the last point as Synchro and no radiance point
            eTipS[
                -1] = 10  # mark the last point as Synchro and no radiance point
            eRootS.append(4)  #add a last point as Synchro
            eTipS.append(4)  #add a last point as Synchro
            #print("Root=", list(zip(eRootX, eRootY, eRootS)))
            #build 2 listes with length of segments
            rootL = lengthSegment(eRootX, eRootY)
            tipL = lengthSegment(eTipX, eTipY)

            #build list of index of pt of synchro and length of sections between synchro
            eRootI, eRootL = lengthSection(eRootS, rootL)
            eTipI, eTipL = lengthSection(eTipS, tipL)
            #print("index and length of root", eRootS , rootL ,  eRootI , eRootL)

            #compare les longueurs pour trouver le coté le plus long
            compLength = compareLength(eRootL, eTipL)
            #print("compare length", compLength)
            #Calcule la radiance de chaque côté ; met 0 si
            rRoot, rTip = self.calculate2Radiance(compLength,
                                                  self.app.vCut.get())
            #print("radiance root, tip", rRoot , rTip)
            #create eRootR and eTipR with the radiance to fit the same nbr of item as exxxS
            eRootR = self.createRadiance(eRootS, rRoot)
            #print('full radiance root', eRootR)
            eTipR = self.createRadiance(eTipS, rTip)
            #print('full radiance tip', eTipR)
            # calculate offset on each side; create one new point at each synchronisation to take care of different radiance offsets
            self.offsetRootX, self.offsetRootY, self.offsetRootS = self.calculateOffset(
                eRootX, eRootY, eRootR, eRootS)
            #print("offset root", list(zip( self.offsetRootX , self.offsetRootY ,self.offsetRootS)))
            self.offsetTipX, self.offsetTipY, self.offsetTipS = self.calculateOffset(
                eTipX, eTipY, eTipR, eTipS)
            #print("len R T",len(self.offsetRootX) , len(self.offsetTipX) )
            # adjust points in order to have the same number of points on each section
            self.syncRX, self.syncRY, self.syncTX, self.syncTY = self.synchrAllSections(
                self.offsetRootX, self.offsetRootY, self.offsetRootS,
                self.offsetTipX, self.offsetTipY, self.offsetTipS)
            """
            print("eRoot X Y", eRootX, eRootY)
            print("eTip X Y", eTipX, eTipY)
            print("offset RX RY", self.offsetRootX , self.offsetRootY)
            print("offset TX TY", self.offsetTipX , self.offsetTipY)
            print("distance offset Rx Ry", self.printDistance(self.offsetRootX , self.offsetRootY))
            print("distance offset Tx Ty",  self.printDistance(self.offsetTipX , self.offsetTipY))
            """
            #Remove points if they are to close from each other (on both sides)
            #print("Offset ", self.offsetRootX , self.offsetRootY , self.offsetTipX , self.offsetTipY)
            self.oSimRX, self.oSimRY, self.oSimTX, self.oSimTY = self.simplifyProfiles(
                self.syncRX, self.syncRY, self.syncTX, self.syncTY)

            #print("len before after",  len(self.syncRX), len(self.oSimRX))

            #Calculate projections on cnc axis, messages, speed and feedRate (inverted)
            if self.app.leftRightWing.get(
            ) == 'Right':  #for right wing, the root is on the left side
                self.GX, self.DX, self.GY, self.DY, self.warningMsg, self.speed, self.feedRate = self.projectionAll(
                    self.oSimRX, self.oSimTX, self.oSimRY, self.oSimTY,
                    self.app.blocToTableLeft.get() + self.app.tableYG.get(),
                    self.app.blocLX.get(),
                    self.app.tableYY.get() - self.app.blocToTableLeft.get() -
                    self.app.tableYG.get() - self.app.blocLX.get())
            else:  #Left wing = root is on rigth side
                self.GX, self.DX, self.GY, self.DY, self.warningMsg, self.speed, self.feedRate = self.projectionAll(
                    self.oSimTX, self.oSimRX, self.oSimTY, self.oSimRY,
                    self.app.blocToTableLeft.get() + self.app.tableYG.get(),
                    self.app.blocLX.get(),
                    self.app.tableYY.get() - self.app.blocToTableLeft.get() -
                    self.app.tableYG.get() - self.app.blocLX.get())

            #print(self.warningMsg)
            self.app.cutMsg.set(self.warningMsg)
            #print("Projection ", self.GX , self.DX , self.GY, self.DY)
            #print("Projection ", self.GX , self.DX )
            #genère le Gcode
            # set G54 à la valeur actuelle, set absolu et mm, set feed rate, met en chauffe, attend 5 sec
            # monte à la hauteur du ppremier point puis avance au premier point
            # passe tous les points
            # revient à la verticale de l'origine puis à l'origine
            # attend 5 sec puis éteint la chauffe puis éteint les moteurs

            self.gcode = self.generateGcode(self.GX, self.DX, self.GY, self.DY,
                                            self.speed, self.feedRate)

    def createRadiance(self, s, r):
        # create a radiance list with the same nbr of items as s and using the radiance in r
        imax = len(s)
        i = 0
        rIdx = 0
        rTemp = 0
        result = []
        while i < (imax - 1):
            if s[i] > 0:
                if s[i] > 4:
                    rTemp = 0
                else:
                    rTemp = r[rIdx]
                rIdx += 1
            result.append(rTemp)
            i += 1
        return result

    def printDistance(self, x, y):
        imax = len(x)
        i = 0
        result = []
        while i < imax - 1:
            d1 = x[i + 1] - x[i]
            d2 = y[i + 1] - y[i]
            result.append(math.sqrt(d1 * d1 + d2 * d2))
            i += 1
        return result

    def generateGcode(self, GX, DX, GY, DY, axisSpeed, feedRate):
        #gCodeStart ="G10 L20 P1 X0 Y0 Z0 A0 \n G90 G21 M3 \n G04 P5.0\n G01 X0 \n"
        #gCodeEnd = "G04 P5.0\n M5\n M2\n"
        heat = self.app.tGuillotine.calculateHeating(self.app.vCut.get())
        formatAxis = "{:.3f} "
        #A="X{:.3f} Y{:.3f} Z{:.3f} A{:.3f}\n"
        L = self.app.gCodeLetters.get() + "XYZA"  # contains 4 letters
        G00 = "G00 " + L[0] + formatAxis + L[1] + formatAxis + L[
            2] + formatAxis + L[3] + formatAxis + "\n"
        G01 = "G01 " + L[0] + formatAxis + L[1] + formatAxis + L[
            2] + formatAxis + L[3] + formatAxis + "F{:d}\n"
        xyza = L[0] + formatAxis + L[1] + formatAxis + L[2] + formatAxis + L[
            3] + formatAxis + "\n"
        st = self.app.gCodeStart1.get() + "\n" + self.app.gCodeStart2.get(
        ) + "\n" + self.app.gCodeStart3.get(
        ) + "\n" + self.app.gCodeStart4.get() + "\n"
        st = st + "G10 L20 P1" + xyza.format(
            0, 0, 0, 0)  #set wcs to current position: G10 L20 P1 X0 Y0 Z0 A0
        st = st + "G54\n"  # apply wcs1
        st = st + "S{:d}\n".format(
            int(heat))  # set the heating value based on speed
        st = st + "G90 G21 G93 M3\n"  # apply  Absolute and mm and inverted feedrate and heating
        st = st + "G04 P{:.1f}\n".format(
            self.app.tPreHeat.get())  # pause for the preheat delay
        en = "G04 P{:.1f}\n".format(
            self.app.tPostHeat.get())  # pause for the post delay
        en = en + "G94\nM5\nM2\n"  # go back to normal feedrate , stop heating and stop motor
        en = en + self.app.gCodeEnd1.get() + "\n" + self.app.gCodeEnd2.get(
        ) + "\n" + self.app.gCodeEnd3.get() + "\n" + self.app.gCodeEnd4.get(
        ) + "\n"
        li = []
        imax = len(GX)
        if imax > 1:
            i = 1
            li.append(st)  #append start
            li.append(G00.format(0.0, GY[0], 0.0, DY[0]), )  #move up
            li.append(G00.format(GX[0], GY[0], DX[0], DY[0]),
                      )  #move up to entry of bloc
            while i < imax:
                li.append(
                    G01.format(GX[i], GY[i], DX[i], DY[i], int(
                        feedRate[i - 1])))  # we use inverted feedRate
                i += 1
            li.append(G00.format(0, GY[-1], 0, DY[-1]))
            li.append(G00.format(0.0, 0.0, 0.0, 0.0))
            li.append(en)  #append End
        #print("".join(li)) #print the Gcode
        return "".join(li)  # return a string containing the /n

    def projectionAll(self, x1, x2, y1, y2, lg, l, ld):
        # lg = outside length on the left side (from bloc to axis)
        # l = legnth between the 2 sides of bloc
        # ld = outside length on the right side (from bloc to axis)
        # x1 y1 = profil on the left side
        # x2 y2 = profil on the rigth side
        # return projection, warning msg and speed
        xg = []
        xd = []
        yg = []
        yd = []
        speed = []  # in mm/sec
        feedRate = [
        ]  # inverted feed rate for G93: e.g. 2 means that the movement has to be executed in 1/2 min
        xgmin = x1[0]
        xgmax = x1[0]
        xdmin = x2[0]
        xdmax = x2[0]
        ygmin = y1[0]
        ygmax = y1[0]
        ydmin = y2[0]
        ydmax = y2[0]
        vxGMax = 0
        vyGMax = 0
        vxDMax = 0
        vyDMax = 0
        msg = ""
        i = 0
        imax = len(x1)
        if imax > 0:
            while i < imax:
                xg.append(((x1[i] - x2[i]) / l * lg) + x1[i])
                xd.append(((x2[i] - x1[i]) / l * (l + ld)) + x1[i])
                yg.append(((y1[i] - y2[i]) / l * lg) + y1[i])
                yd.append(((y2[i] - y1[i]) / l * (l + ld)) + y1[i])
                if xg[i] < xgmin: xgmin = xg[i]
                if xg[i] > xgmax: xgmax = xg[i]
                if xd[i] < xdmin: xdmin = xd[i]
                if xd[i] > xdmax: xdmax = xd[i]
                if yg[i] < ygmin: ygmin = yg[i]
                if yg[i] > ygmax: ygmax = yg[i]
                if yd[i] < ydmin: ydmin = yd[i]
                if yd[i] > ydmax: ydmax = yd[i]
                if i > 0:  #calculate speed on Y axis
                    #calculate legnth of segment
                    dx1 = x1[i - 1] - x1[i]
                    dy1 = y1[i - 1] - y1[i]
                    dx2 = x2[i - 1] - x2[i]
                    dy2 = y2[i - 1] - y2[i]
                    dxG = abs(xg[i - 1] - xg[i])
                    dyG = abs(yg[i - 1] - yg[i])
                    dxD = abs(xd[i - 1] - xd[i])
                    dyD = abs(yd[i - 1] - yd[i])
                    d1 = dx1 * dx1 + dy1 * dy1
                    d2 = dx2 * dx2 + dy2 * dy2
                    dG = dxG * dxG + dyG * dyG
                    dD = dxD * dxD + dyD * dyD
                    #select the longest side
                    if d1 >= d2:
                        d1 = math.sqrt(d1)
                        dG = math.sqrt(dG)
                        d2 = math.sqrt(d2)
                        dD = math.sqrt(dD)
                        v1 = self.app.vCut.get()
                        speed.append(v1 * dG / d1)
                        feedRate.append(v1 / d1 * 60)
                        vGD = v1 * dG / d1
                        vxG = v1 * dxG / d1
                        vyG = v1 * dyG / d1
                        vxD = v1 * dxD / d1
                        vyD = v1 * dyD / d1
                    else:
                        d1 = math.sqrt(d1)
                        dG = math.sqrt(dG)
                        d2 = math.sqrt(d2)
                        dD = math.sqrt(dD)
                        v2 = self.app.vCut.get()
                        speed.append(v2 * dD / d2)
                        feedRate.append(v2 / d2 * 60)
                        vGD = v2 * dD / d2
                        vxG = v2 * dxG / d2
                        vyG = v2 * dyG / d2
                        vxD = v2 * dxD / d2
                        vyD = v2 * dyD / d2
                    #print(" point {} dG={:.3f} d1={:.3f} dD={:.3f} d2={:.3f}  vGD={:.3f} vxG={:.3f}  vyG={:.3f} , vxD={:.3f} , vyD={:.3f} "\
                    #    .format(i , dG , d1, dD , d2, vGD, vxG , vyG , vxD , vyD))
                    if vxG > vxGMax: vxGMax = vxG
                    if vyG > vyGMax: vyGMax = vyG
                    if vxD > vxDMax: vxDMax = vxD
                    if vyD > vyDMax: vyDMax = vyD
                i += 1
            if xgmin < 0:
                msg = msg + "Left hor. axis exceeds origin\n"
            if xgmax > self.app.cMaxY.get():
                msg = msg + "Left hor. axis exceeds limit\n"
            if xdmin < 0:
                msg = msg + "Right hor. axis exceeds origin\n"
            if xdmax > self.app.cMaxY.get():
                msg = msg + "Right vertical axis exceeds limit\n"
            if ygmin < 0:
                msg = msg + "Left vertical axis exceeds origin\n"
            if ygmax > self.app.cMaxZ.get():
                msg = msg + "Left vertical axis exceeds limit\n"
            if ydmin < 0:
                msg = msg + "Right vertical axis exceeds origin\n"
            if ydmax > self.app.cMaxZ.get():
                msg = msg + "Right vertical axis exceeds limit\n"
            if vxGMax > self.app.vMaxY.get():
                msg = msg + "Left hor. axis exceeds speed {:.3f}\n".format(
                    vxGMax)
            if vyGMax > self.app.vMaxZ.get():
                msg = msg + "Left vertical axis exceeds speed\n"
            if vxDMax > self.app.vMaxY.get():
                msg = msg + "Right hor. axis exceeds speed\n"
            if vyDMax > self.app.vMaxZ.get():
                msg = msg + "Right vertical axis exceeds speed\n"
        return xg, xd, yg, yd, msg, speed, feedRate

    def simplifyProfiles(self, rX, rY, tX, tY):
        imax = len(rX)
        oRX = []
        oRY = []
        oTX = []
        oTY = []
        i = 0
        if imax > 0:
            rXp = rX[i]
            rYp = rY[i]
            tXp = tX[i]
            tYp = tY[i]
            oRX.append(rXp)
            oRY.append(rYp)
            oTX.append(tXp)
            oTY.append(tYp)
            i = 1
            while i < imax:
                dRX = rX[i] - rXp
                dRX *= dRX
                dRY = rY[i] - rYp
                dRY *= dRY
                dTX = tX[i] - tXp
                dTX *= dTX
                dTY = tY[i] - tYp
                dTY *= dTY
                if dRX > 0.01 or dRY > 0.01 or dTX > 0.01 or dTY > 0.01:
                    rXp = rX[i]
                    rYp = rY[i]
                    tXp = tX[i]
                    tYp = tY[i]
                    oRX.append(rXp)
                    oRY.append(rYp)
                    oTX.append(tXp)
                    oTY.append(tYp)
                i += 1
        return oRX, oRY, oTX, oTY

    def calculateOffset(self, x, y, r, s):
        #create an offset for curve x y at a distance r (which varies)
        # for each synchronisation point, create 2 offset points instead of 1
        #x ,y, r (radiance) , s (synchro) have the same length
        # return new x y s
        # pour 3 points successifs p1-p2-p3 avec r1-r2, calcule les pt d'intersection des 2 offsets
        ox = []
        oy = []
        os = []
        imax = len(r)
        i = 0
        if imax >= 1:
            #met le premier point
            oxi, oxj, oyi, oyj = offset1Segment(x[0], x[1], y[0], y[1], r[0])
            ox.append(oxi)
            oy.append(oyi)
            os.append(s[0])
            while i < (imax - 1):
                oxi, oyi = offset2Segment(x[i], x[i + 1], x[i + 2], y[i],
                                          y[i + 1], y[i + 2], r[i])
                ox.append(oxi)
                oy.append(oyi)
                os.append(s[i + 1])
                if s[i + 1] > 0:
                    oxi, oyi = offset2Segment(x[i], x[i + 1], x[i + 2], y[i],
                                              y[i + 1], y[i + 2], r[i + 1])
                    ox.append(oxi)
                    oy.append(oyi)
                    os.append(s[i + 1])
                i += 1
            oxi, oxj, oyi, oyj = offset1Segment(x[i], x[i + 1], y[i], y[i + 1],
                                                r[i])
            ox.append(oxj)
            oy.append(oyj)
            os.append(s[-1])
        return ox, oy, os

    def calculate2Radiance(self, compLength, speedMax):
        oMin = self.radiance(speedMax)
        imax = len(compLength)
        rR = []  #radiance at root
        rT = []  #radiance at tip
        i = 0
        if imax > 0:
            while i < imax:
                cLi = compLength[i]
                speedLow = speedMax * cLi
                if cLi >= 0:  # root is longer
                    rR.append(oMin)
                    rT.append(self.radiance(speedLow))
                else:
                    rT.append(oMin)
                    rR.append(self.radiance(-speedLow))
                i += 1
        return rR, rT

    def radiance(self, speed):
        a = (self.app.mRadSpHalf.get() - self.app.mRadSpHigh.get()) / (
            self.app.mSpeedHalf.get() - self.app.mSpeedHigh.get())
        return 0.5 * (
            (a *
             (speed - self.app.mSpeedHalf.get())) + self.app.mRadSpHalf.get()
        )  # use only 1/2 of radiance for the offset

    """ synchronise 2 profiles
    extrait le premier tronçon R et T
    pour chaque tronçon
        calcule la longueur R et T
        calcule la longueur cumulée R et T
        Ramène les longueurs cumulées dans un range 0 <> 1 pour R et T
        Crée une liste qui mélange les 2 (concatene, trie, élimine les doublons)
        Fait un interpolate de R et de T suivant cette liste
        Simplifie en enlevant les points trop rapprochés des 2 cotés
    """

    def synchrAllSections(self, rX, rY, rS, tX, tY, tS):
        #synchronise 2 profiles in order to get the same number of points
        #it has to respect synchronisation points
        sectionsIdxR = self.sectionsIdx(rS)
        sectionsIdxT = self.sectionsIdx(tS)
        #print("sectionIdxR", sectionsIdxR)
        #print("sectionIdxT", sectionsIdxT)
        imax = len(sectionsIdxR)
        i = 0
        syncRX = []
        syncRY = []
        syncTX = []
        syncTY = []

        if imax > 0:
            while i < imax:
                firstR = sectionsIdxR[i][0]
                lastR = sectionsIdxR[i][1] + 1
                firstT = sectionsIdxT[i][0]
                lastT = sectionsIdxT[i][1] + 1
                #print( "first fast", firstR, lastR , firstT, lastT)
                #print("rX" ,  rX[firstR:lastR] )
                sRX, sRY, sTX, sTY = self.synchroOneSection(
                    rX[firstR:lastR], rY[firstR:lastR], tX[firstT:lastT],
                    tY[firstT:lastT])
                syncRX = syncRX + sRX.tolist()
                syncRY = syncRY + sRY.tolist()
                syncTX = syncTX + sTX.tolist()
                syncTY = syncTY + sTY.tolist()
                i += 1
        return syncRX, syncRY, syncTX, syncTY

    def sectionsIdx(self, s):
        # return a list of turple with begin and end Idx of each section
        i = 0
        imax = len(s)
        result = []
        if imax > 1:
            while i < (imax - 1):
                j = i + 1
                while s[j] == 0:
                    j += 1
                result.append((i, j))
                i = j + 1
        return result

    def synchroOneSection(self, rX, rY, tX, tY):
        """pour chaque tronçon
        calcule la longueur cumulée R et T
        Ramène les longueurs cumulées dans un range 0 <> 1 pour R et T
        Crée une liste qui mélange les 2 (concatene, trie, élimine les doublons)
        Fait un interpolate de R et de T suivant cette liste
        Simplifie en enlevant les points trop rapprochés des 2 cotés
        """
        #print("synchro one section", rX , rY ,tX , tY)
        cumulLengthR = np.array(self.cumulLength(rX, rY))
        cumulLengthT = np.array(self.cumulLength(tX, tY))
        totLengthR = cumulLengthR[-1]
        totLengthT = cumulLengthT[-1]
        normLengthR = cumulLengthR / totLengthR
        normLengthT = cumulLengthT / totLengthT
        mergedLength = np.concatenate([normLengthR,
                                       normLengthT])  # concatenate
        mergedLength = np.unique(mergedLength)
        mergedLength = np.insert(mergedLength, 0, 0)
        #print("merged mergedLength=", mergedLength)

        mytck, myu = interpolate.splprep([rX, rY], k=1, s=0)
        rXnew, rYnew = interpolate.splev(mergedLength, mytck)
        mytck, myu = interpolate.splprep([tX, tY], k=1, s=0)
        tXnew, tYnew = interpolate.splev(mergedLength, mytck)
        #print("one section result" , rXnew , rYnew , tXnew , tYnew)
        return rXnew, rYnew, tXnew, tYnew

    def cumulLength(self, x, y):
        imax = len(x)
        i = 0
        cL = []
        cumLength = 0
        if imax > 1:
            while i < (imax - 1):
                dx = x[i + 1] - x[i]
                dy = y[i + 1] - y[i]
                cumLength += math.sqrt(dx * dx +
                                       dy * dy)  #calculate cumulative length
                cL.append(cumLength)
                i += 1
        return cL
Example #18
0
class View:
    def __init__(self, main_ui, show_ortho_track):
        self.main_ui = main_ui
        window = tk.Toplevel(self.main_ui.parent)
        self.window = window
        self.current_image = None
        self.rotation = 0

        canvas_frame = tk.Frame(window)
        canvas_frame.pack(side="left", fill=tk.BOTH, expand=1)

        self.toolbox = tk.Frame(canvas_frame)
        self.toolbox.pack(side="left", expand=False, fill=tk.BOTH)

        self.is_latlon_source = tk.BooleanVar(value=False)
        if show_ortho_track:
            self.latlons = self.load_latlons()
            if self.latlons:
                button = tk.Checkbutton(
                    self.toolbox,
                    text="Overhead focus",
                    var=self.is_latlon_source,
                    command=self.trackToggle,
                )
                button.pack(side="top")
        else:
            self.latlons = {}

        self.visible_tracks = None
        self.image_list = tk.StringVar()
        self.image_list_box = tk.Listbox(
            self.toolbox,
            font=FONT,
            width=12,
            selectmode="browse",
            listvariable=self.image_list,
        )
        self.image_list_box.pack(side="bottom", expand=True, fill=tk.Y)
        self.image_list_box.bind("<<ListboxSelect>>", self.onclick_image_list)

        self.figure = Figure()
        self.ax = self.figure.add_subplot(111)

        self.canvas = FigureCanvasTkAgg(self.figure, canvas_frame)
        self.canvas.get_tk_widget().pack(side="top", fill=tk.BOTH, expand=1)
        self.canvas.mpl_connect("button_press_event",
                                lambda event: self.onclick_image(event))
        self.canvas.mpl_connect("scroll_event",
                                lambda event: self.on_scroll(event))

        self.zoomed_in = False
        self.last_seen_px = {}
        self.plt_artists = []

    def load_latlons(self):
        """Loads a latlon associated with each image key"""
        return self.image_manager.load_latlons()

    def trackToggle(self):
        if self.is_latlon_source.get():
            self.main_ui.clear_latlon_sources(self)

    def onclick_image(self, event):
        x, y = event.xdata, event.ydata
        if None in (x, y) or self.current_image is None:
            return
        if event.button == 2:  # Middle / wheel click:
            if self.zoomed_in:
                self.zoom_out()
            else:
                self.zoom_in(x, y)
            self.figure.canvas.draw_idle()
        elif event.button in (1, 3):
            # Left click or right click
            self.last_seen_px[self.main_ui.curr_point] = x, y
            if self.visible_tracks:
                self.auto_gcp_create(x, y, event.button == 1)
            elif self.main_ui.curr_point is not None:
                self.add_move_or_remove_gcp(x, y, event.button == 1)
            self.main_ui.populate_gcp_list()
            self.update_image_list_text()
            self.display_points()
        else:
            return

    def on_scroll(self, event):
        if event.xdata is None or event.ydata is None:
            return
        if event.button == "up":
            self.go_to_next_image()
        elif event.button == "down":
            self.go_to_prev_image()

    def onclick_image_list(self, event):
        widget = event.widget
        sel = widget.curselection()
        if not sel:
            return
        self.go_to_image_index(int(sel[0]))

    def add_move_or_remove_gcp(self, x, y, add):
        if self.main_ui.curr_point is None:
            return
        reproj = self.main_ui.gcp_manager.gcp_reprojections.get(
            self.main_ui.curr_point)
        if reproj:
            reproj.pop(self.current_image, None)
        self.main_ui.gcp_manager.remove_point_observation(
            self.main_ui.curr_point, self.current_image)
        if add:
            self.main_ui.gcp_manager.add_point_observation(
                self.main_ui.curr_point,
                self.current_image,
                self.pixel_to_gcp_coordinates(x, y),
                latlon=self.pixel_to_latlon(x, y),
            )
            self.zoom_in(x, y)
        else:
            self.zoom_out()

    def zoom_in(self, x, y):
        if self.zoomed_in:
            return
        radius = self.zoom_window_size_px / 2
        self.ax.set_xlim(x - radius, x + radius)
        self.ax.set_ylim(y + radius, y - radius)
        self.zoomed_in = True

    def zoom_out(self):
        self.ax.autoscale()
        self.zoomed_in = False

    def zoom_logic(self):
        point_has_been_seen = self.main_ui.curr_point in self.last_seen_px
        if self.main_ui.sticky_zoom.get() and point_has_been_seen:
            # Zoom in to the last seen location of this GCP
            x, y = self.last_seen_px[self.main_ui.curr_point]
            self.zoom_in(x, y)
        else:
            # Show the whole image
            self.ax.axis("scaled")
            self.figure.set_tight_layout(True)
            self.ax.axis("off")

    def point_in_view(self, point):
        if point is None:
            return None
        for projection in self.main_ui.gcp_manager.points[point]:
            if projection["shot_id"] == self.current_image:
                return self.gcp_to_pixel_coordinates(*projection["projection"])
        return None

    def display_points(self):
        visible_points_coords = self.main_ui.gcp_manager.get_visible_points_coords(
            self.current_image)
        self.clear_artists()

        for point_id, coords in visible_points_coords.items():
            color = distinct_colors[divmod(hash(point_id), 19)[1]]
            x, y = self.gcp_to_pixel_coordinates(*coords)
            artists = [
                mpatches.Circle((x, y), 5, color=color, fill=False),
            ]

            if self.main_ui.show_gcp_names.get(
            ) or point_id == self.main_ui.curr_point:
                text = matplotlib.text.Annotation(
                    point_id,
                    (x, y),
                    xytext=[0, 7],
                    # fontsize=9,
                    textcoords="offset points",
                    ha="center",
                    va="bottom",
                    color=color,
                )
                text.set_path_effects([
                    patheffects.Stroke(linewidth=3,
                                       foreground=comp_color(color)),
                    patheffects.Normal(),
                ])
                artists.append(text)

            if point_id == self.main_ui.curr_point:
                artists.extend([
                    mpatches.Circle((x, y), 0.5, color=color, fill=True),
                    mpatches.Circle((x, y), 10, color=color, fill=False),
                    mpatches.Circle((x, y), 11, color=color, fill=False),
                    mpatches.Circle((x, y), 12, color=color, fill=False),
                ])
            for art in artists:
                self.plt_artists.append(art)
                self.ax.add_artist(art)

        self.figure.canvas.draw()

    def clear_artists(self):
        for artist in self.plt_artists:
            artist.set_visible(False)
            del artist

    def populate_image_list(self):
        self.update_image_list_text()
        self.update_image_list_highlight()

    def update_image_list_text(self):
        items = []
        self.images_in_list = self.get_candidate_images()
        n_digits = len(str(len(self.images_in_list)))
        for ix, image_name in enumerate(self.images_in_list):
            points = self.main_ui.gcp_manager.get_visible_points_coords(
                image_name)
            txt = "{:0{n_digits}} {}".format(ix + 1,
                                             len(points),
                                             n_digits=n_digits)
            shot_std = self.main_ui.shot_std.get(image_name, None)
            if shot_std:
                txt += " {:.2f}".format(shot_std)
            items.append(txt)
        self.image_list.set(items)

    def update_image_list_highlight(self):
        defaultbg = self.window.cget("bg")
        for ix, shot in enumerate(self.images_in_list):
            bg = "green" if shot == self.current_image else defaultbg
            self.image_list_box.itemconfig(ix, bg=bg)

    def bring_new_image(self, new_image, force=False):
        if new_image == self.current_image and not force:
            return
        self.current_image = new_image
        self.ax.clear()
        img = self.get_image(new_image)
        img = np.rot90(img, k=-self.rotation)
        self.ax.imshow(img)
        self.ax.axis("on")
        self.ax.axis("scaled")
        self.zoomed_in = False
        self.set_title()

        # Update 'last seen' coordinates for all gcps in this view
        for gcp_id in self.main_ui.gcp_manager.points:
            gcp_visible = self.point_in_view(gcp_id)
            if gcp_visible is not None:
                self.last_seen_px[gcp_id] = gcp_visible

        self.zoom_logic()

        self.update_image_list_highlight()

        self.display_points()

        if self.main_ui.curr_point:
            self.highlight_gcp_reprojection(self.main_ui.curr_point,
                                            zoom=False)

        latlon = self.latlons.get(new_image)
        if self.is_latlon_source.get() and latlon:
            self.main_ui.refocus_overhead_views(latlon["lat"], latlon["lon"])

    def highlight_gcp_reprojection(self, point_id, zoom=True):
        if point_id not in self.main_ui.gcp_manager.gcp_reprojections:
            return
        shot = self.current_image
        x, y = None, None
        for obs in self.main_ui.gcp_manager.points[point_id]:
            if obs["shot_id"] == shot:
                x, y = obs["projection"]
        if x is None:
            return

        reproj = self.main_ui.gcp_manager.gcp_reprojections[point_id].get(shot)
        if not reproj:
            return
        x2, y2 = reproj["reprojection"]
        x, y = self.gcp_to_pixel_coordinates(x, y)
        x2, y2 = self.gcp_to_pixel_coordinates(x2, y2)
        artists = self.ax.plot([x, x2], [y, y2], "r-")
        self.plt_artists.extend(artists)
        if zoom:
            self.zoom_in(x, y)
        self.canvas.draw_idle()

    def rotate_point(self, x, y, h, w, reverse):
        if self.rotation == 0:
            return (x, y)
        elif self.rotation == 1:
            return (y, h - x) if reverse else (h - y, x)
        elif self.rotation == 2:
            return (w - x, h - y)
        elif self.rotation == 3:
            return (w - y, x) if reverse else (y, w - x)
        else:
            raise ValueError

    def gcp_to_pixel_coordinates(self, x: float,
                                 y: float) -> Tuple[float, float]:
        """
        Transforms from normalized coordinates to pixels

        The view displays images at a reduced resolution for speed. We use the image
        manager to obtain the reduced coordinates to use for de-normalization.
        """
        h, w = self.image_manager.get_image_size(self.current_image)
        px = features.denormalized_image_coordinates(np.array([[x, y]]), w,
                                                     h)[0]
        return self.rotate_point(px[0], px[1], h, w, reverse=False)

    def pixel_to_gcp_coordinates(self, x: float,
                                 y: float) -> Tuple[float, float]:
        """
        Transforms from pixels to normalized coordinates

        The view displays images at a reduced resolution for speed. We use the image
        manager to obtain the reduced coordinates to use for normalization.
        """
        h, w = self.image_manager.get_image_size(self.current_image)
        point = self.rotate_point(x, y, h, w, reverse=True)
        coords = features.normalized_image_coordinates(np.array([point]), w,
                                                       h)[0]
        return coords.tolist()

    def go_to_next_image(self):
        self.go_to_adjacent_image(+1)

    def go_to_prev_image(self):
        self.go_to_adjacent_image(-1)

    def go_to_adjacent_image(self, offset):
        if not self.images_in_list:
            return
        target_ix = self.images_in_list.index(self.current_image) + offset
        if 0 <= target_ix < len(self.images_in_list):
            self.go_to_image_index(target_ix)

    def go_to_image_index(self, idx):
        self.bring_new_image(self.images_in_list[idx])
Example #19
0
class ViewWidget(object):

    """
        Draws images using the datasets recorded in the HDF5 file.  Also
        provides widgets to pick which dataset is displayed.
    """

    def __init__(self, f, master):

        self.f = f

        self.mainframe = tk.Frame(master=master)
        self.lbutton = tk.Button(self.mainframe, text="<= Back", command=self.back)
        self.rbutton = tk.Button(self.mainframe, text="Next =>", command=self.forward)
        self.loclabel = tk.Label(self.mainframe, text='To start, enter values and click "compute"')
        self.infolabel = tk.Label(self.mainframe, text='Or, click the "suggest" button for interesting locations')

        self.fig = Figure(figsize=(5, 5), dpi=100)
        self.plot = self.fig.add_subplot(111)
        self.canvas = FigureCanvasTkAgg(self.fig, master=self.mainframe)
        self.canvas.draw_idle()

        self.loclabel.grid(row=0, column=1)
        self.infolabel.grid(row=1, column=1)
        self.lbutton.grid(row=2, column=0)
        self.canvas.get_tk_widget().grid(row=2, column=1)
        self.rbutton.grid(row=2, column=2)

        self.index = 0

        self.jumptolast()

    def draw_fractal(self):
        """ Read a dataset from the HDF5 file and display it """

        with file_lock:
            name = list(self.f.keys())[self.index]
            dset = self.f[name]
            arr = dset[...]
            start = dset.attrs['start']
            extent = dset.attrs['extent']
            self.loclabel["text"] = 'Displaying dataset "%s" (%d of %d)' % (dset.name, self.index+1, len(self.f))
            self.infolabel["text"] = "%(shape)s pixels, starts at %(start)s, extent %(extent)s" % dset.attrs

        self.plot.clear()
        self.plot.imshow(arr.transpose(), cmap='jet', aspect='auto', origin='lower',
                         extent=(start.real, (start.real+extent.real),
                                 start.imag, (start.imag+extent.imag)))
        self.canvas.draw_idle()

    def back(self):
        """ Go to the previous dataset (in ASCII order) """
        if self.index == 0:
            print("Can't go back")
            return
        self.index -= 1
        self.draw_fractal()

    def forward(self):
        """ Go to the next dataset (in ASCII order) """
        if self.index == (len(self.f)-1):
            print("Can't go forward")
            return
        self.index += 1
        self.draw_fractal()

    def jumptolast(self,*args):
        """ Jump to the last (ASCII order) dataset and display it """
        with file_lock:
            if len(self.f) == 0:
                print("can't jump to last (no datasets)")
                return
            index = len(self.f)-1
        self.index = index
        self.draw_fractal()
Example #20
0
class Tool_GUI():

    def __init__(self, root):
        # Definition for audio devices
        self.input_devices_list = []
        self.output_devices_list = []
        self.input_device_index = None
        self.output_device_index = None
        self.find_device()

        # Main Dialog Definition
        main_dialog = root
        main_dialog.title("Tool for ASR")
        main_dialog.geometry("900x650")
        main_dialog.resizable(False, False)
        self.window = tk.Frame(master=main_dialog, relief="solid", bd=2, height=630, width=880)
        self.window.place(x=10, y=10)

        # Font definition
        bc10i = tkFont.Font(family="bitstream charter", size=10, slant="italic")
        bc10b = tkFont.Font(family="bitstream charter", size=10, weight="bold")
        bc12b = tkFont.Font(family="bitstream charter", size=12, weight="bold")
        bc12i = tkFont.Font(family="bitstream charter", size=12, slant="italic")

        # Definition for File info Frame
        file_info_frame = tk.Frame(master=self.window, relief="solid", bd=1, height=100, width=500)
        file_info_frame.place(x=10, y=10)

        # Definition for Source directory
        lbl_src = tk.Label(master=file_info_frame, text="Source", fg="coral4", font=bc12b, anchor="w")
        lbl_src.place(x=10, y=15)
        self.btn_src_path_var = tk.StringVar()
        self.btn_src_path_var.set("Source directory")
        self.btn_src_path = tk.Button(master=file_info_frame, textvariable=self.btn_src_path_var, font=bc12i, fg="gray",
                                      width=40, bg='white', anchor="w", command=lambda: self.select_src_folder())
        self.btn_src_path.place(x=115, y=10)

        # Definition for Destination directory
        lbl_dst = tk.Label(master=file_info_frame, text="Destination", fg="coral4", font=bc12b, anchor="w")
        lbl_dst.place(x=10, y=60)
        self.btn_dst_path_var = tk.StringVar()
        self.btn_dst_path_var.set("Destination directory")
        self.btn_dst_path = tk.Button(master=file_info_frame, textvariable=self.btn_dst_path_var, font=bc12i, fg="gray",
                                      width=40, bg='white', anchor="w", command=lambda: self.select_dst_folder())
        self.btn_dst_path.place(x=115, y=55)

        # Definition for device settings frame
        dev_info_frame = tk.Frame(master=self.window, relief="solid", bd=1, height=190, width=345)
        dev_info_frame.place(x=520, y=10)

        # Combobox Definition for Sample Rate
        lbl_sample_rate = tk.Label(master=dev_info_frame, text="Sampling", fg="coral4", font=bc12b, anchor="w")
        lbl_sample_rate.place(x=10, y=15)
        self.cmb_sample_rate_var = tk.StringVar()
        self.cmb_sample_rate = ttk.Combobox(master=dev_info_frame, textvariable=self.cmb_sample_rate_var,
                                            state="readonly", values=[8000, 16000, 44100, 48000])
        self.cmb_sample_rate.config(height=1, width=10, font=bc10i)
        self.cmb_sample_rate.place(x=100, y=18)
        self.cmb_sample_rate.current(1)
        print("default sample rate = ", self.cmb_sample_rate.get())

        # Combobox Definition for Channel number
        lbl_channel = tk.Label(master=dev_info_frame, text="Channel", fg="coral4", font=bc12b, anchor="w")
        lbl_channel.place(x=10, y=60)
        self.cmb_channel_var = tk.StringVar()
        self.cmb_channel = ttk.Combobox(master=dev_info_frame, textvariable=self.cmb_channel_var, state="readonly",
                                        values=[1, 2])
        self.cmb_channel.config(height=1, width=10, font=bc10i)
        self.cmb_channel.place(x=100, y=63)
        self.cmb_channel.current(0)
        print("default channel numbers = ", self.cmb_channel.get())

        # Combobox Definition for Output device
        lbl_out_dev = tk.Label(master=dev_info_frame, text="Output", fg="coral4", font=bc12b, anchor="w")
        lbl_out_dev.place(x=10, y=105)
        # self.cmb_out_dev_var = tk.StringVar()
        self.cmb_out_dev = ttk.Combobox(master=dev_info_frame, state="readonly", values=[],
                                        postcommand=self.cmb_out_dev_update)
        self.cmb_out_dev.config(height=1, width=28, font=bc10i)
        self.cmb_out_dev.place(x=100, y=108)
        self.cmb_out_dev_update()
        self.cmb_out_dev_init()
        print("default output device = ", self.cmb_out_dev.get())

        # Combobox Definition for Input device
        lbl_in_dev = tk.Label(master=dev_info_frame, text="Input", fg="coral4", font=bc12b, anchor="w")
        lbl_in_dev.place(x=10, y=150)
        self.cmb_in_dev_var = tk.StringVar()
        self.cmb_in_dev = ttk.Combobox(master=dev_info_frame, textvariable=self.cmb_in_dev_var,
                                       state="readonly", values=[], postcommand=self.cmb_in_dev_update)
        self.cmb_in_dev.config(height=1, width=28, font=bc10i)
        self.cmb_in_dev.place(x=100, y=153)
        self.cmb_in_dev_update()
        self.cmb_in_dev_init()
        print("default input device = ", self.cmb_in_dev.get())

        # Definition for Progress Info Frame
        prog_info_frame = tk.Frame(master=self.window, relief="solid", bd=1, height=80, width=500)
        prog_info_frame.place(x=10, y=120)

        # Definition for Current working file entry
        lbl_curr = tk.Label(master=prog_info_frame, text="Current file", fg="coral4", font=bc12b, anchor="w")
        lbl_curr.place(x=10, y=15)
        self.ent_curr_file_var = tk.StringVar()
        self.ent_curr_file_var.set("Working file...")
        ent_curr_file = tk.Entry(master=prog_info_frame, textvariable=self.ent_curr_file_var, font=bc12i, fg="gray",
                                 width=30, bg="white")
        ent_curr_file.place(x=115, y=15)

        # Definition for Progress information
        lbl_prog = tk.Label(master=prog_info_frame, text="Progress", fg="coral4", font=bc12b, anchor="w")
        lbl_prog.place(x=10, y=45)
        self.prog_bar = ttk.Progressbar(master=prog_info_frame, orient=HORIZONTAL, length=370, mode="determinate")
        self.prog_bar.place(x=115, y=47)
        self.update_prog_bar(0)

        # Definition for Reference Waveform Frame
        self.frm_src_wave = tk.Canvas(master=self.window, relief="solid", bd=2, height=150, width=855, bg="white")
        self.frm_src_wave.place(x=10, y=210)
        lbl_ref = tk.Label(master=self.frm_src_wave, text="Reference", fg="gray", font=bc12i, anchor="w", bg="white")
        lbl_ref.place(x=10, y=10)

        # Draw blank wave box for source
        self.fig_src = Figure(figsize=(8.45, 1.43), dpi=100)
        self.fig_src.subplots_adjust(bottom=0.18, left=0.1)
        self.a1 = self.fig_src.add_subplot(111)
        self.a1.set_ylim([-32768, 32767])
        self.a1.set_yticklabels([])
        self.a1.set_xticklabels([])
        self.a1.plot([])
        self.canvas_src = FigureCanvasTkAgg(self.fig_src, master=self.frm_src_wave)
        self.canvas_src.get_tk_widget().place(x=10, y=10)
        self.canvas_src.draw_idle()

        # Definition for Recorded Waveform Frame
        self.frm_rec_wave = tk.Canvas(master=self.window, relief="solid", bd=2, height=150, width=855, bg="white")
        self.frm_rec_wave.place(x=10, y=370)
        lbl_rec = tk.Label(master=self.frm_rec_wave, text="Recorded", fg="gray", font=bc12i, anchor="w", bg="white")
        lbl_rec.place(x=10, y=10)

        # Draw blank wave box for recorded
        self.fig_rec = Figure(figsize=(8.45, 1.43), dpi=100)
        self.fig_rec.subplots_adjust(bottom=0.18, left=0.1)
        self.a2 = self.fig_rec.add_subplot(111)
        self.a2.set_ylim([-32768, 32767])
        self.a2.set_yticklabels([])
        self.a2.set_xticklabels([])
        self.a2.plot([])
        self.canvas_rec = FigureCanvasTkAgg(self.fig_rec, master=self.frm_rec_wave)
        self.canvas_rec.get_tk_widget().place(x=10, y=10)
        self.canvas_rec.draw_idle()

        # Definition for option checkbox
        frm_conv = tk.Frame(master=self.window, relief='solid', bd=1, height=70, width=400)
        frm_conv.place(x=10, y=540)

        self.play_checkVar = tk.IntVar()
        play_check = tk.Checkbutton(master=frm_conv, text="play & record", variable=self.play_checkVar, font=bc12i,
                                    command=lambda: self.play_check_chk())
        play_check.place(x=15, y=20)
        self.play_checkVar.set(1)

        self.flac_checkVar = tk.IntVar()
        flac_check = tk.Checkbutton(master=frm_conv, text="flac to wav", variable=self.flac_checkVar, font=bc12i,
                                    command=lambda: self.flac_check_chk())
        flac_check.place(x=150, y=20)

        self.mp3_checkVar = tk.IntVar()
        mp3_check = tk.Checkbutton(master=frm_conv, text="mp3 to wav", variable=self.mp3_checkVar, font=bc12i,
                                   command=lambda: self.mp3_check_chk())
        mp3_check.place(x=270, y=20)

        # Definition for MOS score
        frm_mos = tk.Frame(master=self.window, relief='solid', bd=1, height=70, width=130)
        frm_mos.place(x=430, y=540)
        lbl_mos = tk.Label(master=frm_mos, text='MOS', fg='gray', font=bc12b)
        lbl_mos.place(x=10, y=23)
        self.ent_mos_var = tk.StringVar()
        self.ent_mos_var.set("0.00")
        self.ent_mos = tk.Label(master=frm_mos, textvariable=self.ent_mos_var, font=bc12i, fg='black', anchor="e",
                                width=5, height=2)
        self.ent_mos.place(x=60, y=15)

        # Definition for Buttons
        self.img_start = PhotoImage(file="resources\\start.png").subsample(10, 10)
        self.img_pause = PhotoImage(file="resources\\pause.png").subsample(10, 10)
        self.img_stop = PhotoImage(file="resources\\stop.png").subsample(10, 10)

        self.tool_started = tk.IntVar()
        self.tool_started.set(STOPPED)
        self.btn_start = tk.Button(master=self.window, image=self.img_start, font=bc12b,
                                   command=lambda: self.tool_start(), borderwidth=0)
        self.btn_start.place(x=700, y=538)

        self.btn_stop = tk.Button(master=self.window, image=self.img_stop, font=bc12b,
                                  command=lambda: self.tool_stop(), borderwidth=0)
        self.btn_stop.place(x=785, y=538)
        self.btn_stop["state"] = "disabled"

    def find_device(self):
        audio = pyaudio.PyAudio()
        device_num = audio.get_device_count()

        info = audio.get_host_api_info_by_index(0)
        numdevices = info.get('deviceCount')
        indev = {}
        outdev = {}
        self.input_devices_list.clear()
        self.output_devices_list.clear()
        for i in range(numdevices):
            # print("Input Device id", i, "-", audio.get_device_info_by_host_api_device_index(0, i))
            if audio.get_device_info_by_host_api_device_index(0, i)['maxInputChannels'] > 0:
                indev['name'] = audio.get_device_info_by_host_api_device_index(0, i)['name']
                indev['index'] = audio.get_device_info_by_host_api_device_index(0, i)['index']
                self.input_devices_list.append(indev)
                indev = {}
            if audio.get_device_info_by_host_api_device_index(0, i)['maxOutputChannels'] > 0:
                outdev["name"] = audio.get_device_info_by_host_api_device_index(0, i)['name']
                outdev['index'] = audio.get_device_info_by_host_api_device_index(0, i)['index']
                self.output_devices_list.append(outdev)
                outdev = {}

        for i in range(len(self.input_devices_list)):
            if audio.get_default_input_device_info()['name'] == self.input_devices_list[i]['name']:
                self.input_device_index = i

        for i in range(len(self.output_devices_list)):
            if audio.get_default_output_device_info()['name'] == self.output_devices_list[i]['name']:
                self.output_device_index = i
        audio.terminate()

    # update input devices Combobox
    def cmb_in_dev_update(self):
        self.find_device()
        self.cmb_in_dev["values"] = []
        lst = []
        for i in range(len(self.input_devices_list)):
            lst.append(self.input_devices_list[i]['name'])
        self.cmb_in_dev["values"] = lst

    # set Default input device
    def cmb_in_dev_init(self):
        self.cmb_in_dev.current(self.input_device_index)

    # update output devices Combobox
    def cmb_out_dev_update(self):
        self.find_device()
        self.cmb_out_dev["values"] = []
        lst = []
        for i in range(len(self.output_devices_list)):
            lst.append(self.output_devices_list[i]['name'])
        self.cmb_out_dev["values"] = lst

    # set Default output device
    def cmb_out_dev_init(self):
        self.cmb_out_dev.current(self.output_device_index)

    def cmb_out_dev_index_get(self):
        self.output_device_index = self.output_devices_list[self.cmb_out_dev.current()]['index']
        # print("output_device_index = ", self.output_device_index)

    def cmb_in_dev_index_get(self):
        self.input_device_index = self.input_devices_list[self.cmb_in_dev.current()]['index']
        # print("input_device_index = ", self.input_device_index)

    # Update Progress information
    def update_prog_bar(self, percent):
        self.prog_bar["value"] = int(370 * percent / 370)

    def thread_play_and_record(self):
        self.cmb_out_dev_index_get()
        self.cmb_in_dev_index_get()

        # copy files from source directories to destination directories
        dirs_list = []
        files_list = []
        for (root, dirs, files) in os.walk(self.btn_src_path_var.get(), topdown=True):
            dirs_list.append(root)
            # print("root =", root)
            # print(dirs)
            # # print(files)
            if files:
                for file in files:
                    if file.endswith(".wav"):
                        files_list.append(os.path.join(root, file))

        print("total files = ", len(files_list))

        total_number = len(files_list)

        # new destination directories list
        new_dirs_list = []
        for i in range(len(dirs_list)):
            new_dir = self.btn_dst_path_var.get() + "\\" + dirs_list[i][len(dirs_list[0]):]
            new_dirs_list.append(os.path.abspath(new_dir))
            # print(new_dirs_list[i])
        new_files_list = []
        for i in range(len(files_list)):
            new_file = self.btn_dst_path_var.get() + "\\" + files_list[i][len(dirs_list[0]):]
            # new_file_wav = new_file.replace(".flac", ".wav")
            new_files_list.append(os.path.abspath(new_file))

        # make destination directories
        for i in range(1, len(new_dirs_list)):
            print(new_dirs_list[i])
            try:
                os.mkdir(new_dirs_list[i])
            except FileExistsError:
                print(new_dirs_list[i], " exists.")

        for i in range(len(files_list)):
            # flac2wav(files_list[i], new_files_list[i])
            # print(files_list[i])
            # print(new_files_list[i])
            self.ent_curr_file_var.set(os.path.basename(new_files_list[i]))
            self.update_prog_bar(int(i / total_number * 100))
            # shutil.copy(files_list[i], new_files_list[i])

            if self.tool_started.get() == STOPPED:
                print(self.tool_started.get())
                break

            play_and_record(int(self.cmb_sample_rate.get()), int(self.cmb_channel.get()), self.input_device_index,
                            self.output_device_index, files_list[i], new_files_list[i])
            self.draw_src_wave(files_list[i])

            self.draw_rec_wave(new_files_list[i])
            mos = pesq_assess.evaluate(files_list[i], new_files_list[i], 16000, 'wb')
            
            self.ent_mos_var.set(f'{mos:.2f}')
            self.update_prog_bar((int(i+1)/total_number * 100))

        self.tool_stop()
        print("thread end")
        messagebox.showwarning("Information", "Play and Record finished.")


    def thread_pause_play_and_record(self):
        pass

    def thread_stop_play_and_record(self):
        pass

    def tool_start(self):
        print("src=", self.btn_src_path_var.get())
        print("dst=", self.btn_dst_path_var.get())
        if not(os.path.isdir(self.btn_src_path_var.get())) or not(os.path.isdir(self.btn_dst_path_var.get())):
            messagebox.showwarning("Warning", "To check Source or Destination directories.")
            return
        if self.tool_started.get() == STOPPED:
            self.tool_started.set(STARTED)
            self.btn_start.config(image=self.img_pause)
            self.btn_stop["state"] = "normal"
            self.dialog_selectable(False)

            if self.flac_checkVar.get():
                tool = threading.Thread(target=self.thread_flac_to_wav, )
                tool.start()
            elif self.mp3_checkVar.get():
                tool = threading.Thread(target=self.thread_mp3_to_wav, )
                tool.start()
            else:
                tool = threading.Thread(target=self.thread_play_and_record, )
                tool.start()
        elif self.tool_started.get() == STARTED:
            self.tool_started.set(PAUSED)
            self.btn_start.config(image=self.img_start)
            self.btn_stop["state"] = "normal"
            self.dialog_selectable(False)
        elif self.tool_started.get() == PAUSED:
            self.tool_started.set(STARTED)
            self.btn_start.config(image=self.img_pause)
            self.btn_stop["state"] = "normal"
            self.dialog_selectable(False)
        print("start thread started")

    def tool_stop(self):
        if self.tool_started.get() == STARTED:
            self.tool_started.set(STOPPED)
            self.btn_start.config(image=self.img_start)
            self.btn_stop.config(relief="flat")
            self.btn_stop["state"] = "disabled"
            self.dialog_selectable(True)
        elif self.tool_started.get() == PAUSED:
            self.tool_started.set(STOPPED)
            self.btn_start.config(image=self.img_start)
            self.btn_stop["state"] = "disabled"
            self.dialog_selectable(False)

    def dialog_selectable(self, enable):
        if not enable:
            self.btn_src_path["state"] = "disabled"
            self.btn_dst_path["state"] = "disabled"
            self.cmb_sample_rate["state"] = "disabled"
            self.cmb_channel["state"] = "disabled"
            self.cmb_out_dev["state"] = "disabled"
            self.cmb_in_dev["state"] = "disabled"
        else:
            self.btn_src_path["state"] = "normal"
            self.btn_dst_path["state"] = "normal"
            self.cmb_sample_rate["state"] = "normal"
            self.cmb_channel["state"] = "normal"
            self.cmb_out_dev["state"] = "normal"
            self.cmb_in_dev["state"] = "normal"

    def select_src_folder(self):
        new_folder = filedialog.askdirectory(initialdir=str(Path.home()), title="Select a Source directory")
        try:
            if new_folder != "":
                if os.path.isdir(new_folder):
                    self.btn_src_path_var.set(os.path.abspath(new_folder))
                else:
                    messagebox.showwarning("Warning", "The selected location is not a directory")
        except:
            messagebox.showwarning("Warning", "Warning: There is a problem with the Directory !")

    def select_dst_folder(self):
        new_dst_folder = filedialog.askdirectory(initialdir=str(Path.home()), title="Select a Destination directory")
        try:
            if new_dst_folder != "":
                if os.path.isdir(new_dst_folder):
                    self.btn_dst_path_var.set(os.path.abspath(new_dst_folder))
                else:
                    messagebox.showwarning("Warning", "The selected location is not a directory")
        except:
            messagebox.showwarning("Warning", "Warning: There is a problem with the Directory !")

    def draw_src_wave(self, src_file):
        spf = wave.open(src_file, "rb")
        signal = spf.readframes(-1)
        spf.close()
        signal = np.frombuffer(signal, "int16")
        print("source samples = ", len(signal))
        fs = spf.getframerate()
        Time = np.linspace(0, len(signal) / fs, num=len(signal))
        self.a1.clear()
        self.a1.set_ylim([-32768, 32767])
        self.a1.set_xlim([0, len(signal) / fs])
        self.a1.set_yticklabels([])
        self.a1.plot(Time, signal)
        self.canvas_src.draw_idle()

    def draw_rec_wave(self, rec_file):
        spf = wave.open(rec_file, "rb")
        rec_signal = spf.readframes(-1)
        spf.close()
        rec_signal = np.frombuffer(rec_signal, "int16")
        print("recorded samples = ", len(rec_signal))
        fs = spf.getframerate()
        Time = np.linspace(0, len(rec_signal) / fs, num=len(rec_signal))
        self.a2.clear()
        self.a2.set_ylim([-32768, 32767])
        self.a2.set_xlim([0, len(rec_signal) / fs])
        self.a2.set_yticklabels([])
        self.a2.plot(Time, rec_signal)
        self.canvas_rec.draw_idle()

    def play_check_chk(self):
        if self.play_checkVar.get():
            self.mp3_checkVar.set(0)
            self.flac_checkVar.set(0)

    def flac_check_chk(self):
        if self.flac_checkVar.get():
            self.play_checkVar.set(0)
            self.mp3_checkVar.set(0)

    def mp3_check_chk(self):
        if self.mp3_checkVar.get():
            self.play_checkVar.set(0)
            self.flac_checkVar.set(0)

    def thread_flac_to_wav(self):
        # conv_thread = threading.Thread(target=self.flac_to_wav, )
        # conv_thread.start()
        self.flac_to_wav()
        self.tool_stop()
        print("flac to wav thread end.")
        messagebox.showwarning("Information", "File conversion from flac to wav finished.")

    def flac_to_wav(self):
        # copy files from source directories to destination directories
        dirs_list = []
        files_list = []
        for (root, dirs, files) in os.walk(self.btn_src_path_var.get(), topdown=True):
            dirs_list.append(root)
            # print("root =", root)
            # print(dirs)
            # # print(files)
            if files:
                for file in files:
                    if file.endswith(".flac"):
                        files_list.append(os.path.join(root, file))

        print("total files = ", len(files_list))

        total_number = len(files_list)

        # new destination directories list
        new_dirs_list = []
        for i in range(len(dirs_list)):
            new_dir = self.btn_dst_path_var.get() + "\\" + dirs_list[i][len(dirs_list[0]):]
            new_dirs_list.append(os.path.abspath(new_dir))
            # print(new_dirs_list[i])
        new_files_list = []
        for i in range(len(files_list)):
            new_file = self.btn_dst_path_var.get() + "\\" + files_list[i][len(dirs_list[0]):]
            new_file_wav = new_file.replace(".flac", ".wav")
            new_files_list.append(os.path.abspath(new_file_wav))

        # make destination directories
        for i in range(1, len(new_dirs_list)):
            print(new_dirs_list[i])
            try:
                os.mkdir(new_dirs_list[i])
            except FileExistsError:
                print(new_dirs_list[i], " exists.")

        for i in range(len(files_list)):
            if self.tool_started.get() == STOPPED:
                break
            flac2wav(files_list[i], new_files_list[i])
            print(files_list[i])
            print(new_files_list[i])
            self.ent_curr_file_var.set(os.path.basename(new_files_list[i]))
            self.update_prog_bar(int((i+1) / total_number * 100))
            # shutil.copy(files_list[i], new_files_list[i])

    def thread_mp3_to_wav(self):
        # conv_thread = threading.Thread(target=self.flac_to_wav, )
        # conv_thread.start()
        self.mp3_to_wav()
        self.tool_stop()
        print("flac to wav thread end.")
        messagebox.showwarning("Information", "File conversion from mp3 to wav finished.")

    def mp3_to_wav(self):
        # copy files from source directories to destination directories
        dirs_list = []
        files_list = []
        for (root, dirs, files) in os.walk(self.btn_src_path_var.get(), topdown=True):
            dirs_list.append(root)
            # print("root =", root)
            # print(dirs)
            # # print(files)
            if files:
                for file in files:
                    if file.endswith(".mp3"):
                        files_list.append(os.path.join(root, file))

        print("total files = ", len(files_list))

        total_number = len(files_list)

        # new destination directories list
        new_dirs_list = []
        for i in range(len(dirs_list)):
            new_dir = self.btn_dst_path_var.get() + "\\" + dirs_list[i][len(dirs_list[0]):]
            new_dirs_list.append(os.path.abspath(new_dir))
            # print(new_dirs_list[i])
        new_files_list = []
        for i in range(len(files_list)):
            new_file = self.btn_dst_path_var.get() + "\\" + files_list[i][len(dirs_list[0]):]
            new_file_wav = new_file.replace(".mp3", ".wav")
            new_files_list.append(os.path.abspath(new_file_wav))

        # make destination directories
        for i in range(1, len(new_dirs_list)):
            print(new_dirs_list[i])
            try:
                os.mkdir(new_dirs_list[i])
            except FileExistsError:
                print(new_dirs_list[i], " exists.")

        for i in range(len(files_list)):
            if self.tool_started.get() == STOPPED:
                break
            mp3towav(files_list[i], new_files_list[i])
            print(files_list[i])
            print(new_files_list[i])
            self.ent_curr_file_var.set(os.path.basename(new_files_list[i]))
            self.update_prog_bar((int(i+1) / total_number * 100))
Example #21
0
class ValuesFrame(tk.Frame):
    MIN_VALUE = 0
    MAX_VALUE = 105

    def __init__(self, title, *args, **kwargs):
        self._title = title

        tk.Frame.__init__(self, *args, **kwargs)

        fig, self._ax = plt.subplots()
        self._ax.xaxis.set_tick_params(rotation=15, labelsize=8)
        self._ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M:%S'))
        self._ax.xaxis.set_major_locator(
            mdates.SecondLocator(bysecond=[0, 15, 30, 45]))
        self._ax.xaxis.set_minor_locator(
            mdates.SecondLocator(
                bysecond=[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55]))
        self._ax.grid(True)

        self._canvas = FigureCanvasTkAgg(fig, self)
        self._canvas.get_tk_widget().pack(side=tk.TOP,
                                          fill=tk.BOTH,
                                          expand=True)

        self.last_line = None
        self.poly = None
        self.update_timeline()

    def invalidate_viewport(self):
        t2 = datetime.today()
        t1 = t2 - timedelta(seconds=65)
        self._ax.set_xlim([t1, t2])
        self._ax.set_ylim([self.MIN_VALUE, self.MAX_VALUE])
        self._canvas.draw_idle()

    def update_timeline(self):
        now = datetime.today()
        '''extend last_line to the current time'''
        if self.last_line:
            xd = self.last_line.get_xdata()
            xd[-1] = now
            self.last_line.set_xdata(xd)
        '''extend the poly to the current time'''
        if self.poly:
            self.poly.xy[-3][0] = mdates.date2num(now)
            self.poly.xy[-2][0] = mdates.date2num(now)

        self.invalidate_viewport()
        self.after(1000, self.update_timeline)

    def draw_data(self, data):
        '''
        update frame with data
        where data elems are points [(datetime,value),]
        '''
        ''''convert input data to xy arrays'''
        tx = []
        tv = []
        last_v = None
        for x, v, *_ in data:
            if last_v != None:
                tx.append(x)
                tv.append(last_v)
            tx.append(x)
            tv.append(v)
            last_v = v
        '''append last point for the current time'''
        if tx and tv:
            tx.append(datetime.today())
            tv.append(last_v)
        '''clear old plots and patches'''
        self._ax.clear()
        self._ax.grid(True)
        [p.remove() for p in reversed(self._ax.patches)]

        if tx and tv:
            '''plot main lines'''
            *_, self.last_line = self._ax.plot_date(tx,
                                                    tv,
                                                    'r-',
                                                    xdate=True,
                                                    lw=3)
            '''draw transparent polygon area'''
            verts = [(mdates.date2num(tx[0]), 0),
                     *zip(map(mdates.date2num, tx), tv),
                     (mdates.date2num(tx[-1]), 0)]
            self.poly = Polygon(verts, alpha=0.2, facecolor='r', edgecolor='r')
            self._ax.add_patch(self.poly)
            self._ax.set_title(self._title)
        else:
            self._ax.set_title('No data for ' + self._title)
        '''update viewport'''
        self.invalidate_viewport()
Example #22
0
class NetworkPlotTk(KWallNetworkPlotBase):
    """
    This class implements UIs using Tkinter. 
    
    The content of this class is independent of the parent class.
    It only depends on the grandparent class, which should be
    'NetworkPlotBase'. Therefore this class can inherit any class
    whose parent is 'NetworkPlotBase'; just change the name of the
    parent in the definition of this class.
    """
    def __init__(self, 
        master=None,
        title=None,
    ):
        super(NetworkPlotTk, self).__init__(
            matplotlib_figure=matplotlib.figure.Figure(),
        )

        if master is None:
            master = tk.Tk()
            master.withdraw()
        self.master = master
        #self.master.protocol("WM_DELETE_WINDOW", self.on_closing)

        # Create a Toplevel widget, which is a child of GUILoom 
        # and contains plots,
        self.toplevel = tk.Toplevel(master)
        self.toplevel.wm_title(title)
        self.toplevel.protocol("WM_DELETE_WINDOW", self.on_closing)

        self.plot_idx_scale = None

        self.plot_idx_entry = None
        self.plot_idx_entry_var = tk.StringVar() 
        self.plot_idx_entry_var.trace('w', self.plot_idx_entry_change)

        self.canvas = FigureCanvas(
            self.figure,
            master=self.toplevel,
            resize_callback=self.canvas_resize_callback
        )
        self.canvas.show()
        self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)

        toolbar = NavigationToolbar(self.canvas, self.toplevel)
        toolbar.update()
        self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
   


    def on_closing(self):
        self.toplevel.destroy()
        self.master.destroy()


    def scale_action(self, scale_value):
        new_plot_idx = int(scale_value)
        self.update_current_plot(new_plot_idx)
        self.plot_idx_entry_var.set(new_plot_idx)


    def plot_idx_entry_change(self, *args):
        try:
            new_plot_idx = int(self.plot_idx_entry_var.get())

            if new_plot_idx == self.current_plot_idx:
                return None
            elif new_plot_idx < 0:
                new_plot_idx = 0
            elif new_plot_idx > len(self.plots) - 1:
                new_plot_idx = len(self.plots) - 1

            self.plot_idx_scale.set(new_plot_idx)
            self.update_current_plot(new_plot_idx)

        except ValueError:
            pass

        return None

    def update_current_plot(self, new_plot_idx):
        if self.data_cursor is not None:
            self.data_cursor.hide().disable()

        self.plots[self.current_plot_idx].set_visible(False)
        self.plots[new_plot_idx].set_visible(True)
        # Update the index variable for the currently displayed plot.
        self.current_plot_idx = new_plot_idx
        self.set_data_cursor()
        self.canvas.draw_idle()
        self.canvas.get_tk_widget().focus_set()

        return None


    def canvas_resize_callback(self, event):
        self.set_data_cursor()


    def show(self):
        plot_idx = 0
        self.current_plot_idx = plot_idx
        self.plots[plot_idx].set_visible(True)
        self.set_data_cursor()

        if(len(self.plots) > 1):
            tk.Label(
                self.toplevel,
                text='Plot #',
            ).pack(side=tk.LEFT)

            self.plot_idx_entry_var.set(plot_idx)
            self.plot_idx_entry = tk.Entry(
                self.toplevel,
                textvariable=self.plot_idx_entry_var,
                width=len(str(len(self.plots)-1)),
            )
            self.plot_idx_entry.pack(side=tk.LEFT)

            tk.Label(
                self.toplevel,
                text='/{}'.format(len(self.plots)-1),
            ).pack(side=tk.LEFT)

            self.plot_idx_scale = tk.Scale(
                self.toplevel,
                command=self.scale_action,
                #length=100*len(self.plots),
                orient=tk.HORIZONTAL,
                #showvalue=1,
                showvalue=0,
                to=len(self.plots)-1,
                variable=self.current_plot_idx,
            ) 
            self.plot_idx_scale.pack(
                expand=True,
                fill=tk.X,
                side=tk.LEFT,
            )
Example #23
0
class AllTransactions:
    def __init__(self, root, main):
        self.main = main
        self.root = root
        self.set_styles()
        matplotlib.rcParams.update({
            "font.family": self.main.font,
            "font.size": 10,
            "text.color": "white"
        })
        self.tFrame = Frame(self.root, bg=self.main.colors[0])
        self.topFrame = Frame(self.tFrame, bg=self.main.colors[0], height=1000)
        Label(self.topFrame,
              text="All Transactions",
              fg=self.main.colors[4],
              bg=self.main.colors[0],
              font=(self.main.font, 24),
              padx=15,
              pady=10).pack(side=LEFT)
        self.backbtn = Button(self.topFrame,
                              text="Back",
                              font=(self.main.font, 12, "bold"),
                              bd=0,
                              highlightthickness=0,
                              padx=10,
                              pady=10,
                              bg=self.main.colors[1],
                              fg=self.main.colors[0],
                              command=self.showDashboard)
        self.backbtn.pack(side=RIGHT, padx=10)
        self.topFrame.pack(side=TOP, fill=X)

        self.bottomFrame = Frame(self.tFrame,
                                 bg=self.main.colors[0],
                                 padx=15,
                                 pady=10)

        self.treeV = ttk.Treeview(self.bottomFrame)
        self.treeV['columns'] = ("Amount", "Type", "Category", "Date",
                                 "Client", "Contact")
        self.treeV.column("#0", width=0, stretch=NO)
        self.treeV.column("Amount", anchor=W, width=150)
        self.treeV.column("Type", anchor=W, width=40)
        self.treeV.column("Category", anchor=W, width=130)
        self.treeV.column("Date", anchor=W, width=60)
        self.treeV.column("Client", anchor=W)
        self.treeV.column("Contact", anchor=W, width=50)
        self.treeV.heading("Amount", text="Amount", anchor=W)
        self.treeV.heading("Type", text="Type", anchor=W)
        self.treeV.heading("Category", text="Wallet", anchor=W)
        self.treeV.heading("Date", text="Date", anchor=W)
        self.treeV.heading("Client", text="Client", anchor=W)
        self.treeV.heading("Contact", text="Contact", anchor=W)
        self.treeV.pack(fill=BOTH, expand=1, side=TOP)
        self.line = Frame(self.bottomFrame,
                          bg=self.main.colors[4],
                          pady=3,
                          padx=3).pack(side=TOP, pady=5, fill=X)
        self.ef = Frame(self.bottomFrame, bg=self.main.colors[0])
        self.fig = Figure(figsize=(7, 5), dpi=100)
        self.fig.set_facecolor(self.main.colors[0])
        self.ax = self.fig.add_subplot(111)
        self.chartcanv = FigureCanvasTkAgg(self.fig, self.ef)
        self.canv = self.chartcanv.get_tk_widget()
        self.canv.pack(side=LEFT, expand=1)
        self.canv['bd'] = 0
        self.canv['highlightthickness'] = 0
        self.canv['bg'] = self.main.colors[0]
        Label(self.ef,
              font=(self.main.font, 18),
              fg=self.main.colors[4],
              text="Search by client",
              bg=self.main.colors[0]).pack(side=LEFT)
        self.search_by_client = Entry(self.ef,
                                      bd=0,
                                      highlightthickness=0,
                                      fg=self.main.colors[2],
                                      bg=self.main.colors[3],
                                      font=(self.main.font, 16))
        self.search_by_client.bind("<KeyRelease>", self.checkMatch)
        self.search_by_client.pack(side=LEFT, padx=20)

        self.ef.pack(side=BOTTOM)
        self.bottomFrame.pack(fill=BOTH, expand=1)
        self.tplot()

    def checkMatch(self, e):
        typed = self.search_by_client.get()
        if typed == '':
            data = self.main.db.get_all_transactions()
        else:
            data = []
            for i in self.main.db.get_all_transactions():
                if typed.lower() in i[4].lower() or typed.lower(
                ) in i[3].lower():
                    data.append(i)

        self.treeV.delete(*self.treeV.get_children())
        for i in range(len(data)):
            self.treeV.insert(parent='',
                              index='end',
                              iid=i,
                              text='',
                              values=(data[i][1], data[i][0], data[i][2],
                                      data[i][3], data[i][4], data[i][5]))

    def tplot(self):
        data = self.main.db.getAmtAndDate()
        sizes = [i[0] for i in data]
        labels = [i[1] for i in data]
        print(sizes, labels)
        self.ax.clear()
        self.ax.pie(sizes,
                    labels=labels,
                    autopct="%1.1f%%",
                    colors=self.main.colors,
                    radius=1.4)
        self.chartcanv.draw_idle()

    def add(self):
        amt = float(self.amt.get())
        name = self.personName.get()
        contact = self.clientContact.get()
        date = datetime.date.today()
        category = self.categories[self.category.current()][0]
        if amt > 0 and len(name) < 20 and len(contact) < 20:
            self.main.db.new_transaction(name, contact, self.trans_type.get(),
                                         amt, category, date)
            self.showDashboard()

    def set_styles(self):
        self.style = ttk.Style()
        self.style.configure("Treeview",
                             background=self.main.colors[0],
                             foreground=self.main.colors[3],
                             fieldbackground=self.main.colors[1],
                             rowheight=25,
                             height=100,
                             borderwidth=0,
                             bd=0,
                             highlightthickness=0,
                             font=(self.main.font, 12))
        self.style.map("Treeview",
                       background=[('selected', self.main.colors[2])])
        self.style.configure(
            "Treeview.Heading",
            font=(self.main.font, 12),
            background=self.main.colors[3],
            foreground=self.main.colors[0],
            padding=5,
            bd=0,
            highlightthickness=0,
        )

        self.style.layout("Treeview", [('Treeview.treearea', {
            'sticky': 'nswe'
        })])

    def show(self):
        self.main.mainFrame.pack_forget()
        self.tFrame.pack(fill=BOTH, expand=True)

        self.main.db.refresh_treev(self.treeV)
        self.tplot()

    def showDashboard(self):
        self.tFrame.pack_forget()
        self.main.mainFrame.pack(fill=BOTH, expand=1)
Example #24
0
class PhaseApp(tk.Tk):
    """Tkinter application for manual phase correction.

    See Also
    --------
    :py:func:`manual_phase_spectrum`
    """
    def __init__(self, spectrum, max_p1):
        super().__init__()
        self.p0 = 0.0
        self.p1 = 0.0
        self.n = spectrum.size
        self.pivot = int(self.n // 2)
        self.init_spectrum = copy.deepcopy(spectrum)

        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)
        self.fig = Figure(figsize=(6, 4), dpi=160)
        # Set colour of figure frame
        color = self.cget('bg')
        self.fig.patch.set_facecolor(color)
        self.ax = self.fig.add_axes([0.03, 0.1, 0.94, 0.87])
        self.ax.set_yticks([])
        self.specline = self.ax.plot(np.real(spectrum), color='k')[0]

        ylim = self.ax.get_ylim()

        mx = max(
            np.amax(np.real(spectrum)),
            np.abs(np.amin(np.real(spectrum))),
        )
        self.pivotline = self.ax.plot(
            2 * [self.pivot],
            [-10 * mx, 10 * mx],
            color='r',
        )[0]

        self.ax.set_ylim(ylim)

        self.canvas = FigureCanvasTkAgg(self.fig, master=self)
        self.canvas.draw()
        self.canvas.get_tk_widget().grid(
            row=0,
            column=0,
            padx=10,
            pady=10,
            sticky='nsew',
        )

        self.toolbar = NavigationToolbar2Tk(
            self.canvas,
            self,
            pack_toolbar=False,
        )
        self.toolbar.grid(row=1, column=0, pady=(0, 10), sticky='w')
        self.scale_frame = tk.Frame(self)
        self.scale_frame.grid(
            row=2,
            column=0,
            padx=10,
            pady=(0, 10),
            sticky='nsew',
        )
        self.scale_frame.columnconfigure(1, weight=1)
        self.scale_frame.rowconfigure(0, weight=1)

        items = [
            (self.pivot, self.p0, self.p1),
            ('pivot', 'p0', 'p1'),
            (0, -np.pi, -max_p1),
            (self.n, np.pi, max_p1),
        ]

        for i, (init, name, mn, mx) in enumerate(zip(*items)):
            lab = tk.Label(self.scale_frame, text=name)
            pady = (0, 10) if i != 2 else 0
            lab.grid(row=i, column=0, sticky='w', padx=(0, 5), pady=pady)

            self.__dict__[f'{name}_scale'] = scale = tk.Scale(
                self.scale_frame,
                from_=mn,
                to=mx,
                resolution=0.001,
                orient=tk.HORIZONTAL,
                showvalue=0,
                sliderlength=15,
                bd=0,
                highlightthickness=1,
                highlightbackground='black',
                relief='flat',
                command=lambda value, name=name: self.update_phase(name),
            )
            scale.set(init)
            scale.grid(row=i, column=1, sticky='ew', pady=pady)

            self.__dict__[f'{name}_label'] = label = tk.Label(
                self.scale_frame,
                text=f"{self.__dict__[f'{name}']:.3f}"
                if i != 0 else str(self.__dict__[f'{name}']))
            label.grid(row=i, column=2, padx=5, pady=pady, sticky='w')

        self.button_frame = tk.Frame(self)
        self.button_frame.columnconfigure(0, weight=1)
        self.button_frame.grid(row=3, column=0, padx=10, pady=10, sticky='ew')

        self.save_button = tk.Button(self.button_frame,
                                     width=8,
                                     highlightbackground='black',
                                     text='Save',
                                     bg='#77dd77',
                                     command=self.save)
        self.save_button.grid(row=1, column=0, sticky='e')

        self.cancel_button = tk.Button(self.button_frame,
                                       width=8,
                                       highlightbackground='black',
                                       text='Cancel',
                                       bg='#ff5566',
                                       command=self.cancel)
        self.cancel_button.grid(row=1, column=1, sticky='e', padx=(10, 0))

    def update_phase(self, name):
        value = self.__dict__[f'{name}_scale'].get()

        if name == 'pivot':
            self.pivot = int(value)
            self.pivot_label['text'] = str(self.pivot)
            self.pivotline.set_xdata([self.pivot, self.pivot])

        else:
            self.__dict__[name] = float(value)
            self.__dict__[f'{name}_label']['text'] = \
                f"{self.__dict__[name]:.3f}"

        spectrum = phase(
            self.init_spectrum,
            [self.p0],
            [self.p1],
            [self.pivot],
        )
        self.specline.set_ydata(np.real(spectrum))
        self.canvas.draw_idle()

    def save(self):
        self.p0 = self.p0 - self.p1 * (self.pivot / self.n)
        self.destroy()

    def cancel(self):
        self.destroy()
        self.p0 = None
        self.p1 = None
Example #25
0
class GraphFrame(tk.Frame):
    def __init__(self, parent, **kw):
        super().__init__(parent, **kw)
        self.atoms_logic = AtomsLogic()
        self.condition_build_surface = True
        label = tk.Label(self, text="Graph Page", font=LARGE_FONT)
        label.pack(pady=10, padx=10)
        self.is_new_point = False
        self.quit = False
        self.x_arr, self.y_arr = np.meshgrid(np.arange(0, MAX_FIELD_SIZE, 1),
                                             np.arange(0, MAX_FIELD_SIZE, 1))
        self.surface = None
        self.tool_tip = None
        self.captured_atom = None
        fig = plt.figure()
        self.ax = fig.add_subplot(111, projection='3d')

        plt.xlim(0, MAX_FIELD_SIZE + 2)
        plt.ylim(0, MAX_FIELD_SIZE + 2)

        self.canvas = FigureCanvasTkAgg(fig, self)
        self.canvas.get_tk_widget().pack(side=tk.BOTTOM,
                                         fill=tk.BOTH,
                                         expand=True)

        toolbar = NavigationToolbar2Tk(self.canvas, self)
        toolbar.update()
        self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)

    def update_graph_data_algorithm(self):
        if self.atoms_logic.is_new_point():
            try:
                self.tool_tip.remove() if self.tool_tip is not None else None
                self.captured_atom.remove(
                ) if self.captured_atom is not None else None
            except Exception as e:
                self.captured_atom = None
                print(traceback.format_exc())
                print(str(e))
            if self.atoms_logic.atom_release_event:
                self.ax.scatter(*self.atoms_logic.get_tool_coordinate(),
                                s=5,
                                c=COLOR_ATOM,
                                marker='8')
                self.atoms_logic.atom_release_event = False
            self.atoms_logic.update_tool_coordinate()
            self.tool_tip = self.ax.scatter(
                *self.atoms_logic.get_tool_coordinate(),
                s=5,
                c=COLOR_TIP,
                marker='8')
            if self.atoms_logic.atom_collection.append_unique_atom():
                self.ax.scatter(*self.atoms_logic.get_tool_coordinate(),
                                s=5,
                                c=COLOR_ATOM,
                                marker='8')
            if self.atoms_logic.atom_captured_event:
                self.__update_all_dots_on_graph()
                self.atoms_logic.atom_captured_event = False
            if self.atoms_logic.is_atom_captured():
                self.captured_atom = self.ax.scatter(
                    *self.atoms_logic.get_tool_coordinate(),
                    s=5,
                    c=COLOR_ATOM,
                    marker='8')
            if self.condition_build_surface:
                self.__build_surface()
            self.__reset_sensor()

    def __reset_sensor(self):
        if self.atoms_logic.tool_is_coming_down():
            return
        self.atoms_logic.set_is_surface(False)
        self.atoms_logic.set_is_atom(False)

    def __update_all_dots_on_graph(self):
        self.ax.collections = []
        self.__set_tool_tip_dot()
        for atom in self.atoms_logic.atom_collection.atoms_list:
            atom: Atom
            if not atom.is_captured:
                self.ax.scatter(*atom.coordinates,
                                s=5,
                                c=COLOR_ATOM,
                                marker='8')
            else:
                self.captured_atom = self.ax.scatter(
                    *self.atoms_logic.get_tool_coordinate(),
                    s=5,
                    c=COLOR_ATOM,
                    marker='8')

    def __set_tool_tip_dot(self):
        self.tool_tip = self.ax.scatter(
            *self.atoms_logic.get_tool_coordinate(),
            s=5,
            c=COLOR_TIP,
            marker='8')

    def show_surface(self):
        self.__build_surface()

    def remove_surface(self):
        try:
            if self.surface is not None: self.surface.remove()
        except Exception as e:
            print(traceback.format_exc())
            print(str(e))

    def draw_graph(self):
        while not self.quit:
            try:
                time.sleep(SLEEP_BETWEEN_DRAW_GRAPH)
                self.canvas.draw_idle()
            except Exception as e:
                self.quit = True
                print(traceback.format_exc())
                print(str(e))
                exit(0)

    @staticmethod
    def write_data_to_json_file(file_name: str, data):
        if os.path.exists(file_name):
            with open(file_name, 'rb+') as data_file:
                data_file.seek(-1, os.SEEK_END)
                data_file.truncate()
            with open(file_name, 'a') as data_file:
                data_file.write(f",{json.dumps(data)}]")
        else:
            with open(file_name, 'a') as data_file:
                data_file.write(f"[{json.dumps(data)}]")

    @staticmethod
    def read_json_file(file_name: str):
        if os.path.exists(file_name):
            with open(file_name, 'r') as data_file:
                return json.load(data_file)

    def __build_surface(self):
        self.remove_surface()
        self.surface = self.ax.plot_surface(
            self.x_arr,
            self.y_arr,
            self.atoms_logic.surface_data,
            rstride=1,
            cstride=1,
            cmap=plt.cm.get_cmap('Blues_r'),
        )
        self.canvas.draw_idle()
        self.ax.mouse_init()

    def get_data(self) -> object:
        return self.atoms_logic.surface_data.tolist()
class StrainMapping:
    def __init__(self, directory):

        self.directory = directory
        self.sampleArray = self.directory.sampleFits.arrays
        self.openArray = self.directory.openFits.arrays
        self.im = self.sampleArray[sliderInd]

        self.frame = tk.Toplevel()
        self.fig = Figure(figsize=(7, 7))
        self.ax = self.fig.add_subplot(111)

        self.strainButton = tk.Button(self.frame,
                                      text="do",
                                      command=self.strainMap)

        self.canvas = FigureCanvasTkAgg(self.fig, master=self.frame)
        self.canvas.show()
        self.canvas.get_tk_widget().grid(row=0)
        self.canvas.mpl_connect('key_press_event', self.onKey)
        self.strainButton.grid(row=1)

        self.mask = np.zeros((512, 512))
        self.pix = np.arange(512)
        self.XX, self.YY = np.meshgrid(self.pix, self.pix)
        self.pix = np.vstack((self.XX.flatten(), self.YY.flatten())).T
        self.lasso = LassoSelector(self.ax, self.onselect)

    def do(self):
        self.canvas.mpl_connect('key_press_event', self.onKey)
        self.ax.imshow(self.im, cmap=plt.cm.gray)

    def strainMap(self):

        zipped = zip(self.sampleArray, self.openArray)
        transmitted = np.zeros((len(zipped), 1, 512 * 512)).astype(np.float32)

        l = 0
        kernel = np.ones((5, 5))
        kernel = kernel / kernel.sum()
        for sample, empty in zipped:
            sample = sample * self.mask.reshape(512, 512)
            empty = empty * self.mask.reshape(512, 512)

            transmitted[l] = convolve2d(
                sample, kernel, mode='same').flatten() / convolve2d(
                    empty, kernel, mode='same').flatten()
            l += 1
            print l

        lambdas = []
        for c in range(512 * 512):
            if transmitted[:, :, c][posList[0]:posList[-1]].all() == False:
                lambdas.append(0)
                print 'empty'

            else:
                try:
                    popt, pcov = curve_fit(
                        self.func,
                        wavelength[posList[0]:posList[-1] + 1],
                        np.dstack(
                            np.nan_to_num(
                                transmitted[:, :, c][posList[0]:posList[-1] +
                                                     1]))[0][0],
                        p0=initial_guess)

                    lambdas.append(
                        (initial_guess[2] - popt[2]) / initial_guess[2])
                    print 'full'
                    "fit Bragg edge, record position"
                except (OptimizeWarning, RuntimeError):
                    lambdas.append(
                        (initial_guess[2] - popt[2]) / initial_guess[2])
                    print 'Exception'

        strainMap = np.array(lambdas).reshape(512, 512) * self.mask.reshape(
            512, 512)
        strainMap = np.ma.masked_where(strainMap == 0, strainMap)
        minVal = strainMap.min()
        maxVal = strainMap.max()
        cmap = plt.cm.coolwarm
        cmap.set_bad(color='black')
        fig = plt.figure()
        ax = fig.add_subplot(111)
        cax = ax.imshow(strainMap, interpolation='None', cmap=cmap)
        cbar = fig.colorbar(cax, ticks=[minVal, 0, maxVal])
        cbar.ax.set_yticklabels(['< ' + minVal, '0', '> ' + maxVal])
        plt.show()
        plt.close()

    def func(self, x, c_1, c_2, lambda0, sigma, tau):
        return c_1 * (scipy.special.erfc(
            (lambda0 - x) / (np.sqrt(2) * sigma)) - np.exp(
                ((lambda0 - x) / tau) +
                (sigma**2 / (2 * tau**2))) * scipy.special.erfc((
                    (lambda0 - x) /
                    (np.sqrt(2) * sigma)) + sigma / (np.sqrt(2) * tau))) + c_2

    def updateArray(self, im, indices, mask):
        lin = np.arange(self.im.size)
        self.mask = self.mask.flatten()
        self.mask[lin[indices]] = 1
        newArray = im.flatten()
        #newArray[lin[indices]] = 1
        newArray = newArray * self.mask
        self.ax.imshow(newArray.reshape(self.im.shape), cmap=plt.cm.gray)
        self.canvas.draw()
        print self.mask
        return newArray.reshape(self.im.shape)

    def onselect(self, verts):
        p = path.Path(verts)
        ind = p.contains_points(self.pix, radius=1)
        array = self.updateArray(self.im, ind, self.mask)
        self.canvas.draw_idle()

    def onKey(self, event):
        print "key pressed"
        if event.key == 'r':
            self.ax.imshow(self.im, cmap=plt.cm.gray)
            self.canvas.draw()
class StrainMapping:
        
    def __init__(self, directory):
        
        self.directory = directory
        self.sampleArray = self.directory.sampleFits.arrays
        self.openArray = self.directory.openFits.arrays
        self.im = self.sampleArray[sliderInd]
        
        self.frame = tk.Toplevel()
        self.fig = Figure(figsize=(7, 7))
        self.ax = self.fig.add_subplot(111)
        
        self.strainButton = tk.Button(self.frame, text="do", command=self.strainMap)

        self.canvas = FigureCanvasTkAgg(self.fig, master=self.frame)
        self.canvas.show()
        self.canvas.get_tk_widget().grid(row=0)
        self.canvas.mpl_connect('key_press_event', self.onKey)
        self.strainButton.grid(row=1)
        
        self.mask = np.zeros((512,512))
        self.pix = np.arange(512)
        self.XX, self.YY = np.meshgrid(self.pix, self.pix)
        self.pix = np.vstack((self.XX.flatten(), self.YY.flatten())).T
        self.lasso = LassoSelector(self.ax, self.onselect)
        
        
        
    def do(self):
        self.canvas.mpl_connect('key_press_event', self.onKey)
        self.ax.imshow(self.im, cmap = plt.cm.gray)
        

    def strainMap(self):

        zipped = zip(self.sampleArray, self.openArray)
        transmitted = np.zeros((len(zipped),1,512*512)).astype(np.float32)
        
        l = 0
        kernel = np.ones((5,5))
        kernel = kernel / kernel.sum()
        for sample, empty in zipped:
            sample = sample * self.mask.reshape(512,512)
            empty = empty * self.mask.reshape(512,512)
            
            transmitted[l] = convolve2d(sample, kernel, mode='same').flatten() / convolve2d(empty, kernel, mode='same').flatten()
            l += 1
            print l
        
        lambdas = []
        for c in range(512*512):
            if transmitted[:,:,c][posList[0]:posList[-1]].all() == False:
                lambdas.append(0)
                print 'empty'

            else:
                try:
                    popt, pcov = curve_fit(self.func, wavelength[posList[0]:posList[-1]+1], np.dstack(np.nan_to_num(transmitted[:,:,c][posList[0]:posList[-1]+1]))[0][0], p0=initial_guess)
                
                    lambdas.append((initial_guess[2] - popt[2])/initial_guess[2])
                    print 'full'
                    "fit Bragg edge, record position"
                except (OptimizeWarning, RuntimeError):
                    lambdas.append((initial_guess[2] - popt[2])/initial_guess[2])
                    print 'Exception'
                
                
        strainMap = np.array(lambdas).reshape(512,512)*self.mask.reshape(512,512) 
        strainMap = np.ma.masked_where(strainMap == 0, strainMap)
        minVal = strainMap.min()
        maxVal = strainMap.max()
        cmap = plt.cm.coolwarm
        cmap.set_bad(color='black')
        fig = plt.figure()
        ax = fig.add_subplot(111)
        cax = ax.imshow(strainMap, interpolation='None', cmap=cmap)
        cbar = fig.colorbar(cax, ticks=[minVal, 0, maxVal])
        cbar.ax.set_yticklabels(['< '+minVal, '0', '> '+maxVal])
        plt.show()
        plt.close()
                
    def func(self, x, c_1, c_2, lambda0, sigma, tau):
        return c_1 * (scipy.special.erfc((lambda0 - x) / (np.sqrt(2) * sigma)) - np.exp(
            ((lambda0 - x) / tau) + (sigma ** 2 / (2 * tau ** 2))) * scipy.special.erfc(
            ((lambda0 - x) / (np.sqrt(2) * sigma)) + sigma / (np.sqrt(2) * tau))) + c_2   
        
    def updateArray(self, im, indices,mask):
        lin = np.arange(self.im.size)
        self.mask = self.mask.flatten()
        self.mask[lin[indices]] = 1
        newArray = im.flatten()
        #newArray[lin[indices]] = 1
        newArray = newArray*self.mask
        self.ax.imshow(newArray.reshape(self.im.shape), cmap=plt.cm.gray)
        self.canvas.draw()
        print self.mask
        return newArray.reshape(self.im.shape)

    def onselect(self, verts):
        p = path.Path(verts)
        ind = p.contains_points(self.pix, radius=1)
        array = self.updateArray(self.im, ind, self.mask)
        self.canvas.draw_idle()
        
    def onKey(self, event):
        print "key pressed"
        if event.key == 'r':
            self.ax.imshow(self.im, cmap=plt.cm.gray)
            self.canvas.draw()
Example #28
0
class LiveDataView(ttk.Frame):
    def __init__(self, parent, x_history=30, scale_x=1, scale_y = 1, data_types={'default': 'line'}, **ax_kwargs):
        self.parent = parent
        self.x_history = x_history * scale_x
        self.scale_x = scale_x
        self.scale_y = scale_y

        # Create matplotlib figure
        self.fig_preview = Figure()
        self.ax_preview = self.fig_preview.add_subplot(111)
        self.data = {}
        for name, plot_type in data_types.items():
            if plot_type in ['line', 'plot']:
                data, = self.ax_preview.plot(0, 0)
            elif plot_type == 'scatter':
                data = self.ax_preview.scatter(0, 0)
            self.data[name] = data
        self.ax_preview.set(**ax_kwargs)
        self.ax_preview.set_xlim((-self.x_history, 0))

        # Add to tkinter
        self.canvas_preview = FigureCanvasTkAgg(self.fig_preview, self.parent)
        self.canvas_preview.draw()
        self.canvas_preview.get_tk_widget().grid(row=0, column=0, sticky='wens')

    def update_view(self, xy, name='default'):
        # Update data
        # Need to determine the type of plot it is.
        new_xy = xy * np.array([self.scale_x, self.scale_y])
        data_type = type(self.data[name])
        if data_type == matplotlib.lines.Line2D:
            # Line plot
            current = self.data[name].get_xydata()
            updated = self.update_data(current, new_xy)
            self.data[name].set_data(updated.T)
        elif data_type == matplotlib.collections.PathCollection:
            # Scatter plot
            current = self.data[name].get_offsets()
            updated = self.update_data(current, new_xy)
            self.data[name].set_offsets(updated)

        # Update view
        new_xlim = new_xy[0] + np.array([-self.x_history, 0])
        self.ax_preview.set_xlim(new_xlim)
        self.canvas_preview.draw_idle()

    def update_data(self, current, xy):
        # Only keep data for window defined by `x_history`
        # Should keep down on resource usage.
        new_ix = current[:, 0] > xy[0] - self.x_history
        return np.concatenate([current[new_ix, :], [xy]], axis=0)

    def clear_data(self):
        blank = np.zeros((1, 2))
        for name, data in self.data.items():
            data_type = type(self.data[name])
            if data_type == matplotlib.lines.Line2D:
                # Need at least 2 data points for some reason...
                self.data[name].set_data(np.concatenate([blank, blank]))
            elif data_type == matplotlib.collections.PathCollection:
                self.data[name].set_offsets(blank)

        # Update view
        self.ax_preview.set_xlim([-self.x_history, 0])
        self.canvas_preview.draw_idle()
Example #29
0
class SpectralNetworkPlotTk(SpectralNetworkPlotUIBase):
    """
    This class implements UIs using Tkinter.

    The content of this class is independent of the parent class.
    It only depends on the grandparent class, which should be
    'NetworkPlotBase'. Therefore this class can inherit any class
    whose parent is 'NetworkPlotBase'; just change the name of the
    parent in the definition of this class.
    """
    def __init__(self, master=None, title=None, plot_range=None,):
        super(SpectralNetworkPlotTk, self).__init__(
            matplotlib_figure=matplotlib.figure.Figure(),
            plot_range=plot_range,
        )

        if master is None:
            root = tk.Tk()
            root.withdraw()
            self.root = root
        else:
            self.root = master
        self.master = master

        # Create a Toplevel widget, which is a child of GUILoom
        # and contains plots,
        self.toplevel = tk.Toplevel(self.root)
        self.toplevel.wm_title(title)
        self.toplevel.protocol("WM_DELETE_WINDOW", self.on_closing)

        self.plot_idx_scale = None

        self.plot_idx_entry = None
        self.plot_idx_entry_var = tk.StringVar()
        self.plot_idx_entry_var.trace('w', self.plot_idx_entry_change)

        self.canvas = FigureCanvas(
            self.figure,
            master=self.toplevel,
            resize_callback=self.canvas_resize_callback
        )
        self.canvas.show()
        self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)

        toolbar = NavigationToolbar(self.canvas, self.toplevel)
        toolbar.update()
        self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)

    def on_closing(self):
        self.toplevel.destroy()
        if self.master is None:
            self.root.destroy()

    def scale_action(self, scale_value):
        new_plot_idx = int(scale_value)
        self.update_current_plot(new_plot_idx)
        self.plot_idx_entry_var.set(new_plot_idx)

    def plot_idx_entry_change(self, *args):
        try:
            new_plot_idx = int(self.plot_idx_entry_var.get())

            if new_plot_idx == self.current_plot_idx:
                return None
            elif new_plot_idx < 0:
                new_plot_idx = 0
            elif new_plot_idx > len(self.plots) - 1:
                new_plot_idx = len(self.plots) - 1

            self.plot_idx_scale.set(new_plot_idx)
            self.update_current_plot(new_plot_idx)

        except ValueError:
            pass

        return None

    def update_current_plot(self, new_plot_idx):
        if self.data_cursor is not None:
            self.data_cursor.hide().disable()

        self.plots[self.current_plot_idx].set_visible(False)
        self.plots[new_plot_idx].set_visible(True)
        # Update the index variable for the currently displayed plot.
        self.current_plot_idx = new_plot_idx
        self.set_data_cursor()
        self.canvas.draw_idle()
        self.canvas.get_tk_widget().focus_set()

        return None

    def canvas_resize_callback(self, event):
        self.set_data_cursor()

    def show(self):
        plot_idx = 0
        self.current_plot_idx = plot_idx
        self.plots[plot_idx].set_visible(True)
        self.set_data_cursor()

        if(len(self.plots) > 1):
            tk.Label(
                self.toplevel,
                text='Plot #',
            ).pack(side=tk.LEFT)

            self.plot_idx_entry_var.set(plot_idx)
            self.plot_idx_entry = tk.Entry(
                self.toplevel,
                textvariable=self.plot_idx_entry_var,
                width=len(str(len(self.plots) - 1)),
            )
            self.plot_idx_entry.pack(side=tk.LEFT)

            tk.Label(
                self.toplevel,
                text='/{}'.format(len(self.plots) - 1),
            ).pack(side=tk.LEFT)

            self.plot_idx_scale = tk.Scale(
                self.toplevel,
                command=self.scale_action,
                # length=100*len(self.plots),
                orient=tk.HORIZONTAL,
                showvalue=0,
                to=len(self.plots) - 1,
                variable=self.current_plot_idx,
            )
            self.plot_idx_scale.pack(
                expand=True,
                fill=tk.X,
                side=tk.LEFT,
            )
Example #30
0
class Watch():
    xy_data_style = {'fontsize': 28, 'rotation': 0}

    main_panel = 0

    def __init__(self, frame, config=None, width=100, height=100, ready=None):
        self._frame = frame
        self._fig = None
        self.config = config
        self.canvas = None
        self.width = width
        self.height = height
        self.ready = ready
        self.type = ''

        if 'fontsize' in config:
            self.xy_data_style['fontsize'] = config['fontsize']

        self.k_watch = data.K(other.stock_csv_path(self.config))
        self.k = None
        self.trend_watch = data.Trend(other.csv_path(self.config))
        self.trend = None
        self.k_trend = None

        self._use_style()

    # 繪製
    def plot(self, code, date=None, **kwargs):
        if self._fig is not None:
            self.clear()
        else:
            self._fig = plt.figure()
            self._fig.set_size_inches((self.width / 100, self.height / 100))
            self.canvas = FigureCanvasTkAgg(self._fig, self._frame)

        self.kwargs = kwargs
        self.update_plot(code, date=date, **kwargs)

        return self._fig

    # 繪製某個股
    def update_plot(self, code, date=None, **kwargs):
        type = kwargs.get('type')

        if type == 'k':
            self._plot_k(code, date=date, **kwargs)
        elif type == 'trend':
            self._plot_trend(code, date=date, **kwargs)
        elif type == 'k_trend':
            self._plot_k_trend(code, date=date, **kwargs)

        self.canvas.draw_idle()

        return True

    # K線看盤
    def _plot_k(self, code, date=None, **kwargs):
        if self.k is None:
            self.k = KWatch(
                self._fig,
                self.canvas,
                self.k_watch,
            )

        self.k.plot(code, date=date, **kwargs)

    # 走勢圖看盤
    def _plot_trend(self, code, date=None, **kwargs):
        if self.trend is None:
            self.trend = TrendWatch(
                self._fig,
                self.canvas,
                self.trend_watch,
                self.k_watch.get_stock(),
            )

        self.trend.plot(code, date=date, **kwargs)

    def _plot_k_trend(self, code, date=None, **kwargs):
        if self.k_trend is None:
            self.k_trend = KTrendWatch(
                self._fig,
                self.canvas,
                self.k_watch,
                self.trend_watch,
                self.k_watch.get_stock(),
            )

        self.k_trend.plot(code, date=date, **kwargs)

    # 設定看盤樣式
    def _use_style(self):
        plt.rcParams['font.sans-serif'] = ['Taipei Sans TC Beta']
        plt.rcParams['axes.unicode_minus'] = False

        plt.style.use('dark_background')
        plt.rcParams.update([
            ('axes.edgecolor', 'white'),
            ('axes.linewidth', 1.5),
            ('axes.labelsize', 'large'),
            ('axes.labelweight', 'semibold'),
            ('axes.grid', True),
            ('axes.grid.axis', 'y'),
            ('grid.linewidth', 0.4),
            ('lines.linewidth', 2.0),
            ('font.weight', 'medium'),
            ('font.size', 10.0),
        ])

        plt.rcParams.update({
            'axes.facecolor': '#0f0f10',
            'grid.linestyle': '-',
            'grid.color': '#a0a0a0',
        })

    def clear(self):
        for ax in [self.k, self.trend, self.k_trend]:
            if ax is not None:
                ax.remove()

        self._fig.clear()

    # 執行
    def pack(self):
        self.canvas.draw()
        self.canvas.get_tk_widget().focus_force()
        self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
Example #31
0
class Main():
    def __init__(self):
        self.thread_handler = thread_handler.ThreadHandler()
        self.temperature_control = TC.TemperatureControl()
        self.ph_control = PHC.PHControl()
        self.pressure_control = PC.PressureControl()
        self.co2_control = CC.Co2Control()
        self.reactor = reactor.reactor()
        self.thermocouple = TCS.thermocouple()
        self.phsensor = PHS.phsensor()
        self.pressure_sensor = PS.SensorPressure()
        self.co2_sensor = CS.SensorCo2()
        self.running = False
        self.shutting_down = False
        self.update_delay = 250
        self.should_update_setpoint = False
        self.should_update_spinbox = False

    def shut_down(self):
        """
        Stop all running threads before stopping main thread
        """
        self.m.after_cancel(self.window_update)
        self.window_update = None
        self.temperature_control.stop()
        self.ph_control.stop()
        self.pressure_control.stop()
        self.co2_control.stop()
        self.reactor.stop()
        self.thread_handler.stop_threads()
        self.running = False
        self.m.quit()

    def start_drawing(self):
        ''' Root '''
        self.m = tk.Tk(className='Bioreactor Simulator')
        self.m.title("Bioreactor Simulator")
        self.m.geometry("800x600")
        self.m['background'] = 'white'
        ''' Menu '''
        self.menu = tk.Menu(self.m)
        self.m.config(menu=self.menu)
        ''' File - Reset and Exit'''
        self.menu_file = tk.Menu(self.menu)
        self.menu.add_cascade(label='File', menu=self.menu_file)
        self.menu_file.add_command(label='Reset', command=self.on_reset)
        self.menu_file.add_separator()
        self.menu_file.add_command(label='Exit', command=self.on_closing)
        ''' Help - About'''
        self.menu_help = tk.Menu(self.menu)
        self.menu.add_cascade(label='Help', menu=self.menu_help)
        self.menu_help.add_command(label='About', command=self.show_about)
        ''' Canvas, used for drawing matplotlib plot '''
        canvas = tk.Canvas(self.m, width=800, height=600)
        canvas.pack(side=tk.LEFT)
        ''' Matplotlib plot '''
        figure = plt.figure(figsize=(6, 5), dpi=100)
        self.ax = figure.add_subplot(111)
        self.plot_canvas = FigureCanvasTkAgg(figure, master=canvas)
        self.plot_canvas.get_tk_widget().pack()
        ''' Controls frame, contains three sections:
            Setpoint control - Allows PID setpoints to be changed
            Effector selection - Allows plotted effector to be changed
            Labels for current values - Display current values from PIDs'''
        frame_controls = tk.Frame(self.m, width=200, height=200)
        frame_controls.pack(side=tk.RIGHT)
        ''' Setpoint control '''
        frame_setpoint = tk.Frame(frame_controls, width=200, height=200)
        frame_setpoint.pack(pady=20)
        lbl_setpoint = tk.Label(frame_setpoint, text="Setpoint:")
        lbl_setpoint.pack()
        self.spbx_setpoint = tk.Spinbox(frame_setpoint)
        self.spbx_setpoint.pack(side=tk.LEFT)
        btn_setpoint = tk.Button(frame_setpoint,
                                 text='Update',
                                 command=self.on_setpoint_changed)
        btn_setpoint.pack(side=tk.RIGHT)
        ''' Effector selection '''
        frame_plot_select = tk.Frame(frame_controls, width=200, height=200)
        frame_plot_select.pack(pady=20)
        lbl_plot_select = tk.Label(frame_plot_select,
                                   text="Plot Shown:",
                                   justify=tk.LEFT)
        lbl_plot_select.pack()
        self.selected_plot = tk.IntVar(self.m)
        radbtn_temp = tk.Radiobutton(frame_plot_select,
                                     text="Temperature",
                                     variable=self.selected_plot,
                                     value=0,
                                     command=self.on_plot_source_changed,
                                     width=100,
                                     indicatoron=0)
        radbtn_temp.pack()
        radbtn_ph = tk.Radiobutton(frame_plot_select,
                                   text="pH",
                                   variable=self.selected_plot,
                                   value=1,
                                   command=self.on_plot_source_changed,
                                   width=100,
                                   indicatoron=0)
        radbtn_ph.pack()
        radbtn_pressure = tk.Radiobutton(frame_plot_select,
                                         text="Pressure",
                                         variable=self.selected_plot,
                                         value=2,
                                         command=self.on_plot_source_changed,
                                         width=100,
                                         indicatoron=0)
        radbtn_pressure.pack()
        radbtn_co2 = tk.Radiobutton(frame_plot_select,
                                    text="CO2",
                                    variable=self.selected_plot,
                                    value=3,
                                    command=self.on_plot_source_changed,
                                    width=100,
                                    indicatoron=0)
        radbtn_co2.pack()
        ''' Labels for current values '''
        frame_curr_vals = tk.Frame(frame_controls, width=200, height=200)
        frame_curr_vals.pack(pady=20)
        ''' Label - Temperature '''
        frame_lbl_temp = tk.Frame(frame_curr_vals, width=200, height=100)
        frame_lbl_temp.pack()
        label_temp = tk.Label(frame_lbl_temp,
                              text="Temperature (\xb0C):",
                              justify=tk.LEFT)
        label_temp.pack(side=tk.LEFT)
        self.lbl_temp = tk.Label(frame_lbl_temp, text="0", justify=tk.LEFT)
        self.lbl_temp.pack(side=tk.RIGHT)
        ''' Label - pH '''
        frame_lbl_ph = tk.Frame(frame_curr_vals, width=200, height=100)
        frame_lbl_ph.pack()
        lbl_ph = tk.Label(frame_lbl_ph, text="pH:", justify=tk.LEFT)
        lbl_ph.pack(side=tk.LEFT)
        self.lbl_ph = tk.Label(frame_lbl_ph, text="0", justify=tk.LEFT)
        self.lbl_ph.pack(side=tk.RIGHT)
        ''' Label - Pressure '''
        frame_lbl_pressure = tk.Frame(frame_curr_vals, width=200, height=100)
        frame_lbl_pressure.pack()
        lbl_pressure = tk.Label(frame_lbl_pressure,
                                text="Pressure (bar):",
                                justify=tk.LEFT)
        lbl_pressure.pack(side=tk.LEFT)
        self.lbl_pressure = tk.Label(frame_lbl_pressure,
                                     text="0",
                                     justify=tk.LEFT)
        self.lbl_pressure.pack(side=tk.RIGHT)
        ''' Label - CO2 '''
        frame_lbl_co2 = tk.Frame(frame_curr_vals, width=200, height=100)
        frame_lbl_co2.pack()
        lbl_co2 = tk.Label(frame_lbl_co2, text="CO2 (%):", justify=tk.LEFT)
        lbl_co2.pack(side=tk.LEFT)
        self.lbl_co2 = tk.Label(frame_lbl_co2, text="0", justify=tk.LEFT)
        self.lbl_co2.pack(side=tk.RIGHT)
        ''' Call the gui_update function once, after set time has passed '''
        self.window_update = self.m.after(self.update_delay, self.update_gui)
        ''' Set up window functions '''
        self.m.protocol("WM_DELETE_WINDOW", self.on_closing)
        ''' Start main loop (do this last) '''
        self.m.mainloop()

    def on_plot_source_changed(self):
        ''' When changing the plot source, schedule spinbox to be updated '''
        self.should_update_spinbox = True

    def on_setpoint_changed(self):
        ''' When changing setpoint, schedule update for draw call '''
        self.should_update_setpoint = True

    def on_reset(self):
        ''' When reset uption is selcted, reset effectors '''
        self.temperature_control.reset()
        self.ph_control.reset()
        self.pressure_control.reset()
        self.co2_control.reset()

    def on_closing(self):
        self.shut_down()

    def show_about(self):
        message_to_show = """Credits:
Calum MacRobert
Mirrin Gillespie
Natasha Sutherland
Stefan Olsson"""
        self.msgbx_about = tk.messagebox.Message(self.m)
        self.msgbx_about.show(title="About", message=message_to_show)

    def draw_plot(self):
        ''' Draw selected plot on canvas from latest effector values'''
        if self.selected_plot.get() == 0:
            effector = self.temperature_control
        elif self.selected_plot.get() == 1:
            effector = self.ph_control
        elif self.selected_plot.get() == 2:
            effector = self.pressure_control
        elif self.selected_plot.get() == 3:
            effector = self.co2_control

        if (self.should_update_setpoint == True):
            ''' Update setpoint if value is valid '''
            new_setpoint = float(self.spbx_setpoint.get())
            if (new_setpoint <= effector.upper_range
                    and new_setpoint >= effector.lower_range):
                effector.set_setpoint(new_setpoint)
                self.spbx_setpoint.config(background="White")
            else:
                self.spbx_setpoint.config(background="Red")
            self.should_update_setpoint = False

        setpoint = effector.get_setpoint()
        lower_range = effector.lower_range
        upper_range = effector.upper_range
        lower_domain = effector.lower_domain
        upper_domain = effector.upper_domain

        self.spbx_setpoint.config(from_=lower_range, to=upper_range)
        if (self.should_update_spinbox == True):
            ''' Update spinbox after switching plot'''
            self.spbx_setpoint.delete(0, 'end')
            self.spbx_setpoint.insert(0, setpoint)
            self.should_update_spinbox = False

        self.ax.clear()
        self.ax.plot(effector.get_x(), effector.get_y())
        self.ax.hlines(setpoint, lower_domain, upper_domain, 'C1', 'dashed')
        plt.xlim(lower_domain, upper_domain)
        plt.ylim(lower_range, upper_range)
        self.ax.set_title(effector.get_title())
        self.ax.set_ylabel(effector.get_y_label())
        self.ax.set_xlabel("Time (s)")
        self.plot_canvas.draw_idle()

    def update_gui(self):
        ''' Update GUI, refreshing plots '''
        self.draw_plot()

        self.lbl_temp.config(
            text=str(round(self.temperature_control.get_current_value(), 3)))
        self.lbl_ph.config(
            text=str(round(self.ph_control.get_current_value(), 1)))
        self.lbl_pressure.config(
            text=str(round(self.pressure_control.get_current_value(), 1)))
        self.lbl_co2.config(
            text=str(round(self.co2_control.get_current_value(), 1)))
        ''' Schedule update function again'''
        self.window_update = self.m.after(self.update_delay, self.update_gui)

    def update_reactor(self):
        ''' Grabs values from reactor, passes them to places '''
        self.thermocouple.set_sensor_value(self.reactor.get_temperature())
        #self.temperature_control.set_current_value(self.thermocouple.get_sensor_value())
        self.reactor.set_peltier_temp(
            self.temperature_control.get_current_value())

        self.phsensor.set_sensor_value(self.reactor.get_ph())
        #self.ph_control.set_current_value(self.phsensor.get_sensor_value())
        self.reactor.set_ph_input(self.ph_control.get_current_value())

        self.pressure_sensor.set_sensor_value(self.reactor.get_pressure())
        #self.pressure_control.set_current_value(self.pressure_sensor.get_sensor_value())
        self.reactor.set_pressure_input(
            self.pressure_control.get_current_value())

        self.co2_sensor.set_sensor_value(self.reactor.get_co2())
        #self.co2_control.set_current_value(self.co2_sensor.get_sensor_value())
        self.reactor.set_co2_input(self.co2_control.get_current_value())

    def main(self):
        '''
        Main loop starts threads for window and effectors
            then continually runs own update function
            Currently waiting 1 second between updates, to aid debugging
        '''
        self.running = True

        self.thread_handler.start_thread("temperaturecontrol",
                                         self.temperature_control.start)
        self.thread_handler.start_thread("PHcontroler", self.ph_control.start)
        self.thread_handler.start_thread("PressureControler",
                                         self.pressure_control.start)
        self.thread_handler.start_thread("CO2 Controler",
                                         self.co2_control.start)
        self.thread_handler.start_thread("reactor", self.reactor.start)
        self.thread_handler.start_thread("window", self.start_drawing)

        while (self.running == True):
            time.sleep(1)  # Delay when polling, mainly for debugging
            self.update_reactor()

        self.shutting_down = True
        while (self.shutting_down == True):
            ''' Check all other threaded processes have stopped '''
            if (self.temperature_control.get_running() == False
                    and self.ph_control.get_running() == False
                    and self.pressure_control.get_running() == False
                    and self.co2_control.get_running() == False
                    and self.reactor.get_running() == False):
                self.shutting_down = False
        print("Main - Shutdown complete")
class matplotlibSwitchGraphs:
    def __init__(self, master):
        self.master = master
        self.frame = Frame(self.master)
        self.fig, self.ax, self.toolbar = config_plot()
        self.lanes = ['r', 'g', 'b', 'y']
        self.lane_idx = 0
        self.canvas = FigureCanvasTkAgg(self.fig, self.master)
        self.config_window()
        self.frame.pack(expand=YES, fill=BOTH)
        self.epsilon = 7
        self.active_point = None
        self.last_point = -1
        self.last_point_reference = None
        self.alpha = 0.8
        self.xs = []
        self.ys = []
        self.categories = []
        self.line = None
        self.point_references = []
        self.save_dir = 'annotations'
        self.image_paths = None
        self.current_image = -1
        self.init_save_dir()

    def config_window(self):
        self.canvas.mpl_connect("key_press_event", self.on_key_press)
        self.canvas.mpl_connect('button_press_event', self.on_click)
        self.canvas.mpl_connect('motion_notify_event',
                                self.motion_notify_callback)
        self.canvas.mpl_connect('button_release_event',
                                self.button_release_callback)
        toolbar = NavigationToolbar2Tk(self.canvas, self.master)
        toolbar.update()
        self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
        self.file_button = Button(self.master,
                                  text="Open",
                                  command=self.openfile)
        self.file_button.pack(side=RIGHT)
        self.button_image = Button(self.master,
                                   text="Next Image",
                                   command=self.load_image)
        self.button_image.pack(side=RIGHT)
        self.lane_switch = Button(self.master,
                                  text="Switch Lane",
                                  command=self.switch_lane)
        self.lane_switch.pack(side=RIGHT)
        self.save_button = Button(self.master,
                                  text="Save Annotation",
                                  command=self.save_annotation)
        self.save_button.pack(side=RIGHT)
        self.ax.set(title=self.lanes[self.lane_idx])

    def on_key_press(self, event):
        print("you pressed {}".format(event.key))

    def openfile(self):
        self.image_paths_file = filedialog.askopenfilename()
        with open(self.image_paths_file, 'r') as file:
            self.image_paths = file.readlines()
        for path in range(len(self.image_paths)):
            self.image_paths[path] = self.image_paths[path].replace('\n', '')

    def on_click(self, event):
        ret = False
        if not event.inaxes or self.canvas.toolbar._lastCursor in [3, 2]:
            return
        if len(self.xs) > 0:
            ret, self.active_point = self.get_ind_under_point(event)
        if ret:
            self.last_point = self.active_point
            self.highlight_active_point()
        if ret or event.button == 3:
            if event.button == 3 and ret:
                self.remove_active_point()
                self.last_point -= 1
                if len(self.xs) > 0:
                    self.highlight_active_point()
            return
        idx = self.last_point + 1
        if self.line:
            self.line.remove()
            self.line = None
        self.xs.insert(idx, event.xdata)
        self.ys.insert(idx, event.ydata)
        self.categories.insert(idx, self.lanes[self.lane_idx])
        point_reference = self.ax.plot(event.xdata,
                                       event.ydata,
                                       self.lanes[self.lane_idx] + 'o',
                                       alpha=self.alpha)
        self.point_references.insert(idx, point_reference[0])
        self.draw_line(category=self.lanes[self.lane_idx])
        self.last_point += 1
        self.highlight_active_point()
        self.canvas.draw_idle()

    def highlight_active_point(self):
        if self.last_point_reference is not None:
            self.last_point_reference.remove()
        self.last_point_reference = self.ax.plot(self.xs[self.last_point],
                                                 self.ys[self.last_point],
                                                 'ko',
                                                 alpha=self.alpha)[0]

    def load_image(self):
        if self.image_paths == None:
            self.openfile()
        self.save_annotation()
        self.reset_annotation()
        self.ax.clear()
        self.current_image = (self.current_image + 1) % len(self.image_paths)
        img = cv2.imread(self.image_paths[self.current_image])[:, :, (2, 1, 0)]
        self.image = img
        self.ax.imshow(img)
        self.load_annotation()
        self.ax.set(title=self.lanes[self.lane_idx])
        self.canvas.draw()

    def reset_annotation(self):
        self.active_point = None
        self.last_point = -1
        self.last_point_reference = None
        self.xs = []
        self.ys = []
        self.categories = []
        self.line = None
        self.point_references = []

    def save_annotation(self):
        '''saves annotations as 3 x n_points'''
        if len(self.xs) > 0:
            annotations = np.vstack([self.xs, self.ys, self.categories])
            filename = os.path.basename(
                self.image_paths[self.current_image]).split('.')[0]
            np.save(f'{self.save_dir}/{filename}', annotations)
            return True

    def init_save_dir(self):
        if not os.path.exists(self.save_dir):
            os.mkdir(self.save_dir)

    def load_annotation(self):
        filename = os.path.basename(
            self.image_paths[self.current_image]).split('.')[0]
        if os.path.exists(f'{self.save_dir}/{filename}.npy'):
            xs, ys, categories = np.load(f'{self.save_dir}/{filename}.npy')
            self.xs, self.ys, self.categories = list(
                xs.astype('float32')), list(
                    ys.astype('float32')), list(categories)
            for point in range(len(xs)):
                point_resference = self.ax.plot(self.xs[point],
                                                self.ys[point],
                                                f'{self.categories[point]}o',
                                                alpha=self.alpha)[0]
                self.point_references.append(point_resference)
            self.last_point = 0
            self.highlight_active_point()

    def _quit(self):
        self.master.quit()  # stops mainloop

    def switch_lane(self):
        self.lane_idx = (self.lane_idx + 1) % len(self.lanes)
        self.ax.set(title=self.lanes[self.lane_idx])
        self.canvas.draw_idle()

    def get_ind_under_point(self, event):
        '''get the index of the vertex under point if within epsilon tolerance'''
        is_available = True
        t = self.ax.transData.inverted()
        tinv = self.ax.transData
        xy = t.transform([event.x, event.y])
        x, yvals = np.array(self.xs), np.array(self.ys)
        xr = np.reshape(x, (np.shape(x)[0], 1))
        yr = np.reshape(yvals, (np.shape(yvals)[0], 1))
        xy_vals = np.append(xr, yr, 1)
        xyt = tinv.transform(xy_vals)
        xt, yt = xyt[:, 0], xyt[:, 1]
        d = np.hypot(xt - event.x, yt - event.y)
        indseq, = np.nonzero(d == d.min())
        ind = indseq[0]
        if d[ind] >= self.epsilon:
            is_available = False
        return is_available, ind

    def motion_notify_callback(self, event):
        if self.active_point is None:
            return
        if event.inaxes is None or event.button != 1:
            return
        self.ys[self.active_point] = event.ydata
        self.xs[self.active_point] = event.xdata
        self.update_point()
        self.highlight_active_point()
        self.canvas.draw_idle()

    def button_release_callback(self, event):
        if event.button == 1:
            self.active_point = None
        self.canvas.draw_idle()

    def remove_active_point(self):
        category = self.categories[self.active_point]
        if self.line:
            self.line.remove()
            self.line = None
        if self.active_point is not None:
            self.point_references[self.active_point].remove()
            self.point_references.pop(self.active_point)
            self.xs.pop(self.active_point)
            self.ys.pop(self.active_point)
            self.categories.pop(self.active_point)
            self.active_point = None
            self.draw_line(category)
            self.canvas.draw_idle()

    def update_point(self):
        self.point_references[self.active_point].remove()
        if self.line:
            self.line.remove()
        new_point_reference = self.ax.plot(
            self.xs[self.active_point],
            self.ys[self.active_point],
            f'{self.categories[self.active_point]}o',
            alpha=self.alpha)
        self.point_references[self.active_point] = new_point_reference[0]
        self.draw_line()

    def draw_line(self, category=None):
        if category is None:
            category = self.categories[self.active_point]
        if len(self.xs) > 0:
            xnp, ynp, cats_np = np.array(self.xs), np.array(self.ys), np.array(
                self.categories)
            xnp = xnp[cats_np == category]
            ynp = ynp[cats_np == category]
            self.line = self.ax.plot(xnp,
                                     ynp,
                                     f'{category}-',
                                     alpha=self.alpha)[0]
Example #33
0
class Screen(Frame):
    def __init__(self, master, locations,
                 debug=False,
                 debug_update=False,
                 debug_update2=False,
                 debug_netatmo=False,
                 debug_nowcast=False,
                 debug_forecast=False,
                 test_fail_netatmo=False,
                 test_fail_forecast=False,
                 test_fail_nowcast=False,
                 updtime=300000,
                 timeout_netatmo=5,
                 timeout_nowcast=4,
                 timeout_forecast=5):

        Frame.__init__(self, master)

        # Initialize
        self.master = master
        self.loc_index = 0
        self.locations = locations
        self.location = self.locations[self.loc_index]
        self.days = 5
        self.debug = debug
        self.debug_update = debug_update
        self.debug_update2 = debug_update2
        self.debug_netatmo = debug_netatmo
        self.debug_nowcast = debug_nowcast
        self.debug_forecast = debug_forecast
        self.test_fail_netatmo = test_fail_netatmo
        self.test_fail_forecast = test_fail_forecast
        self.test_fail_nowcast = test_fail_nowcast
        self.updtime = updtime
        self.timeout_netatmo = timeout_netatmo
        self.timeout_nowcast = timeout_nowcast
        self.timeout_forecast = timeout_forecast

        # Raspberry pi has 800x480 pixels
        # Set fullscreen
        self.pad = 1
        self._geom = '200x200+0+0'
        # self.master.geometry("{0}x{1}+0+0".format(
        #    self.master.winfo_screenwidth()-self.pad, self.master.winfo_screenheight()-self.pad))
        self.master.geometry("{0}x{1}+0+0".format(800, 480))
        self.master.bind('<Escape>', self.toggle_geom)
        self.master.bind("<Button-1>", self.change_location)
        self.master.bind("<Button-3>", self.quit)
        self.master.wm_attributes('-type', 'splash')

        master.configure(background='white')

        screenwidth = self.master.winfo_screenwidth()
        screenheight = self.master.winfo_screenheight()
        if debug:
            print(screenwidth)
            print(screenheight)

        self.times = []
        self.dts = []
        self.indoor_station = None
        self.netatmo_updated = None
        self.indoor_temp = None
        self.indoor_pressure = None
        self.indoor_co2 = None
        self.outdoor_station = None
        self.netatmo_outdoor_updated = None
        self.outdoor_temp = None
        self.outdoor_humidity = None
        self.rain1h = None

        self.vars = ["temperature", "windDirection", "windSpeed", "windGust",
                     "areaMaxWindSpeed", "humidity", "pressure", "cloudiness",
                     "fog", "lowClouds", "mediumClouds", "highClouds", "temperatureProbability",
                     "windProbability", "dewpointTemperature"]

        self.netatmo = Canvas(self.master, bg="white", width=380, height=150)

        self.netatmo_outdoor = Canvas(self.master, bg="white", width=380, height=130)

        self.time1 = ''
        self.clock = Label(self.master, font=('times', 60, 'bold'), bg='white')

        my_dpi = 80
        sthisfig = Figure(figsize=(int(float(400)/float(my_dpi)), int(float(150)/float(my_dpi))), dpi=my_dpi)
        sthisfig.patch.set_facecolor('white')
        self.sthisplot = sthisfig.add_subplot(111)
        sthisplotcanvas = FigureCanvasTkAgg(sthisfig, master=self.master)
        sthisplotcanvas.draw()
        self.sthisplot.set_visible(False)

        self.bottomfig = Figure(figsize=(int(float(800)/float(my_dpi)), int(float(200)/float(my_dpi))), dpi=my_dpi)
        self.bottomfig.patch.set_facecolor('white')
        gs = gridspec.GridSpec(1, 2, width_ratios=[1, 3])
        self.nowcast = self.bottomfig.add_subplot(gs[0])

        self.forecast = self.bottomfig.add_subplot(gs[1])

        # a tk.DrawingArea
        self.bottomplots = FigureCanvasTkAgg(self.bottomfig, master=self.master)
        self.bottomplots.draw()

        self.netatmo.grid(row=0, column=0)
        sthisplotcanvas.get_tk_widget().grid(row=0, column=1)
        sthisplotcanvas._tkcanvas.grid(row=0, column=1)
        self.netatmo_outdoor.grid(row=1, column=0)
        self.clock.grid(row=1, column=1)
        self.bottomplots.get_tk_widget().grid(row=2, columnspan=2)
        self.bottomplots._tkcanvas.grid(row=2, columnspan=2)

        self.master.grid_columnconfigure(0, weight=1, uniform="group1")
        self.master.grid_columnconfigure(1, weight=1, uniform="group1")
        self.master.grid_rowconfigure(0, weight=1)

        self.test_increase = 0
        self.update()  # start the update loop

    def quit(self, event):
        Frame.quit(self)

    def change_location(self, event):
        self.loc_index = self.loc_index + 1
        if self.loc_index >= len(self.locations):
            self.loc_index = 0
        self.location = self.locations[self.loc_index]

        if self.debug:
            print("Change location")
            self.location.print_location()

        # Clear canvas elements
        if hasattr(self, "indoor_station"):
            self.netatmo.delete(self.indoor_station)
        if hasattr(self, "netatmo_updated"):
            self.netatmo.delete(self.netatmo_updated)
        if hasattr(self, "indoor_temp"):
            self.netatmo.delete(self.indoor_temp)
        if hasattr(self, "indoor_pressure"):
            self.netatmo.delete(self.indoor_pressure)
        if hasattr(self, "indoor_co2"):
            self.netatmo.delete(self.indoor_co2)
        if hasattr(self, "outdoor_station"):
            self.netatmo_outdoor.delete(self.outdoor_station)
        if hasattr(self, "netatmo_outdoor_updated"):
            self.netatmo_outdoor.delete(self.netatmo_outdoor_updated)
        if hasattr(self, "outdoor_temp"):
            self.netatmo_outdoor.delete(self.outdoor_temp)
        if hasattr(self, "outdoor_humidity"):
            self.netatmo_outdoor.delete(self.outdoor_humidity)
        if hasattr(self, "rain1h"):
            self.netatmo_outdoor.delete(self.rain1h)
        if hasattr(self, "nowcast"):
            self.nowcast.clear()
        if hasattr(self, "forecast"):
            self.forecast.clear()

        self.update()

    def toggle_geom(self, event):
        geom = self.master.winfo_geometry()
        if debug:
            print(geom, self._geom)
        self.master.geometry(self._geom)
        self._geom = geom

    def find_x_center(self, canvas, item):
        if debug:
            print(self.master.winfo_screenwidth() - self.pad)
        return (self.master.winfo_screenwidth() - self.pad) / 8

    def set_time_dimension(self, now, hours):
        self.times = []
        self.dts = []
        for t in range(0, hours):
            self.times.append(t)
            self.dts.append(now+timedelta(hours=t))

    def get_time_indices(self, dts, values_in=None):
        if values_in is not None and len(dts) != len(values_in):
            raise Exception("Mismatch in length: "+str(len(dts))+" != "+str(len(values_in)))

        indices = []
        values = []
        j = 0
        for dt in dts:
            for t in range(0, len(self.dts)):
                if dt == self.dts[t]:
                    indices.append(t)
                    if values_in is not None:
                        values.append(values_in[j] + self.test_increase)
            j = j + 1

        indices = np.asarray(indices)
        values = np.asarray(values)
        if values_in is not None:
            return indices, values
        else:
            return indices

    def update(self):

        # self.testIncrease=self.testIncrease-1
        if self.debug_update:
            print(datetime.now())
        self.tick()
        self.days = 5
        now = datetime.utcnow()
        now = now.replace(second=0, minute=0, microsecond=0)
        self.set_time_dimension(now, self.days*24)

        ###################################################################
        # Netatmo
        ###################################################################
        indoor_values = None
        outdoor_values = None
        rain_values = None
        test_fail_netatmo = False
        if self.debug_update and self.test_fail_netatmo:
            test_fail_netatmo = True
        try:
            indoor_values, outdoor_values, rain_values = get_measurement(self.location,
                                                                         debug=self.debug_netatmo,
                                                                         test_fail_netatmo=test_fail_netatmo)
        except:
            pass

        if indoor_values is not None and outdoor_values is not None and rain_values is not None:
            # if self.debug:
            #    print(indoor_values)
            #    print(outdoor_values)
            #    print(rain_values)

            # Inddor
            label = str(self.location.name) + " (inne)"
            len_label = len(label)
            x_pos = int((len_label * 8) * 0.5)
            if hasattr(self, "indoor_station"):
                self.netatmo.delete(self.indoor_station)
            self.indoor_station = self.netatmo.create_text(x_pos, 12, text=label, font=('verdana', 10))

            updated = "Oppdatert: NA"
            if "time_utc" in indoor_values:
                updated = "Oppdatert: " + datetime.fromtimestamp(indoor_values["time_utc"],
                                                                 pytz.timezone('Europe/Amsterdam')).strftime("%H:%M")
            if hasattr(self, 'netatmo_updated'):
                self.netatmo.delete(self.netatmo_updated)
            self.netatmo_updated = self.netatmo.create_text(300, 10, text=updated, font=('verdana', 10))

            # Temp
            if hasattr(self, 'indoor_temp'):
                self.netatmo.delete(self.indoor_temp)
            temp = "NA"
            if "Temperature" in indoor_values:
                temp = indoor_values["Temperature"]
            self.indoor_temp = self.netatmo.create_text(60, 40, text=self.temp_text(temp), fill=self.temp_color(temp),
                                                        font=('verdana', 20))

            # Pressure
            if hasattr(self, 'indoor_pressure'):
                self.netatmo.delete(self.indoor_pressure)
            pres = "NA"
            if "Pressure" in indoor_values:
                pres = "{0:.0f}".format(round(float(indoor_values["Pressure"]), 0))+' mb'
            self.indoor_pressure = self.netatmo.create_text(45, 90, text=pres, fill="black", font=('verdana', 12))

            # CO2
            if hasattr(self, 'indoor_co2'):
                self.netatmo.delete(self.indoor_co2)
            co2 = "NA"
            if "CO2" in indoor_values:
                co2 = str(indoor_values["CO2"])
            self.indoor_co2 = self.netatmo.create_text(65, 120, text='co2: '+co2+'ppm', fill="black",
                                                       font=('verdana', 12))

            #######################
            # Outdoor
            #######################
            label = str(self.location.name) + " (ute)"
            len_label = len(label)
            x_pos = int((len_label * 8) * 0.5)

            if hasattr(self, "outdoor_station"):
                self.netatmo_outdoor.delete(self.outdoor_station)
            self.outdoor_station = self.netatmo_outdoor.create_text(x_pos, 12, text=label, font=('verdana', 10))

            updated = "Oppdatert: NA"
            if "time_utc" in outdoor_values:
                updated = "Oppdatert: " + datetime.fromtimestamp(outdoor_values["time_utc"],
                                                                 pytz.timezone('Europe/Amsterdam')).strftime("%H:%M")
            if hasattr(self, 'netatmo_outdoor_updated'):
                self.netatmo_outdoor.delete(self.netatmo_outdoor_updated)
            self.netatmo_outdoor_updated = self.netatmo_outdoor.create_text(300, 12, text=updated, font=('verdana', 10))

            if hasattr(self, 'outdoor_temp'):
                self.netatmo_outdoor.delete(self.outdoor_temp)
            temp = "NA"
            if "Temperature" in outdoor_values:
                temp = outdoor_values["Temperature"]
            self.outdoor_temp = self.netatmo_outdoor.create_text(235, 75, text=self.temp_text(temp),
                                                                 fill=self.temp_color(temp),
                                                                 font=('verdana', 60))

            # Humidity
            if hasattr(self, 'outdoor_humidity'):
                self.netatmo_outdoor.delete(self.outdoor_humidity)
            hum = "NA"
            if "Humidity" in outdoor_values:
                hum = str(outdoor_values["Humidity"])
            self.outdoor_humidity = self.netatmo_outdoor.create_text(40, 90, text=hum + '%',
                                                                     fill="black", font=('verdana', 15))
            # Rain
            if hasattr(self, 'rain1h'):
                self.netatmo_outdoor.delete(self.rain1h)
            rain1h = ""
            if "sum_rain_1" in rain_values:
                rain1h = "{0:.1f}".format(round(float(rain_values["sum_rain_1"]), 1))+'mm/h'
            self.rain1h = self.netatmo_outdoor.create_text(60, 120, text=rain1h, font=('verdana', 15))
            if self.debug_update:
                print("Updated netatmo")
        else:
            print("Can not update netatmo")

        ###########################################################
        # Nowcast
        ###########################################################
        minutes = None
        values = None
        test_fail_nowcast = False
        if self.debug_update and self.test_fail_nowcast:
            test_fail_nowcast = True
        try:
            minutes, values = get_nowcast(self.location, debug=self.debug_nowcast,
                                          timeout_nowcast=self.timeout_nowcast,
                                          test_fail_nowcast=test_fail_nowcast)
        except:
            pass

        self.nowcast.clear()
        if minutes is not None and values is not None:
            ticks = [0, 15, 30, 45, 60, 75, 90]
            self.nowcast.axes.get_xaxis().set_ticks(ticks)
            if len(values) > 0:
                lines = self.nowcast.plot(minutes, values)
                lines[0].set_ydata(values)
                self.nowcast.set_ylim(bottom=0., top=max(values)+0.2)

                if max(values) > 0:
                    self.nowcast.fill_between(minutes, 0, values)
            if self.debug_update:
                print("Updated nowcast")
        else:
            print("Could not update nowcast")

        ###############################################################################
        # Location forecast
        ###############################################################################

        acc_vars1h = None
        other_vars = None
        test_fail_forecast = False
        if self.debug_update and self.test_fail_forecast:
            test_fail_forecast = True
        try:
            acc_vars1h, other_vars, acc_vars2h, acc_vars3h, acc_vars6h = \
                get_location_forecast(self.location, self.vars,
                                      debug=self.debug_forecast,
                                      timeout_forecast=self.timeout_forecast,
                                      test_fail_forecast=test_fail_forecast)
        except:
            pass

        if acc_vars1h is not None and other_vars is not None:
            # if self.debug:
            #    print(acc_vars1h)
            precipitation = []
            times = []
            var = "precipitation"
            for time in sorted(acc_vars1h):
                # if self.debug:
                #    print(time, var, acc_vars1h[time])
                times.append(time)
                precipitation.append(acc_vars1h[time][var]["value"])

            prec_indices, precipitation = self.get_time_indices(times, precipitation)
            temperature = []
            windspeed = []
            times = []
            for time in sorted(other_vars):
                var = "temperature"
                times.append(time)
                temperature.append(float(other_vars[time][var]["value"]))
                var = "windSpeed"
                windspeed.append(float(other_vars[time][var]["mps"]))

            temp_indices, temperature = self.get_time_indices(times, temperature)
            wind_indices, windspeed = self.get_time_indices(times, windspeed)

            c = ['r' if t > 0 else 'b' for t in temperature]
            lines = [((x0, y0), (x1, y1)) for x0, y0, x1, y1 in zip(temp_indices[:-1], temperature[:-1],
                                                                    temp_indices[1:],
                                                                    temperature[1:])]
            colored_lines = LineCollection(lines, colors=c, linewidths=(2,))
            self.forecast.clear()
            self.forecast.set_ylim(bottom=np.min(temperature) - 1, top=np.max(temperature) + 1)
            self.forecast.add_collection(colored_lines)
            if not hasattr(self, "axP"):
                self.axP = self.forecast.twinx()
            self.axP.clear()
            self.axP.bar(prec_indices, height=precipitation, width=1)
            self.axP.set_ylim(bottom=0, top=max(np.maximum(precipitation, 2)))
            line_wind = self.forecast.plot(wind_indices, windspeed, color="grey")
            today = now.replace(hour=0, second=0, minute=0, microsecond=0)
            ticks = []
            labels = []
            for d in range(1, self.days+1):
                ticks.append(today+timedelta(days=d))
                labels.append((today+timedelta(days=d)).strftime("%d/%m"))

            tick_positions = self.get_time_indices(ticks)
            self.forecast.axes.set_xticks(ticks=tick_positions, minor=False)
            self.forecast.axes.set_xticklabels(labels, fontdict=None, minor=False)
            line_wind[0].set_ydata(windspeed)
            if self.debug_update:
                print("Updated forecast")

        else:
            print("Can not update location forecast")

        self.bottomplots.draw_idle()
        if self.debug_update:
            if not self.debug_update2:
                self.debug_update = False
        else:
            if self.debug_update2:
                self.debug_update = True

        if self.debug_update2:
            self.debug_update2 = False
        self.after(self.updtime, self.update)  # ask the mainloop to call this method again in ms

    def tick(self):
        # get the current local time from the PC
        time2 = strftime('%H:%M:%S')
        # if time string has changed, update it
        if time2 != self.time1:
            time1 = time2
            self.clock.config(text=time2)
        # calls itself every 200 milliseconds
        # to update the time display as needed
        # could use >200 ms, but display gets jerky
        self.clock.after(200, self.tick)

    @staticmethod
    def temp_color(value):
        color = "red"
        if value != "NA" and value < 0:
            color = "blue"
        return color

    @staticmethod
    def temp_text(value):
        if value != "NA":
            # txt = "%s °C" % (value)
            txt = "%s" % value
        else:
            txt = "NA"
        return txt