From 56596bd57c39f0756e33befb2168381f4f940979 Mon Sep 17 00:00:00 2001 From: Lan <ldam@passcal.nmt.edu> Date: Thu, 18 May 2023 11:40:30 -0600 Subject: [PATCH] create plotting channel processors in the preference order; remove checking for GPS channel, it should be set in DB to not plot those channels --- sohstationviewer/view/main_window.py | 3 +- .../multi_threaded_plotting_widget.py | 44 ++++++++++++------- sohstationviewer/view/util/functions.py | 40 +++++++++++++++++ 3 files changed, 71 insertions(+), 16 deletions(-) diff --git a/sohstationviewer/view/main_window.py b/sohstationviewer/view/main_window.py index 4775539e1..666c94cf5 100755 --- a/sohstationviewer/view/main_window.py +++ b/sohstationviewer/view/main_window.py @@ -739,7 +739,8 @@ class MainWindow(QtWidgets.QMainWindow, UIMainWindow): try: self.plotting_widget.plot_channels( - d_obj, sel_key, self.start_tm, self.end_tm, time_tick_total) + d_obj, sel_key, self.start_tm, self.end_tm, time_tick_total, + self.req_soh_chans) except Exception: fmt = traceback.format_exc() msg = f"Can't plot SOH data due to error: {str(fmt)}" 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 229544d77..7e52995e0 100644 --- a/sohstationviewer/view/plotting/plotting_widget/multi_threaded_plotting_widget.py +++ b/sohstationviewer/view/plotting/plotting_widget/multi_threaded_plotting_widget.py @@ -11,6 +11,8 @@ from sohstationviewer.view.plotting.plotting_widget.plotting_processor import ( from sohstationviewer.view.plotting.plotting_widget.plotting_widget import ( PlottingWidget) from sohstationviewer.view.util.enums import LogType +from sohstationviewer.view.util.functions import ( + replace_actual_quest_chans, remove_not_found_chans) from sohstationviewer.controller.util import display_tracking_info from sohstationviewer.controller.plotting_data import get_title @@ -106,21 +108,34 @@ class MultiThreadedPlottingWidget(PlottingWidget): def create_plotting_channel_processors( self, plotting_data: Dict, - get_plot_info: Optional[Callable[[str, Dict, str], Dict]]) -> None: + get_plot_info: Optional[Callable[[str, Dict, str], Dict]], + pref_order: List[str] = []) -> None: """ - Create a data processor for each channel data. + Create a data processor for each channel data in the order of + pref_order. If pref_order isn't given, process in order of + plotting_data. :param plotting_data: dict of data by chan_id :param get_plot_info: function to get plotting info from database + :param pref_order: order of channels to be plotted """ - for chan_id in plotting_data: + chan_order = pref_order if pref_order else list(plotting_data.keys()) + chan_order = replace_actual_quest_chans( + chan_order, plotting_data.keys()) + chan_order = remove_not_found_chans( + chan_order, plotting_data.keys(), self.processing_log) + + not_plot_chans = [] + for chan_id in chan_order: if get_plot_info is not None: chan_db_info = get_plot_info(chan_id, plotting_data[chan_id], self.parent.data_type, self.c_mode) - if chan_db_info['height'] == 0: + if (chan_db_info['height'] == 0 or + chan_db_info['plotType'] == ''): # not draw + not_plot_chans.append(chan_id) continue if 'DEFAULT' in chan_db_info['channel']: msg = (f"Channel {chan_id}'s " @@ -130,19 +145,16 @@ class MultiThreadedPlottingWidget(PlottingWidget): # instruction here self.processing_log.append((msg, LogType.WARNING)) - if chan_db_info['plotType'] == '': - continue - - # These channels contain GPS data which are only shown in - # the GPS dialog. - if chan_id in {'GLO', 'VLO', 'VLA', 'GLA', 'VEL', 'VNS', 'GNS', - 'GEL'}: - continue plotting_data[chan_id]['chan_db_info'] = chan_db_info + if not_plot_chans != []: + msg = (f"The database settings 'plotType' or 'height' show not to " + f"be plotted for the following channels: " + f"{', '.join( not_plot_chans)}") + self.processing_log.append((msg, LogType.WARNING)) self.move_soh_channels_with_link_to_the_end() - for chan_id in plotting_data: + for chan_id in chan_order: if 'chan_db_info' not in plotting_data[chan_id]: continue channel_processor = PlottingChannelProcessor( @@ -173,7 +185,8 @@ class MultiThreadedPlottingWidget(PlottingWidget): for channel in channels_to_move: self.plotting_data1[channel] = self.plotting_data1.pop(channel) - def plot_channels(self, d_obj, key, start_tm, end_tm, time_ticks_total): + def plot_channels(self, d_obj, key, start_tm, end_tm, time_ticks_total, + pref_soh_order=[]): """ Prepare to plot waveform/SOH/mass-position data by creating a data processor for each channel, then, run the processors. @@ -183,6 +196,7 @@ class MultiThreadedPlottingWidget(PlottingWidget): :param start_tm: requested start time to read :param end_tm: requested end time to read :param time_ticks_total: max number of tick to show on time bar + :param pref_order: order of channels to be plotted """ if not self.is_working: self.reset_widget() @@ -197,7 +211,7 @@ class MultiThreadedPlottingWidget(PlottingWidget): self.finished.emit() return self.create_plotting_channel_processors( - self.plotting_data1, self.get_plot_info) + self.plotting_data1, self.get_plot_info, pref_soh_order) self.create_plotting_channel_processors( self.plotting_data2, get_chan_plot_info) self.process_channel() diff --git a/sohstationviewer/view/util/functions.py b/sohstationviewer/view/util/functions.py index 2927cae8c..60e2883b3 100644 --- a/sohstationviewer/view/util/functions.py +++ b/sohstationviewer/view/util/functions.py @@ -325,5 +325,45 @@ def get_index_from_time(chan_data: List[np.ndarray], tm: float, val: float) \ return list_idx, section_idx +def remove_not_found_chans( + chan_order: List[str], actual_chans: List[str], + processing_log: List[Tuple[str, LogType]]) -> List[str]: + """ + Remove channels that are not found in actual_chans from chan_order. + + :param chan_order: The list of channel that have channels end with '?' + :param actual_chans: The actual channel list + :param processing_log: The log list to keep track with not found channels + :return: chan_order from which not found channels have been removed. + """ + not_found_chans = [c for c in chan_order if c not in actual_chans] + if not_found_chans != []: + msg = (f"No data found for the following channels: " + f"{', '.join(not_found_chans)}") + processing_log.append((msg, LogType.WARNING)) + return [c for c in chan_order if c not in not_found_chans] + + +def replace_actual_quest_chans( + chan_order: List[str], actual_chans: List[str]) -> List[str]: + """ + Remove channels end with '?' from chan_order and replace with corresponding + channels found in actual channels. + + :param chan_order: The list of channel that have channels end with '?' + :param actual_chans: The actual channel list + :return: chan_order that have channels end with '?' replaced by actual + channels. + """ + quest_chans = [c for c in chan_order if c.endswith('?')] + for qc in quest_chans: + actual_quest_chans = [c for c in list(actual_chans) + if qc[:-1] == c[:-1]] + quest_idx = chan_order.index(qc) + chan_order.remove(qc) + chan_order[quest_idx:quest_idx] = sorted(actual_quest_chans) + return chan_order + + if __name__ == '__main__': create_table_of_content_file(Path('../../../documentation')) -- GitLab