Commit a806e954 authored by Michael Rudolf's avatar Michael Rudolf Committed by Michael Rudolf
Browse files

Basic interface RSTpicking (WIP).

Will allow to change parameters and easier opening of files.
parent ba54ecbb
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
'''
RST_pick_GUI.py
GUI based approach for RSTpicking
__AUTHOR__: Michael Rudolf
__DATE__: 20-Feb-2019
'''
import configparser
import tkinter as tk
from tkinter import filedialog
from tkinter import messagebox
import re
import os
import logging
log = logging.getLogger()
log.setLevel(logging.INFO)
class RST_pick_GUI(tk.Tk):
"""Main Window for the RST Picking"""
def __init__(self, parent):
tk.Tk.__init__(self, parent)
# == VARIABLES
self.parent = parent
self.projectname = tk.StringVar()
self.path_in = tk.StringVar()
self.path_out = tk.StringVar()
self.path_cfg = tk.StringVar()
self.plot_ts = tk.IntVar()
self.save_ts = tk.IntVar()
self.rst = tk.IntVar()
self.cfg = configparser.ConfigParser()
self.path_cfg.set('default.ini')
self.params = dict()
# Initialize Object
self.initalize()
def initalize(self):
# Read or create config and set entries from config
self.refresh_entries_from_cfg()
# == WIDGETS and INTERFACE ==
self.grid()
# Project name
self.label_projname = tk.Label(self,
text='Project:',
anchor='e',
width=20)
self.label_projname.grid(column=0, row=0, sticky='EW')
self.entry_projname = tk.Entry(self,
textvariable=self.projectname)
self.entry_projname.grid(column=1, row=0, sticky='EW')
# Input path
self.label_input = tk.Label(self,
text='Input Folder:',
anchor='e')
self.label_input.grid(column=0, row=1, sticky='EW')
self.entry_input = tk.Entry(self,
width=80,
textvariable=self.path_in)
self.entry_input.grid(column=1, row=1, sticky='EW')
self.button_input = tk.Button(self,
text='...')
self.button_input.grid(column=2, row=1)
self.button_input.bind('<ButtonRelease-1>', self.folder_browser)
# Output path
self.label_output = tk.Label(self,
text='Output Folder:',
anchor='e')
self.label_output.grid(column=0, row=2, sticky='EW')
self.entry_output = tk.Entry(self,
textvariable=self.path_out)
self.entry_output.grid(column=1, row=2, sticky='EW')
self.button_output = tk.Button(self,
text='...')
self.button_output.grid(column=2, row=2)
self.button_output.bind('<ButtonRelease-1>', self.folder_browser)
# Options
self.label_options = tk.Label(self,
text='Options:',
anchor='w',
font=('Helvetica', 12, 'bold'))
self.label_options.grid(column=0, row=3, columnspan=3, sticky='EW')
# Plot Data
self.opt_plot = tk.Checkbutton(self,
text='Plot time series',
anchor='w',
variable=self.plot_ts)
self.opt_plot.grid(column=0, row=4, sticky='EW')
# Pick Data
self.opt_pick = tk.Checkbutton(self,
text='Automatically pick data',
anchor='w',
variable=self.rst)
self.opt_pick.grid(column=0, row=5, sticky='EW')
# Save Data
self.opt_save = tk.Checkbutton(self,
text='Save picked data',
anchor='w',
variable=self.save_ts)
self.opt_save.grid(column=0, row=6, sticky='EW')
# More Options
self.button_options = tk.Button(self,
text='More options...')
self.button_options.grid(column=1, row=6, sticky='w')
self.button_options.bind('<ButtonRelease-1>', self.more_options)
# Start processing
self.button_start = tk.Button(self,
text='Start Processing',
padx=20)
self.button_start.grid(column=0, row=7, columnspan=3, sticky='w')
self.button_start.bind('<ButtonRelease-1>', self.start_processing)
self.make_dpi_aware()
def get_HWND_dpi(self):
# Detects high dpi displays and rescales gui in Windows
# Adapted from the user 'dingles at stack-overflow'
if os.name == "nt":
from ctypes import windll, pointer, wintypes
try:
windll.shcore.SetProcessDpiAwareness(1)
except Exception as e:
logging.info('High-DPI scaling failed')
pass # this will fail on Win Server and maybe early Windows
DPI100pc = 96 # DPI 96 is 100% scaling
DPI_type = 0
# MDT_EFFECTIVE_DPI = 0, MDT_ANGULAR_DPI = 1, MDT_RAW_DPI = 2
winH = wintypes.HWND(self.winfo_id())
monitorhandle = windll.user32.MonitorFromWindow(winH,
wintypes.DWORD(2))
# MONITOR_DEFAULTTONEAREST = 2
X = wintypes.UINT()
Y = wintypes.UINT()
try:
windll.shcore.GetDpiForMonitor(monitorhandle,
DPI_type,
pointer(X),
pointer(Y))
return X.value, Y.value, (X.value + Y.value) / (2 * DPI100pc)
except Exception:
logging.info('Assuming standard dpi scaling.')
return 96, 96, 1 # Assume standard Windows DPI & scaling
else:
return None, None, 1 # What to do for other OSs?
def TkGeometryScale(s, cvtfunc):
# Adapted from the user 'dingles at stack-overflow'
# format "WxH+X+Y"
patt = r"(?P<W>\d+)x(?P<H>\d+)\+(?P<X>\d+)\+(?P<Y>\d+)"
R = re.compile(patt).search(s)
G = str(cvtfunc(R.group("W"))) + "x"
G += str(cvtfunc(R.group("H"))) + "+"
G += str(cvtfunc(R.group("X"))) + "+"
G += str(cvtfunc(R.group("Y")))
return G
def make_dpi_aware(self):
# Adapted from the user 'dingles' at stack-overflow.com
self.DPI_X, self.DPI_Y, self.DPI_scaling = self.get_HWND_dpi()
self.TkScale = lambda v: int(float(v) * self.DPI_scaling)
self.TkGeometryScale = lambda s: self.TkGeometryScale(s, self.TkScale)
def resize_all_elements(self):
# Resizes all elements according to the DPI scaling of the window
pass
# == CALLBACKS ==
def folder_browser(self, event):
f_path = filedialog.askdirectory()
if event.widget._name == '!button': # Input path
self.entry_input.delete(0, 'end')
self.entry_input.insert(0, f_path + '/')
elif event.widget._name == '!button2': # Output path
self.entry_output.delete(0, 'end')
self.entry_output.insert(0, f_path + '/')
else:
print(event.widget._name)
def start_processing(self, event):
print('Start Processing')
for item in self.params.items():
print(item)
def more_options(self, event):
# Shows all additional options for the processing
opt_dlg = tk.Toplevel(self)
opt_dlg.wm_title('More Options')
opt_dlg.grid()
opt_dlg.label_options = tk.Label(opt_dlg,
text='Options:')
opt_dlg.label_options.grid(column=0, row=0, sticky='EW')
# Dynamically generate options based on config entries
for (i, item) in enumerate(self.cfg['parameters'].items()):
opt_dlg.label_item = tk.Label(opt_dlg,
text=item[0] + ':')
opt_dlg.label_item.grid(column=0, row=i + 1, sticky='e')
opt_dlg.entry_item = tk.Entry(opt_dlg,
textvariable=self.params[item[0]],
justify='right')
opt_dlg.entry_item.grid(column=1, row=i + 1, sticky='EW')
opt_dlg.label_unit = tk.Label(opt_dlg,
text=self.cfg['units'][item[0]])
opt_dlg.label_unit.grid(column=2, row=i + 1, sticky='w')
def refresh_entries_from_cfg(self):
# Try to see whether there is already a config
try:
self.cfg.read(self.path_cfg.get())
self.projectname.set(self.cfg['paths']['projectname'])
except Exception as e:
self.create_default_config()
print('created new config')
self.cfg.read(self.path_cfg.get())
# Set contents of fields and variables according to config
self.projectname.set(self.cfg['paths']['projectname'])
self.path_in.set(self.cfg['paths']['path_in'])
self.path_out.set(self.cfg['paths']['path_out'])
self.plot_ts.set(self.cfg.getint('options', 'plot_ts'))
self.save_ts.set(self.cfg.getint('options', 'plot_ts'))
self.rst.set(self.cfg.getint('options', 'plot_ts'))
# Read parameters and store them as a dictionary of StringVars
# This automatically links them to changes made in the Options dialog.
for item in self.cfg['parameters'].items():
self.params[item[0]] = tk.StringVar()
self.params[item[0]].set(item[1])
def create_default_config(self):
'''Creates default config in the given path'''
config = configparser.ConfigParser()
config['paths'] = {
'projectname': 'Example',
'path_in': 'input/',
'path_out': 'output/'
}
config['options'] = {
'plot_ts': 1, # if 1: data plotted, if 0: not
'save_ts': 1, # if 1: data stored in .txt files, if 0: not
'rst': 1, # if 1: automatic picking
}
config['parameters'] = {
'A': 0.022619, # area of shear zone (area of lid) (m^2)
'li': 0.0776, # inner lever (center cell-center shear zone)
'lo': 0.1250, # outer lever (center cell-hinge point)
'vel': 30, # shear velocity (mm/min)
'prec': 500, # precision for normal stress in filenames
'velnoise': 1e-2,
'stressnoise': 0.025,
'smoothwindow': 51 # define window for smooth shear stress curve
}
config['units'] = {
'A': 'm^2',
'li': 'm',
'lo': 'm',
'vel': 'mm/min',
'prec': 'Pa',
'velnoise': 'mm/min',
'stressnoise': 'Pa',
'smoothwindow': 'samples'
}
self.path_cfg.set('default.ini')
with open(self.path_cfg.get(), 'w') as f:
config.write(f)
if __name__ == '__main__':
app = RST_pick_GUI(None)
app.title('RSTpick GUI')
app.mainloop()
[paths]
projectname = Example
path_in = input/
path_out = output/
[options]
plot_ts = 1
save_ts = 1
rst = 1
[parameters]
a = 0.022619
li = 0.0776
lo = 0.125
vel = 30
prec = 500
velnoise = 0.01
stressnoise = 0.025
smoothwindow = 51
[units]
a = m^2
li = m
lo = m
vel = mm/min
prec = Pa
velnoise = mm/min
stressnoise = Pa
smoothwindow = samples
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment