From ec17cdb0534621b9ad26a8458559c7c682edcee2 Mon Sep 17 00:00:00 2001 From: Lan Dam <lan.dam@earthscope.org> Date: Fri, 25 Oct 2024 17:19:39 -0600 Subject: [PATCH] fontsize options --- sohstationviewer/conf/config_processor.py | 20 ++++ sohstationviewer/conf/constants.py | 9 +- .../documentation/32 _ Options Menu.help.md | 15 ++- .../options_menu/base_plot_font_size.jpg | Bin 0 -> 41130 bytes sohstationviewer/view/main_window.py | 25 +++++ .../multi_threaded_plotting_widget.py | 3 +- .../plotting/plotting_widget/plotting_axes.py | 92 +++++++++++++----- .../plotting_widget/plotting_widget.py | 13 ++- .../time_power_squared_widget.py | 14 ++- sohstationviewer/view/ui/main_ui.py | 38 +++++++- 10 files changed, 192 insertions(+), 37 deletions(-) create mode 100644 sohstationviewer/documentation/images/options_menu/base_plot_font_size.jpg diff --git a/sohstationviewer/conf/config_processor.py b/sohstationviewer/conf/config_processor.py index f427fd542..51b8f1a51 100644 --- a/sohstationviewer/conf/config_processor.py +++ b/sohstationviewer/conf/config_processor.py @@ -49,6 +49,7 @@ to_date = {QtCore.QDate.currentDate().toString("yyyy-MM-dd")} mp_color_mode = regular tps_color_mode = High date_mode = YYYY-MM-DD +base_plot_font_size = 6 add_mass_pos_to_soh = False ''' @@ -74,6 +75,7 @@ class ConfigProcessor: 'all_soh', 'from_date', 'to_date', 'mp_color_mode', 'tps_color_mode', 'date_mode', + 'base_plot_font_size', 'add_mass_pos_to_soh' # noqa: E131 } @@ -182,6 +184,19 @@ class ConfigProcessor: f'values: ' f'{", ".join(expected_date_modes)}.') + base_plot_font_size = self.config.get( + 'MiscOptions', 'base_plot_font_size') + expected_base_plot_font_sizes = [ + str(i) + for i in range(constants.MIN_FONTSIZE, constants.MAX_FONTSIZE + 1) + ] + + if base_plot_font_size not in expected_base_plot_font_sizes: + raise BadConfigError( + f'Font size can only have one of these ' + f'values: ' + f'{", ".join(expected_base_plot_font_sizes)}.') + def apply_config(self, window: MainWindow) -> None: """ Apply the loaded config to a window. @@ -263,6 +278,11 @@ class ConfigProcessor: elif date_mode == 'YYYY:DOY': window.yyyy_doy_action.trigger() + base_plot_font_size = window.config.get( + 'MiscOptions', 'base_plot_font_size') + window.base_plot_font_size_action_dict[ + int(base_plot_font_size)].trigger() + window.add_masspos_to_rt130_soh.setChecked( get_bool('MiscOptions', 'add_mass_pos_to_soh') ) diff --git a/sohstationviewer/conf/constants.py b/sohstationviewer/conf/constants.py index ffdec557d..a83be3650 100644 --- a/sohstationviewer/conf/constants.py +++ b/sohstationviewer/conf/constants.py @@ -84,7 +84,7 @@ BASIC_HEIGHT_IN = 0.15 # However, when there's no channel height_normalizing_factor can't be # calculated, so DEFAULT_SIZE_FACTOR_TO_NORMALIZE will be used to plot # timestamp. -DEFAULT_SIZE_FACTOR_TO_NORMALIZE = 0.02 +DEFAULT_SIZE_FACTOR_TO_NORMALIZE = 0.005 # vertical margin TOP_SPACE_SIZE_FACTOR = 3 BOT_SPACE_SIZE_FACTOR = 6 # to avoid hidden time bar partially @@ -98,7 +98,7 @@ PLOT_NONE_SIZE_FACTOR = 0.01 PLOT_SEPARATOR_SIZE_FACTOR = 1 TPS_SEPARATOR_SIZE_FACTOR = 2 # Size factor of TPS legend height -TPS_LEGEND_SIZE_FACTOR = 21 +TPS_LEGEND_SIZE_FACTOR = 15 # ============================================================================= # ================================= NORMALIZE ================================= # Normalized distance from left edge to the start of channel plots @@ -121,8 +121,9 @@ Z_ORDER = {'AXIS_SPINES': 0, 'CENTER_LINE': 1, 'LINE': 2, 'GAP': 3, 'DOT': 3, # Distance from 'Hour' label to timestamp bar HOUR_TO_TMBAR_D = 50 -# DEFAULT FONT SIZE -FONTSIZE = 6 +# Base font size range +MIN_FONTSIZE = 6 +MAX_FONTSIZE = 12 # day total limit for all tps channels to stay in one tab DAY_LIMIT_FOR_TPS_IN_ONE_TAB = 180 # about half of a year # ================================================================= # diff --git a/sohstationviewer/documentation/32 _ Options Menu.help.md b/sohstationviewer/documentation/32 _ Options Menu.help.md index 32988bd63..5259e6709 100644 --- a/sohstationviewer/documentation/32 _ Options Menu.help.md +++ b/sohstationviewer/documentation/32 _ Options Menu.help.md @@ -73,7 +73,7 @@ From, To dates. <br /> <br /> -<img alt="Date Format" src="images/options_menu/date_format.jpg" width="600" /> +<img alt="Date Format" src="images/options_menu/date_format.jpg" width="620" /> <br /> There are three options to select from: @@ -83,4 +83,15 @@ There are three options to select from: + YYYYMMMDD: Ex. 2023MAR01 + <br /> -<br /> \ No newline at end of file +<br /> + + +### Base Font Size + +Allow user to select the font size of texts displayed in the plotting. This +option has to be selected before reading data or replot data. + +<br /> +<br /> +<img alt="Base Plot Font Size" src="images/options_menu/base_plot_font_size.jpg" width="530" /> +<br /> diff --git a/sohstationviewer/documentation/images/options_menu/base_plot_font_size.jpg b/sohstationviewer/documentation/images/options_menu/base_plot_font_size.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7e67d3962dba333b5d503dd9e9da2e6acff3a434 GIT binary patch literal 41130 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 literal 0 HcmV?d00001 diff --git a/sohstationviewer/view/main_window.py b/sohstationviewer/view/main_window.py index 5fe5c6697..d33f02ecd 100755 --- a/sohstationviewer/view/main_window.py +++ b/sohstationviewer/view/main_window.py @@ -67,6 +67,16 @@ class MainWindow(QtWidgets.QMainWindow, UIMainWindow): super().__init__(parent) self.setup_ui(self) """ + vertical_ratio: ratio based selected font and min_font to spread out + layout vertically according to the selected font + """ + self.vertical_ratio: float = 1. + """ + fig_height_in_ratio: ratio based selected font and min_font to resize + plot's main_widget, figure and canvas vertically + """ + self.fig_height_in_ratio: float = 1 + """ dir_names: list of absolute paths of data sets """ self.list_of_dir: List[Path] = [] @@ -940,6 +950,9 @@ class MainWindow(QtWidgets.QMainWindow, UIMainWindow): self.clear_plots() if self.has_problem: return + font_ratio = self.base_plot_font_size / constants.MAX_FONTSIZE + self.vertical_ratio = 0.45 + font_ratio + self.fig_height_in_ratio = 2 * font_ratio self.is_plotting_soh = True self.plotting_widget.set_colors(self.color_mode) self.waveform_dlg.plotting_widget.set_colors(self.color_mode) @@ -1221,6 +1234,18 @@ class MainWindow(QtWidgets.QMainWindow, UIMainWindow): raise Exception('Something is very wrong. No date mode is chosen.' 'Please contact the software group.') self.config.set('MiscOptions', 'date_mode', date_mode) + + base_plot_font_size = None + for i in range(constants.MIN_FONTSIZE, constants.MAX_FONTSIZE + 1): + if self.base_plot_font_size_action_dict[i].isChecked(): + base_plot_font_size = i + break + if base_plot_font_size is None: + raise Exception('Something is very wrong. No base font size is ' + 'chosen. Please contact the software group.') + self.config.set('MiscOptions', 'base_plot_font_size', + str(base_plot_font_size)) + self.config.set('MiscOptions', 'add_mass_pos_to_soh', str(self.add_masspos_to_rt130_soh.isChecked())) with open(CONFIG_PATH, 'w+') as file: diff --git a/sohstationviewer/view/plotting/plotting_widget/multi_threaded_plotting_widget.py b/sohstationviewer/view/plotting/plotting_widget/multi_threaded_plotting_widget.py index 7b7ad46d5..2e37c46a5 100644 --- a/sohstationviewer/view/plotting/plotting_widget/multi_threaded_plotting_widget.py +++ b/sohstationviewer/view/plotting/plotting_widget/multi_threaded_plotting_widget.py @@ -106,7 +106,8 @@ class MultiThreadedPlottingWidget(PlottingWidget): self.title = get_title( data_set_id, self.min_x, self.max_x, self.date_mode) self.plotting_axes.height_normalizing_factor = \ - const.DEFAULT_SIZE_FACTOR_TO_NORMALIZE + const.DEFAULT_SIZE_FACTOR_TO_NORMALIZE * \ + self.main_window.vertical_ratio self.plotting_bot = const.BOTTOM self.axes = [] diff --git a/sohstationviewer/view/plotting/plotting_widget/plotting_axes.py b/sohstationviewer/view/plotting/plotting_widget/plotting_axes.py index 669d3af56..633c28dd8 100644 --- a/sohstationviewer/view/plotting/plotting_widget/plotting_axes.py +++ b/sohstationviewer/view/plotting/plotting_widget/plotting_axes.py @@ -1,4 +1,4 @@ -from typing import List, Optional, Dict +from typing import List, Optional, Dict, Tuple import numpy as np @@ -16,6 +16,28 @@ from sohstationviewer.view.util.color import clr from sohstationviewer.conf import constants as const +def split_label(label: str) -> Tuple[str, str]: + """ + Split label into 2 parts: + + If there is '-' between channel and detail, split at the hyphen + + Otherwise split into words + + :param label: label to be split + :return 2 parts of label + """ + if '-' in label: + labels = label.split('-') + if len(labels) == 2: + return labels[0], labels[1] + else: + return label[0], '-'.join(labels[1:]) + labels = label.split(' ') + half_of_total_word = int(len(labels) / 2) + label = ' '.join(labels[0:half_of_total_word]) + sub_label = ' '.join(labels[half_of_total_word:]) + return label, sub_label + + class PlottingAxes: """ Class that includes a figure to add axes for plotting and all methods @@ -77,15 +99,25 @@ class PlottingAxes: :param top: flag indicating this timestamp_bar is located on top or bottom to locate tick label. """ + height_normalizing_factor = self.height_normalizing_factor + if self.parent.name == 'TPS': + # For TPS, vertical_ratio only apply to title and timestamp bar + height_normalizing_factor *= self.main_window.vertical_ratio + # For bottom timestamp bar: space from the last plot to the bar + # For top timestamp bar: space from title to the bar self.parent.plotting_bot -= \ - const.TIME_BAR_SIZE_FACTOR * self.height_normalizing_factor + const.TIME_BAR_SIZE_FACTOR * height_normalizing_factor if top: - # top timestamp bar: the total of this and the above value is the - # space from edge to the bar which includes space for title. - self.parent.plotting_bot -= \ - const.TOP_SPACE_SIZE_FACTOR * self.height_normalizing_factor - height = 0.0005 * self.height_normalizing_factor + # add space for title + margin = const.TOP_SPACE_SIZE_FACTOR * height_normalizing_factor + if self.parent.name != 'TPS': + # TPS has timestamp bar not shown, reduce the margin so + # the total space from edge to the plot is reasonable + margin /= 3 + self.parent.plotting_bot -= margin + + height = 0.0005 * height_normalizing_factor timestamp_bar = self.fig.add_axes( [const.PLOT_LEFT_NORMALIZE, self.parent.plotting_bot, @@ -107,9 +139,10 @@ class PlottingAxes: labelbottom = True # bottom timestamp bar: space from edge to the bar self.parent.plotting_bot -= \ - const.BOT_SPACE_SIZE_FACTOR * self.height_normalizing_factor + const.BOT_SPACE_SIZE_FACTOR * height_normalizing_factor timestamp_bar.tick_params(which='major', length=7, width=2, + pad=5 * self.main_window.vertical_ratio, direction='inout', colors=self.parent.display_color['basic'], labelbottom=labelbottom, @@ -119,7 +152,7 @@ class PlottingAxes: colors=self.parent.display_color['basic']) timestamp_bar.set_ylabel('HOURS', fontweight='bold', - fontsize=const.FONTSIZE, + fontsize=self.main_window.base_plot_font_size, rotation=0, labelpad=const.HOUR_TO_TMBAR_D, ha='left', @@ -142,8 +175,9 @@ class PlottingAxes: timestamp_bar.axis('on') timestamp_bar.set_xticks(times, minor=True) timestamp_bar.set_xticks(major_times) - timestamp_bar.set_xticklabels(major_time_labels, - fontsize=const.FONTSIZE + 1) + timestamp_bar.set_xticklabels( + major_time_labels, + fontsize=self.main_window.base_plot_font_size + 1) timestamp_bar.set_xlim(self.parent.min_x, self.parent.max_x) @staticmethod @@ -192,7 +226,7 @@ class PlottingAxes: ax.tick_params(colors=self.parent.display_color['basic'], width=0, pad=-2, - labelsize=const.FONTSIZE) + labelsize=self.main_window.base_plot_font_size) # transparent background => self.fig will take care of background ax.patch.set_alpha(0) # prepare chan_plots list to be reference for the plotted lines/dots @@ -218,7 +252,7 @@ class PlottingAxes: rotation='horizontal', transform=ax.transAxes, color=color, - size=const.FONTSIZE + size=self.main_window.base_plot_font_size ) def set_axes_info(self, ax: Axes, @@ -249,8 +283,24 @@ class PlottingAxes: """ if label is None: label = chan_db_info['label'] + + label_color = self.parent.display_color['plot_label'] + if label.startswith("DEFAULT"): + label_color = self.parent.display_color["warning"] + + info_color = label_color + if info != '': + info_color = self.parent.display_color['sub_basic'] + + elif self.main_window.base_plot_font_size > 8: + # When there's no info and font size is big, + # separate label into 2 lines. + # The second line will be in the position of info. + label, info = split_label(label) + pos_y = 0.4 if info != '': + # set info/sub label on left side in the lower part ax.text( -0.11, 0.4, info, @@ -258,22 +308,20 @@ class PlottingAxes: verticalalignment='top', rotation='horizontal', transform=ax.transAxes, - color=self.parent.display_color['sub_basic'], - size=const.FONTSIZE + color=info_color, + size=self.main_window.base_plot_font_size ) pos_y = 0.6 - # set title on left side - color = self.parent.display_color['plot_label'] - if label.startswith("DEFAULT"): - color = self.parent.display_color["warning"] + # set main label on left side on the higher part + # or whole label on left side in the middle ax.text( -0.11, pos_y, label, horizontalalignment='left', rotation='horizontal', transform=ax.transAxes, - color=color, - size=const.FONTSIZE + 1 + color=label_color, + size=self.main_window.base_plot_font_size + 1 ) if not sample_no_pos: @@ -463,4 +511,4 @@ class PlottingAxes: horizontalalignment='left', transform=self.parent.timestamp_bar_top.transAxes, color=self.parent.display_color['basic'], - size=const.FONTSIZE + 2) + size=self.main_window.base_plot_font_size + 2) diff --git a/sohstationviewer/view/plotting/plotting_widget/plotting_widget.py b/sohstationviewer/view/plotting/plotting_widget/plotting_widget.py index 302a11922..0cd8f4185 100644 --- a/sohstationviewer/view/plotting/plotting_widget/plotting_widget.py +++ b/sohstationviewer/view/plotting/plotting_widget/plotting_widget.py @@ -305,9 +305,18 @@ class PlottingWidget(QtWidgets.QScrollArea): Set height of figure and main widget according to total of plotting channels' heights. + Vertical_ratio and fig_height_in_ratio are used to spread out plotting. + However, TPS channels won't need to be spread out. + Calculate height_normalizing_factor. """ self.set_size() + # Don't need to spead out channels for TPS + vertical_ratio = (self.main_window.vertical_ratio + if self.name != 'TPS' else 1) + if self.name != 'TPS': + self.fig_height_in *= self.main_window.fig_height_in_ratio + fig_height = math.ceil(self.fig_height_in * self.dpi_y) # adjusting main_widget to fit view port @@ -325,7 +334,7 @@ class PlottingWidget(QtWidgets.QScrollArea): # with height ratio of an item to fit in figure height start from # 1 to 0. normalize_total = math.ceil(self.fig_height_in / const.BASIC_HEIGHT_IN) - self.height_normalizing_factor = 1. / normalize_total + self.height_normalizing_factor = vertical_ratio / normalize_total if fig_height < max_height: # to avoid artifact in main widget's section that isn't covered by @@ -340,7 +349,7 @@ class PlottingWidget(QtWidgets.QScrollArea): self.plotting_axes.fig.set_figheight(self.fig_height_in) self.plotting_axes.height_normalizing_factor = \ - self.height_normalizing_factor + self.height_normalizing_factor * vertical_ratio # ======================================================================= # # EVENT # ======================================================================= # diff --git a/sohstationviewer/view/plotting/time_power_square/time_power_squared_widget.py b/sohstationviewer/view/plotting/time_power_square/time_power_squared_widget.py index c8834784b..579d0e8c4 100644 --- a/sohstationviewer/view/plotting/time_power_square/time_power_squared_widget.py +++ b/sohstationviewer/view/plotting/time_power_square/time_power_squared_widget.py @@ -104,7 +104,7 @@ class TimePowerSquaredWidget(plotting_widget.PlottingWidget): def init_fig_height_in(self): return const.BASIC_HEIGHT_IN * ( - const.TOP_SPACE_SIZE_FACTOR + + const.TOP_SPACE_SIZE_FACTOR/3 + const.BOT_SPACE_SIZE_FACTOR + const.TPS_LEGEND_SIZE_FACTOR + const.TPS_SEPARATOR_SIZE_FACTOR) @@ -164,6 +164,8 @@ class TimePowerSquaredWidget(plotting_widget.PlottingWidget): self.has_data = True self.title = get_title( data_set_id, self.min_x, self.max_x, self.date_mode) + # With TPS, not apply vertical ratio to channels, + # only for timestamp bar and title self.plotting_axes.height_normalizing_factor = \ const.DEFAULT_SIZE_FACTOR_TO_NORMALIZE self.plotting_bot = const.BOTTOM @@ -210,7 +212,7 @@ class TimePowerSquaredWidget(plotting_widget.PlottingWidget): self.timestamp_bar_top = self.plotting_axes.add_timestamp_bar( show_bar=False, top=True ) - self.plotting_axes.set_title(self.title) + self.plotting_axes.set_title(self.title, y=1000) def create_plotting_channel_processors(self): for chan_id in sorted(self.plotting_data1.keys()): @@ -331,7 +333,7 @@ class TimePowerSquaredWidget(plotting_widget.PlottingWidget): rotation='horizontal', transform=ax.transAxes, color=self.display_color['plot_label'], - size=const.FONTSIZE + 2 + size=self.main_window.base_plot_font_size + 2 ) zoom_marker1 = ax.plot( @@ -379,7 +381,8 @@ class TimePowerSquaredWidget(plotting_widget.PlottingWidget): ax.set_ylim(-(c_data['tps_data'].shape[0] + 1), 1) # show separation year tick labels ax.set_yticks(start_year_indexes) - ax.set_yticklabels(start_year_labels, fontsize=const.FONTSIZE, + ax.set_yticklabels(start_year_labels, + fontsize=self.main_window.base_plot_font_size, color=self.display_color['basic']) return ax @@ -448,7 +451,8 @@ class TimePowerSquaredWidget(plotting_widget.PlottingWidget): times, major_times, major_time_labels = get_day_ticks() ax.set_xticks(times, minor=True) ax.set_xticks(major_times) - ax.set_xticklabels(major_time_labels, fontsize=const.FONTSIZE, + ax.set_xticklabels(major_time_labels, + fontsize=self.main_window.base_plot_font_size, color=self.display_color['basic']) if self.display_top_ticks: # Show time ticks on both top and bottom of the first ax. diff --git a/sohstationviewer/view/ui/main_ui.py b/sohstationviewer/view/ui/main_ui.py index a637aad5e..bf796eae7 100755 --- a/sohstationviewer/view/ui/main_ui.py +++ b/sohstationviewer/view/ui/main_ui.py @@ -1,6 +1,6 @@ # UI and connectSignals for main_window import configparser -from typing import Union, List, Optional +from typing import Union, List, Optional, Dict from PySide6 import QtCore, QtGui, QtWidgets from PySide6.QtWidgets import ( @@ -254,6 +254,10 @@ class UIMainWindow(object): self.yyyy_doy_action: Union[QAction, None] = None self.yyyy_mm_dd_action: Union[QAction, None] = None self.yyyymmmdd_action: Union[QAction, None] = None + """ + Dict of base_plot_font_size_action by size + """ + self.base_plot_font_size_action_dict: Dict[int, QAction] = {} # ======================== Database Menu ========================== """ @@ -732,6 +736,18 @@ class UIMainWindow(object): date_format_menu.addAction(self.yyyymmmdd_action) date_format_action_group.addAction(self.yyyymmmdd_action) + base_plot_font_size_menu = QMenu('Base Font Size:', main_window) + base_plot_font_size_action_group = QActionGroup(main_window) + menu.addMenu(base_plot_font_size_menu) + for i in range(constants.MIN_FONTSIZE, constants.MAX_FONTSIZE + 1): + self.base_plot_font_size_action_dict[i] = QAction( + f'{i}px', main_window) + self.base_plot_font_size_action_dict[i].setCheckable(True) + base_plot_font_size_menu.addAction( + self.base_plot_font_size_action_dict[i]) + base_plot_font_size_action_group.addAction( + self.base_plot_font_size_action_dict[i]) + def create_database_menu(self, main_window, menu): """ Create Database Menu's Actions which allow user to add/edit @@ -811,6 +827,9 @@ class UIMainWindow(object): self.yyyy_doy_action.triggered.connect( lambda: main_window.set_date_format('YYYY:DOY')) + for i in range(constants.MIN_FONTSIZE, constants.MAX_FONTSIZE + 1): + self.connect_base_plot_font_size_action(main_window, i) + # Database self.add_edit_data_type_action.triggered.connect( main_window.open_data_type) @@ -830,6 +849,23 @@ class UIMainWindow(object): self.calendar_action.triggered.connect(main_window.open_calendar) self.doc_action.triggered.connect(main_window.open_help_browser) + def connect_base_plot_font_size_action( + self, main_window: QMainWindow, size: int): + """ + Connect an action of base_plot_font_size_dict with task to assign + main_window.base_plot_font_size to the corresponding size. + + This have to be written separately to avoid problem of lambda + in loop, which only pass the value in the last loop to the function of + lambda. + + :param main_window: main control window + :param size: font size + """ + self.base_plot_font_size_action_dict[size].triggered.connect( + lambda: setattr( + main_window, 'base_plot_font_size', size)) + def connect_widget_signals(self, main_window): main_window.current_directory_changed.connect( self.curr_dir_line_edit.setText) -- GitLab