diff --git a/sohstationviewer/database/soh.db b/sohstationviewer/database/soh.db index 4b0ea0a9262a978f1b1e72bcb45b4774afb180d5..90430cd3be7ab2b25781a5f0d15c3f640e62b3a2 100755 Binary files a/sohstationviewer/database/soh.db and b/sohstationviewer/database/soh.db differ 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 0e36e7ab4e08bee2f3caba711566357eec7473f0..f8cec92810a379ae2c31ed608f884c90b56af1be 100644 --- a/sohstationviewer/view/plotting/plotting_widget/multi_threaded_plotting_widget.py +++ b/sohstationviewer/view/plotting/plotting_widget/multi_threaded_plotting_widget.py @@ -109,7 +109,9 @@ class MultiThreadedPlottingWidget(PlottingWidget): def create_plotting_channel_processors( self, plotting_data: Dict, - need_db_info: bool = False) -> None: + need_db_info: bool = False, + need_move_channel: bool = False + ) -> None: """ Create a data processor for each channel data in the order of pref_order. If pref_order isn't given, process in order of @@ -117,6 +119,8 @@ class MultiThreadedPlottingWidget(PlottingWidget): :param plotting_data: dict of data by chan_id :param need_db_info: flag to get db info + :param need_move_channel: flag to call + move_soh_channels_with_link_to_the_end() """ chan_order = self.pref_order if self.pref_order \ else sorted(list(plotting_data.keys())) @@ -151,7 +155,8 @@ class MultiThreadedPlottingWidget(PlottingWidget): f"{', '.join( not_plot_chans)}") self.processing_log.append((msg, LogType.WARNING)) - self.move_soh_channels_with_link_to_the_end() + if need_move_channel: + self.move_soh_channels_with_link_to_the_end(chan_order) for chan_id in chan_order: if 'chan_db_info' not in plotting_data[chan_id]: @@ -165,24 +170,11 @@ class MultiThreadedPlottingWidget(PlottingWidget): channel_processor.finished.connect(self.process_channel) channel_processor.stopped.connect(self.has_stopped) - def move_soh_channels_with_link_to_the_end(self): + def move_soh_channels_with_link_to_the_end(self, chan_order): """ - In order to plot a channel (channel A) that is linked with another - channel (channel B), we need to plot B before we plot A. Because the - order of the channel in the data is not predetermined, we need to - manually move A to the end of the data set. This is, of course, - assuming that channel link is at most one level deep. + This only need for soh channels """ - channels_to_move = [] - for channel, chan_data in self.plotting_data1.items(): - try: - linked_channel = chan_data['chan_db_info']['linkedChan'] - if linked_channel not in ['', 'None', None]: - channels_to_move.append(channel) - except KeyError: - continue - for channel in channels_to_move: - self.plotting_data1[channel] = self.plotting_data1.pop(channel) + pass def plot_channels(self, d_obj, key, start_tm, end_tm, time_ticks_total, pref_order=[]): @@ -211,8 +203,10 @@ class MultiThreadedPlottingWidget(PlottingWidget): self.finished.emit() return - self.create_plotting_channel_processors(self.plotting_data1, True) - self.create_plotting_channel_processors(self.plotting_data2, True) + self.create_plotting_channel_processors( + self.plotting_data1, True, True) + self.create_plotting_channel_processors( + self.plotting_data2, True) self.process_channel() diff --git a/sohstationviewer/view/plotting/plotting_widget/plotting.py b/sohstationviewer/view/plotting/plotting_widget/plotting.py index 1a169ac683cf9f2627f65f06bfc4b6cb6a07130b..133699e98afd2f0b156fe5bf793b3ec761c494c0 100644 --- a/sohstationviewer/view/plotting/plotting_widget/plotting.py +++ b/sohstationviewer/view/plotting/plotting_widget/plotting.py @@ -280,8 +280,10 @@ class Plotting: if chan_id == 'GPS Lk/Unlk': sample_no_list = [] - sample_no_list.append(np.where(y_list[0] == -1)[0].size) - sample_no_list.append(np.where(y_list[0] == 1)[0].size) + ax.x_bottom = x_list[0][np.where(y_list[0] == -1)[0]] + sample_no_list.append(ax.x_bottom.size) + ax.x_top = x_list[0][np.where(y_list[0] == 1)[0]] + sample_no_list.append(ax.x_top.size) sample_no_colors = [clr[d_color], clr[d_color]] else: sample_no_list = [sum([len(x) for x in x_list])] @@ -309,8 +311,10 @@ class Plotting: mec=clr[d_color], picker=True, pickradius=3) - ax.x_list = x_list - ax.y_list = y_list + if chan_id != 'GPS Lk/Unlk': + ax.x_list = x_list + ax.y_list = y_list + ax.chan_db_info = chan_db_info return ax diff --git a/sohstationviewer/view/plotting/plotting_widget/plotting_axes.py b/sohstationviewer/view/plotting/plotting_widget/plotting_axes.py index cbe97d14472c1054915a2e7f9f9f32b1ab4a0d11..a5ced409fbc624585f4014e7a9c6fac4910270e2 100644 --- a/sohstationviewer/view/plotting/plotting_widget/plotting_axes.py +++ b/sohstationviewer/view/plotting/plotting_widget/plotting_axes.py @@ -240,9 +240,8 @@ class PlottingAxes: # bottom_total_point_lbl, top_total_point_lbl are label to diplay # total number of data points which are splitted into top # and bottom. The ax needs to include attributes x_bottom and x_top - # The plotTypes that use these labels are upDownDots (and linesDot - # with channel='GPS Lk/Unlk' which will have another MR to add - # x_bottom and x_top for this) + # The plotTypes that use these labels are upDownDots and linesDot + # with channel='GPS Lk/Unlk' ax.bottom_total_point_lbl = ax.text( 1.005, sample_no_pos[0], sample_no_list[0], @@ -290,14 +289,22 @@ class PlottingAxes: ) self.set_axes_ylim(ax, min_y, max_y, chan_db_info) - def set_axes_ylim(self, ax, org_min_y, org_max_y, chan_db_info): + def set_axes_ylim(self, ax: Axes, org_min_y: float, org_max_y: float, + chan_db_info: dict): """ Limit y range in min_y, max_y. Set y tick labels at min_y, max_y - :param ax: matplotlib.axes.Axes - axes of a channel - :param min_y: float - minimum of y values - :param max_y: float - maximum of y values + :param ax: axes of a channel + :param min_y: minimum of y values + :param max_y: maximum of y values + :param chan_db_info: info of channel from database """ + if chan_db_info['channel'] == 'GPS Lk/Unlk': + # to avoid case that the channel doesn't have Lk or Unlk + # preset min, max value so that GPS Clock Power is always in the + # middle + org_min_y = -1 + org_max_y = 1 min_y = round(org_min_y, 7) max_y = round(org_max_y, 7) if chan_db_info['fixPoint'] == 0 and org_max_y > org_min_y: diff --git a/sohstationviewer/view/plotting/plotting_widget/plotting_widget.py b/sohstationviewer/view/plotting/plotting_widget/plotting_widget.py index cfcfb8a0c63b1837becc4adebd15c423d6625eda..970ba1903f2ba734848ea36cd29d45c6b523006c 100755 --- a/sohstationviewer/view/plotting/plotting_widget/plotting_widget.py +++ b/sohstationviewer/view/plotting/plotting_widget/plotting_widget.py @@ -590,7 +590,7 @@ class PlottingWidget(QtWidgets.QScrollArea): # again or the plot would be collapsed to one line if total_points > 1: self.plotting_axes.set_axes_ylim( - ax, new_min_y, new_max_y) + ax, new_min_y, new_max_y, ax.chan_db_info) ax.center_total_point_lbl.set_text(total_points) def draw(self): diff --git a/sohstationviewer/view/plotting/state_of_health_widget.py b/sohstationviewer/view/plotting/state_of_health_widget.py index bc219840a012ad21555f4fe35dcdffc1e2563d98..35c32da4d5f4fc0007f88e48d14caca7017e87f7 100644 --- a/sohstationviewer/view/plotting/state_of_health_widget.py +++ b/sohstationviewer/view/plotting/state_of_health_widget.py @@ -64,10 +64,44 @@ class SOHWidget(MultiThreadedPlottingWidget): plot_type = chan_db_info['plotType'] linked_ax = None - if chan_db_info['linkedChan'] not in [None, 'None', '']: - linked_ax = self.plotting_data1[chan_db_info['linkedChan']]['ax'] + try: + if chan_db_info['linkedChan'] not in [None, 'None', '']: + linked_ax = self.plotting_data1[chan_db_info[ + 'linkedChan']]['ax'] + except KeyError: + # linkedChan not point to an actual channel + # which is when the channel in linkedChan doesn't have data + # or the channel with likedChan is plotted first + # (the later is prevented by + # move_soh_channels_with_link_to_the_end()) + pass ax = getattr(self.plotting, plot_functions[plot_type][1])( c_data, chan_db_info, chan_id, None, linked_ax) c_data['ax'] = ax - ax.chan = chan_id - self.axes.append(ax) + if linked_ax is None: + # to prevent same ax is appended to self.axes twice when there is + # linkedChan for the channel + ax.chan = chan_id + self.axes.append(ax) + + def move_soh_channels_with_link_to_the_end(self, chan_order): + """ + In order to plot a channel (channel A) that is linked with another + channel (channel B), we need to plot B before we plot A. Because the + order of the channel in the data is not predetermined, we need to + manually move A to the end of chan_order. This is, of course, + assuming that channel link is at most one level deep. + """ + channels_to_move = [] + + for channel, chan_data in self.plotting_data1.items(): + try: + linked_channel = chan_data['chan_db_info']['linkedChan'] + if linked_channel not in ['', 'None', None]: + chan_order.remove(channel) + channels_to_move.append(channel) + except KeyError: + continue + + for channel in channels_to_move: + chan_order.append(channel)