To receive notifications about scheduled maintenance, please subscribe to the mailing-list gitlab-operations@sympa.ethz.ch. You can subscribe to the mailing-list at https://sympa.ethz.ch

Commit bf7e6b9d authored by holukas's avatar holukas
Browse files

extending top menu, code optimizations

parent d921ac73
This diff is collapsed.
......@@ -447,3 +447,9 @@ Kept here so it can be found with search function.
# self.eef_df[filter].index
# print("x")
# def convert_date_to_datetime(self, date):
# """Converts date to datetime by adding hour and minute info"""
# time = dt.datetime.min.time()
# datetime = dt.datetime.combine(date, time)
# return datetime
......@@ -9,6 +9,7 @@ from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from gui import gui_building_blocks, gui_elements
from gui.top_menu import TopMenu
from logger import QTextEditLogger
from modboxes import controls as modbox_cn
from modboxes.Analyses import Analyses_gui as modbox_an
......@@ -22,83 +23,6 @@ from modboxes.Pipelines import Pipelines_gui as modbox_pn
from modboxes.QualityControl import QualityControl_gui as modbox_qc
class TopMenu:
""" Create dropdown menu at the top. """
def __init__(self, main_win, ctx):
self.ctx = ctx
self.mainMenu = main_win.menuBar()
self.btn_fileImportSettings, self.btn_fileAddFile, self.btn_fileLoadNewFile, self.btn_fileOutputDir = \
self.file()
self.btn_plotsCorrMatrix, self.btn_plotsHexbins, self.btn_plotsMultiPanel, self.btn_plotsScatter, \
self.btn_plotsUstarThresholdsFXN, self.btn_plotsWindSectors, self.btn_plotsCumulative, self.btn_plotsHeatmap = \
self.plots()
self.btn_analysesUstarDetectionAuto, self.btn_analysesAggregator, self.btn_analysesNetGHGBalance = \
self.analyses()
self.btn_gapfillingMDS, self.btn_gapfillingRandomForest = \
self.gap_filling()
def file(self):
""" File menu """
menu = self.mainMenu.addMenu('&File')
btn_fileLoadNewFile = gui_elements.menu_action(txt='Load New File ...', menu=menu,
icon=False)
btn_fileAddFile = gui_elements.menu_action(txt='Add File ...', menu=menu,
icon=self.ctx.icon_btn_menu_add)
btn_fileImportSettings = gui_elements.menu_action(txt='File Import Settings ...', menu=menu,
icon=self.ctx.icon_btn_menu_settings)
btn_fileOutputDir = gui_elements.menu_action(txt='Output Directory ...', menu=menu,
icon=self.ctx.icon_btn_menu_settings)
return btn_fileImportSettings, btn_fileAddFile, btn_fileLoadNewFile, btn_fileOutputDir
def plots(self):
""" Plots menu """
menu = self.mainMenu.addMenu('Plots')
btn_plotsCorrMatrix = gui_elements.menu_action(txt='Correlation Matrix', menu=menu,
icon=self.ctx.icon_open_in_new_tab)
btn_plotsCumulative = gui_elements.menu_action(txt='Cumulative', menu=menu,
icon=self.ctx.icon_open_in_new_tab)
btn_plotsHeatmap = gui_elements.menu_action(txt='Heatmap', menu=menu,
icon=self.ctx.icon_open_in_new_tab)
btn_plotsHexbins = gui_elements.menu_action(txt='Hexbins', menu=menu,
icon=self.ctx.icon_open_in_new_tab)
btn_plotsMultiPanel = gui_elements.menu_action(txt='Multipanel', menu=menu,
icon=self.ctx.icon_open_in_new_tab)
btn_plotsScatter = gui_elements.menu_action(txt='Scatter', menu=menu,
icon=self.ctx.icon_open_in_new_tab)
btn_plotsUstarThresholdsFXN = gui_elements.menu_action(txt='u* Thresholds (FXN)', menu=menu,
icon=self.ctx.icon_open_in_new_tab)
btn_plotsWindSectors = gui_elements.menu_action(txt='Wind Sectors', menu=menu,
icon=self.ctx.icon_open_in_new_tab)
return btn_plotsCorrMatrix, btn_plotsHexbins, btn_plotsMultiPanel, btn_plotsScatter, \
btn_plotsUstarThresholdsFXN, btn_plotsWindSectors, btn_plotsCumulative, btn_plotsHeatmap
def analyses(self):
menu = self.mainMenu.addMenu('Analyses')
btn_analysesAggregator = gui_elements.menu_action(txt='Aggregator', menu=menu,
icon=self.ctx.icon_open_in_new_tab)
btn_analysesNetGHGBalance = gui_elements.menu_action(txt='Net GHG Balance', menu=menu,
icon=self.ctx.icon_open_in_new_tab)
btn_analysesUstarDetectionAuto = gui_elements.menu_action(txt='Ustar Threshold Detection', menu=menu,
icon=self.ctx.icon_open_in_new_tab)
return btn_analysesUstarDetectionAuto, btn_analysesAggregator, btn_analysesNetGHGBalance
def gap_filling(self):
menu = self.mainMenu.addMenu('Gap-filling')
btn_gapfillingMDS = gui_elements.menu_action(txt='Marginal Distribution Sampling (MDS)',
menu=menu, icon=self.ctx.icon_open_in_new_tab)
btn_gapfillingRandomForest = gui_elements.menu_action(txt='Random Forest',
menu=menu, icon=self.ctx.icon_open_in_new_tab)
return btn_gapfillingMDS, btn_gapfillingRandomForest
# def get(self):
# return self.mainMenu
class Ui_MainWindow(object):
"""
Prepares the raw gui, i.e. the canvas that is filled with content later.
......
# ==========================================================
#
# Building blocks for the gui
#
#
#
# ==========================================================
"""
General GUI building blocks.
"""
from PyQt5 import QtCore as qtc
from PyQt5 import QtWidgets as qw
from PyQt5.QtGui import QIcon
......@@ -44,37 +41,32 @@ class SelectFileTypeSettingsFile(qw.QDialog):
return layout_left, layout_right
# class SettingsWindow(qw.QDialog):
# def setupUi(self, SettingsWindow, win_title):
# SettingsWindow.setAccessibleName('SettingsWindow')
#
# # # Load external CSS file
# # dir_start = pathlib.Path(__file__) # Auto-detect where template_main.py is located.
# # dir_css = dir_start.parents[3] / 'main' / 'resources' / 'base' # One folder up
# # # path_gui = Path('gui')
# # with open(dir_css / 'gui_light.css', "r") as fh:
# # SettingsWindow.setStyleSheet(fh.read())
# # # with open(path_gui / 'gui_light.css', "r") as fh:
# # # SettingsWindow.setStyleSheet(fh.read())
#
# SettingsWindow.setWindowTitle(win_title)
# SettingsWindow.setWindowIcon(QIcon('gui/Icons/python_icon.png'))
# SettingsWindow.resize(1000, 600)
# SettingsWindow.setContentsMargins(0, 0, 0, 0)
#
# # CONTAINER (lyt_CategoryOptions)
# layout = qw.QGridLayout()
# layout.setContentsMargins(0, 0, 0, 0)
# layout.setSpacing(0)
# self.setLayout(layout)
# return layout
#
# # return SettingsWindow
# # self.CentralWidget = qw.QWidget(SettingsWindow)
# # self.CentralWidget.setObjectName("centralwidget")
# # self.CentralWidget.setAccessibleName('SettingsWindow')
# # self.CentralWidget.setContentsMargins(0, 0, 0, 0)
# # SettingsWindow.setCentralWidget(self.CentralWidget)
class SimpleSettingsWindow(qw.QDialog):
def setupUi(self, SimpleSettingsWindow, win_title, ctx):
SimpleSettingsWindow.setAccessibleName('')
# SimpleSettingsWindow.setWindowFlags(qtc.Qt.FramelessWindowHint)
SimpleSettingsWindow.setWindowTitle(win_title)
SimpleSettingsWindow.setWindowIcon(QIcon(ctx.icon_amp))
# SelectFileTypeSettingsFile.resize(1200, 800)
SimpleSettingsWindow.setContentsMargins(0, 0, 0, 0)
# Container layout
container_layout = qw.QHBoxLayout()
container_layout.setContentsMargins(0, 0, 0, 0)
container_layout.setSpacing(0)
self.setLayout(container_layout)
# Container frame
container_frame = qw.QFrame()
container_frame.setAccessibleName('SimpleSettingsWindowFrame')
container_frame.setContentsMargins(0, 0, 0, 0)
container_layout.addWidget(container_frame)
# Grid for fields
grid = qw.QGridLayout()
container_frame.setLayout(grid)
return grid
class CategoryOptions:
......
from gui import gui_elements
class TopMenu:
""" Create dropdown menu at the top. """
def __init__(self, main_win, ctx):
self.ctx = ctx
self.mainMenu = main_win.menuBar()
# File
self.btn_fileImportSettings, self.btn_fileAddFile, self.btn_fileLoadNewFile, self.btn_fileOutputDir = \
self.file()
# Plots
self.btn_plotsCorrMatrix, self.btn_plotsHexbins, self.btn_plotsMultiPanel, self.btn_plotsScatter, \
self.btn_plotsUstarThresholdsFXN, self.btn_plotsWindSectors, self.btn_plotsCumulative, self.btn_plotsHeatmap = \
self.plots()
# Analyses
self.btn_analysesUstarDetectionAuto, self.btn_analysesAggregator, self.btn_analysesNetGHGBalance = \
self.analyses()
# Gap-filling
self.btn_gapfillingMDS, self.btn_gapfillingRandomForest = \
self.gap_filling()
# Modifications
self.btn_modificationsLimitDatasetTimeRange, self.btn_modificationsAddPrefixSuffixToVariables, \
self.btn_modificationsCreateNewEvent = \
self.modifications()
# Export
self.btn_exportExportDataset = \
self.export()
def file(self):
""" File menu """
menu = self.mainMenu.addMenu('&File')
btn_fileLoadNewFile = gui_elements.menu_action(txt='Load New File ...', menu=menu,
icon=False)
btn_fileAddFile = gui_elements.menu_action(txt='Add File ...', menu=menu,
icon=self.ctx.icon_btn_menu_add)
btn_fileOutputDir = gui_elements.menu_action(txt='Output Directory ...', menu=menu,
icon=self.ctx.icon_btn_menu_settings)
btn_fileImportSettings = gui_elements.menu_action(txt='File Import Settings ...', menu=menu,
icon=self.ctx.icon_btn_menu_settings)
return btn_fileImportSettings, btn_fileAddFile, btn_fileLoadNewFile, btn_fileOutputDir
def plots(self):
""" Plots menu """
menu = self.mainMenu.addMenu('Plots')
btn_plotsCorrMatrix = gui_elements.menu_action(txt='Correlation Matrix', menu=menu,
icon=self.ctx.icon_open_in_new_tab)
btn_plotsCumulative = gui_elements.menu_action(txt='Cumulative', menu=menu,
icon=self.ctx.icon_open_in_new_tab)
btn_plotsHeatmap = gui_elements.menu_action(txt='Heatmap', menu=menu,
icon=self.ctx.icon_open_in_new_tab)
btn_plotsHexbins = gui_elements.menu_action(txt='Hexbins', menu=menu,
icon=self.ctx.icon_open_in_new_tab)
btn_plotsMultiPanel = gui_elements.menu_action(txt='Multipanel', menu=menu,
icon=self.ctx.icon_open_in_new_tab)
btn_plotsScatter = gui_elements.menu_action(txt='Scatter', menu=menu,
icon=self.ctx.icon_open_in_new_tab)
btn_plotsUstarThresholdsFXN = gui_elements.menu_action(txt='u* Thresholds (FXN)', menu=menu,
icon=self.ctx.icon_open_in_new_tab)
btn_plotsWindSectors = gui_elements.menu_action(txt='Wind Sectors', menu=menu,
icon=self.ctx.icon_open_in_new_tab)
return btn_plotsCorrMatrix, btn_plotsHexbins, btn_plotsMultiPanel, btn_plotsScatter, \
btn_plotsUstarThresholdsFXN, btn_plotsWindSectors, btn_plotsCumulative, btn_plotsHeatmap
def analyses(self):
menu = self.mainMenu.addMenu('Analyses')
btn_analysesAggregator = gui_elements.menu_action(txt='Aggregator', menu=menu,
icon=self.ctx.icon_open_in_new_tab)
btn_analysesNetGHGBalance = gui_elements.menu_action(txt='Net GHG Balance', menu=menu,
icon=self.ctx.icon_open_in_new_tab)
btn_analysesUstarDetectionAuto = gui_elements.menu_action(txt='Ustar Threshold Detection', menu=menu,
icon=self.ctx.icon_open_in_new_tab)
return btn_analysesUstarDetectionAuto, btn_analysesAggregator, btn_analysesNetGHGBalance
def gap_filling(self):
menu = self.mainMenu.addMenu('Gap-filling')
btn_gapfillingMDS = gui_elements.menu_action(txt='Marginal Distribution Sampling (MDS)',
menu=menu, icon=self.ctx.icon_open_in_new_tab)
btn_gapfillingRandomForest = gui_elements.menu_action(txt='Random Forest',
menu=menu, icon=self.ctx.icon_open_in_new_tab)
return btn_gapfillingMDS, btn_gapfillingRandomForest
def modifications(self):
menu = self.mainMenu.addMenu('Modifications')
btn_modificationsAddPrefixSuffixToVariables = gui_elements.menu_action(txt='Add Prefix / Suffix To Variables',
menu=menu,
icon=self.ctx.icon_btn_new_window)
btn_modificationsCreateNewEvent = gui_elements.menu_action(txt='Create New Event',
menu=menu, icon=self.ctx.icon_btn_new_window)
btn_modificationsLimitDatasetTimeRange = gui_elements.menu_action(txt='Limit Dataset Time Range',
menu=menu, icon=self.ctx.icon_btn_new_window)
return btn_modificationsLimitDatasetTimeRange, btn_modificationsAddPrefixSuffixToVariables, \
btn_modificationsCreateNewEvent
def export(self):
menu = self.mainMenu.addMenu('Export')
btn_exportExportDataset = gui_elements.menu_action(txt='Export Dataset',
menu=menu,
icon=self.ctx.icon_btn_new_window)
return btn_exportExportDataset
# def get(self):
# return self.mainMenu
from logger import log
import datetime as dt
import fnmatch
import os
......@@ -88,45 +89,94 @@ def parse_events_file(filepath, settings_dict):
return data_df
def parse_csv_file(filepath, settings_dict):
def compare_len_header_vs_data(filepath, skip_rows_list, header_rows_list):
"""
Read file into df.
Check whether there are more data columns than given in the header.
If not checked, this would results in an error when reading the csv file
with .read_csv, because the method expects an equal number of header and
data columns. If this check is True, then the difference between the length
of the first data row and the length of the header row(s) can be used to
automatically generate names for the missing header columns.
"""
# Check number of columns of the first data row after the header part
skip_num_lines = len(header_rows_list) + len(skip_rows_list)
first_data_row_df = pd.read_csv(filepath, skiprows=skip_num_lines,
header=None, nrows=1)
len_data_cols = first_data_row_df.columns.size
# Check number of columns of the header part
header_cols_df = pd.read_csv(filepath, skiprows=skip_rows_list,
header=header_rows_list, nrows=0)
len_header_cols = header_cols_df.columns.size
# Check if there are more data columns than header columns
if len_data_cols > len_header_cols:
more_data_cols_than_header_cols = True
num_missing_header_cols = len_data_cols - len_header_cols
else:
more_data_cols_than_header_cols = False
num_missing_header_cols = 0
# Column settings for parsing dates / times correctly
parsed_index_col = ('index', '[parsed]')
parse_dates = settings_dict['TIMESTAMP_INDEX_COLUMN']
parse_dates = {parsed_index_col: parse_dates}
# Generate missing header columns if necessary
header_cols_list = header_cols_df.columns.to_list()
generated_missing_header_cols_list = []
sfx = make_timestamp_microsec_suffix()
if more_data_cols_than_header_cols:
for m in list(range(1, num_missing_header_cols + 1)):
missing_col = (f'unknown_{m}-{sfx}', '[-unknown-]')
generated_missing_header_cols_list.append(missing_col)
header_cols_list.append(missing_col)
# if settings_dict['TIMESTAMP_DATE_AND_TIME_IN_SEPARATE_COLUMNS'] == 'yes':
#
# separate_cols = [settings_dict['TIMESTAMP_DATE_COLUMN_NAME'],
# settings_dict['TIMESTAMP_TIME_COLUMN_NAME']]
#
# parse_dates = {parsed_index_col: separate_cols}
# else:
# parse_dates = {parsed_index_col: [0]}
return more_data_cols_than_header_cols, num_missing_header_cols, header_cols_list,generated_missing_header_cols_list
def parse_csv_file(filepath, settings_dict):
""" Read file into df. """
# In case there is only one header row, use integer instead if list as parsing arg
# data_header_rows = 0 if len(settings_dict['DATA_HEADER_ROWS']) == 1 else settings_dict['DATA_HEADER_ROWS']
# Check data
# ----------
more_data_cols_than_header_cols, num_missing_header_cols, header_cols_list,generated_missing_header_cols_list = \
compare_len_header_vs_data(filepath=filepath,
skip_rows_list=settings_dict['DATA_SKIP_ROWS'],
header_rows_list=settings_dict['DATA_HEADER_ROWS'])
# Read data file
# --------------
parse = lambda x: dt.datetime.strptime(x, settings_dict['TIMESTAMP_DATETIME_FORMAT'])
# Column settings for parsing dates / times correctly
parsed_index_col = ('index', '[parsed]')
parse_dates = settings_dict['TIMESTAMP_INDEX_COLUMN']
parse_dates = {parsed_index_col: parse_dates}
date_parser = lambda x: dt.datetime.strptime(x, settings_dict['TIMESTAMP_DATETIME_FORMAT'])
data_df = pd.read_csv(filepath,
skiprows=settings_dict['DATA_SKIP_ROWS'],
header=settings_dict['DATA_HEADER_ROWS'],
skiprows=[0, 1, 2],
header=None,
names=header_cols_list,
na_values=settings_dict['DATA_NA_VALUES'],
encoding='utf-8',
delimiter=settings_dict['DATA_DELIMITER'],
mangle_dupe_cols=True,
keep_date_col=False,
parse_dates=parse_dates,
date_parser=parse,
date_parser=date_parser,
index_col=None,
dtype=None)
dtype=None,
engine='python')
# data_df = pd.read_csv(filepath,
# skiprows=settings_dict['DATA_SKIP_ROWS'],
# header=settings_dict['DATA_HEADER_ROWS'],
# na_values=settings_dict['DATA_NA_VALUES'],
# encoding='utf-8',
# delimiter=settings_dict['DATA_DELIMITER'],
# mangle_dupe_cols=True,
# keep_date_col=False,
# parse_dates=parse_dates,
# date_parser=date_parser,
# index_col=None,
# dtype=None,
# engine='python')
standardize_index(df=data_df, settings_dict=settings_dict)
......@@ -134,7 +184,7 @@ def parse_csv_file(filepath, settings_dict):
if len(settings_dict['DATA_HEADER_ROWS']) == 1:
data_df = add_second_header_row(df=data_df)
return data_df
return data_df, generated_missing_header_cols_list
def add_second_header_row(df):
......@@ -231,7 +281,7 @@ def read_selected_data_file(filepath, settings_dict):
filepath, dir_temp_unzipped = unzip_file(filepath=filepath)
# Data
data_df = parse_csv_file(filepath=filepath, settings_dict=settings_dict)
data_df, generated_missing_header_cols_list = parse_csv_file(filepath=filepath, settings_dict=settings_dict)
# SANITIZE
# --------
......@@ -268,7 +318,7 @@ def read_selected_data_file(filepath, settings_dict):
# -------------------
pass
return data_df
return data_df, generated_missing_header_cols_list
def downsample_data(df, freq, max_freq):
......@@ -648,13 +698,14 @@ def resample_df(df, freq_str, agg_method, min_vals, out_timestamp_convention, to
# TIMESTAMP CONVENTION
# --------------------
agg_df, timestamp_info_df = timestamp_convention(df=agg_df, out_timestamp_convention=out_timestamp_convention,
to_duration=to_freq_duration, to_freq=to_freq,
timestamp_shows_start=timestamp_shows_start)
agg_df.index = pd.to_datetime(agg_df.index)
return agg_df, timestamp_info_df
def timestamp_convention(df, out_timestamp_convention, to_duration, to_freq, timestamp_shows_start):
def timestamp_convention(df, out_timestamp_convention, timestamp_shows_start):
original_cols = df.columns
df.index = pd.to_datetime(df.index)
......@@ -819,6 +870,7 @@ def check_df_available_records_aux_for_measured_gaps(df, gap_locations):
# check_df = check_df.dropna(subset=collist) # subset = list of column names to consider for nan values
return available_records
def make_timestamp_suffix():
now_time_dt = dt.datetime.now()
now_time_str = now_time_dt.strftime("%Y%m%d%H%M%S")
......@@ -826,6 +878,13 @@ def make_timestamp_suffix():
# log(name=make_run_id.__name__, dict={'run id': run_id}, highlight=False)
return run_id
def make_timestamp_microsec_suffix():
now_time_dt = dt.datetime.now()
now_time_str = now_time_dt.strftime("%H%M%S%f")
run_id = f'{now_time_str}'
# log(name=make_run_id.__name__, dict={'run id': run_id}, highlight=False)
return run_id
# def insert_index_as_col(df):
# # CSV files are exported w/o the row index
# # Before export, a new col is inserted that contains the datetime info
......
......@@ -13,6 +13,9 @@ def load(file, ctx):
elif file == 'EddyProFullOutput_30T':
settings_dict = SelectFileTypeSettings.read_settings_from_file(filepath=ctx.filetype_EddyProFullOutput_30T)
initial_data = ctx.file_EddyProFullOutput_30T
elif file == 'FluxnetFullSet_30T':
settings_dict = SelectFileTypeSettings.read_settings_from_file(filepath=ctx.filetype_FluxnetFullSet_30T)
initial_data = ctx.file_FluxnetFullSet_30T
elif file == 'MeteoEFDC6_30T':
settings_dict = SelectFileTypeSettings.read_settings_from_file(filepath=ctx.filetype_MeteoEFDC6_30T)
initial_data = ctx.file_MeteoEFDC6_30T
......
This diff is collapsed.
......@@ -69,10 +69,10 @@ class MakeNewTab:
(buttons, dropdowns) to the new tab.
"""
def __init__(self, TabWidget, data_df, colname_pretty_string, new_tab_id):
def __init__(self, TabWidget, data_df, col_list_pretty, new_tab_id):
self.TabWidget = TabWidget
self.colname_pretty_string = colname_pretty_string
self.colname_pretty_string = col_list_pretty
self.data_df = data_df
linebreak = '\n'
......
......@@ -33,7 +33,7 @@ class AddControls:
self.add_options(layout=opt_layout)
# Linear Interpolation
self.cr_ref_StorageCorrNEE_stackTab = 27
self.cr_ref_StorageCorrNEE_stackTab = 24
self.btn_cr_opt_StorageCorrection, \
self.drp_cr_ref_StorageCorrection_Flux, \
self.drp_cr_ref_StorageCorrection_StorageTerm, \
......
from gui import gui_elements
from modboxes.Export import SaveFigure
from modboxes.Export import VariablesToFiles
from modboxes.Export import ExportDataset
def connect(self, opt_tab_idx):
# (ModBox) Buttons
self.modbox_export.cat_btn_show_stack.clicked.connect((lambda: self.view_stk_option(tab_idx=opt_tab_idx)))
# Option: Export Variables To CSV File
self.modbox_export.VariablesToFiles.opt_btn.clicked.connect(
(lambda: self.view_stk_refinement(tab_idx=self.modbox_export.ex_ref_VarsToFiles_stackTab)))
self.modbox_export.VariablesToFiles.ref_btn_export.clicked.connect(lambda: self.call_ex_VarsToFiles())
# Option: Save Figure
self.modbox_export.SaveFigure.opt_btn.clicked.connect(
(lambda: self.view_stk_refinement(tab_idx=self.modbox_export.ex_ref_SaveFigure_stackTab)))
......@@ -43,13 +38,8 @@ class AddControls:
opt_frame, opt_layout = gui_elements.add_frame_grid()
self.add_options(layout=opt_layout)
# Variables to CSV
self.ex_ref_VarsToFiles_stackTab = 30
self.VariablesToFiles = VariablesToFiles.AddControls(opt_stack=stk_Options, opt_frame=opt_frame,
opt_layout=opt_layout, ref_stack=stk_Refinements)
# Save figure
self.ex_ref_SaveFigure_stackTab = 31
self.ex_ref_SaveFigure_stackTab = 27
self.SaveFigure = SaveFigure.AddControls(opt_stack=stk_Options, opt_frame=opt_frame,
opt_layout=opt_layout, ref_stack=stk_Refinements)
......@@ -73,4 +63,4 @@ class AddControls:
css_id='lbl_Header2',
row=0, col=0, rowspan=1, colspan=1)
layout.setRowStretch(4, 1)
layout.setRowStretch(3, 1)
......@@ -34,7 +34,7 @@ class AddControls:
self.add_options(layout=opt_layout)
# Linear Interpolation
self.hrt_ref_StationarityM98_stackTab = 28
self.hrt_ref_StationarityM98_stackTab = 25
self.btn_hrt_opt_StationarityM98, \
self.btn_hrt_ref_StationarityM98_showInNewTab = \
StationarityM98.AddControls(opt_stack=stk_Options, opt_frame=opt_frame, opt_layout=opt_layout,
......
import gui.gui_elements
import gui.plotfuncs
from gui import gui_elements
from gui import plotfuncs
from PyQt5 import QtWidgets as qw
from gui import gui_building_blocks, gui_elements
class AddControls():
"""
Creates the gui control elements and their handles for usage.
"""
class DialogWindow(gui_building_blocks.SimpleSettingsWindow):
""" Limit dataset to selected time range. """
def __init__(self, opt_stack, opt_frame, opt_layout, ref_stack):
self.opt_stack = opt_stack
self.opt_frame = opt_frame
self.opt_layout = opt_layout
self.ref_stack