From e79e5faea39a7ebee9b9f21d16422b0c0b9cf16e Mon Sep 17 00:00:00 2001 From: apasarkar Date: Mon, 15 Jul 2024 14:03:36 -0400 Subject: [PATCH 1/4] Updates LUT to deal with divide by zero errors and updates figure shape logic in imagewidget to deal with multiple shape values in constructor --- fastplotlib/widgets/histogram_lut.py | 15 +++++++++------ fastplotlib/widgets/image.py | 21 ++++++++++++++++----- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/fastplotlib/widgets/histogram_lut.py b/fastplotlib/widgets/histogram_lut.py index 872cf4319..e0f316326 100644 --- a/fastplotlib/widgets/histogram_lut.py +++ b/fastplotlib/widgets/histogram_lut.py @@ -25,8 +25,8 @@ def __init__( ---------- data image_graphic - nbins - flank_divisor: float, default 5.0 + nbins: int, defaut 100. Total number of bins used in the histogram + flank_divisor: float, default 5.0. Fraction of empty histogram bins on the tails of the distribution set `np.inf` for no flanks kwargs """ @@ -161,9 +161,10 @@ def _calculate_histogram(self, data): hist, edges = np.histogram(data_ss, bins=self._nbins) # used if data ptp <= 10 because event things get weird - # with tiny world objects due to floating point error + # with tiny world objects due to floating point error # so if ptp <= 10, scale up by a factor - self._scale_factor: int = max(1, 100 * int(10 / np.ptp(data_ss))) + data_interval = edges[-1] - edges[0] + self._scale_factor: int = max(1, 100 * int(10 / data_interval)) edges = edges * self._scale_factor @@ -178,7 +179,6 @@ def _calculate_histogram(self, data): ) edges_flanked = np.concatenate((flank_left, edges, flank_right)) - np.unique(np.diff(edges_flanked)) hist_flanked = np.concatenate( (np.zeros(flank_nbins), hist, np.zeros(flank_nbins)) @@ -186,7 +186,10 @@ def _calculate_histogram(self, data): # scale 0-100 to make it easier to see # float32 data can produce unnecessarily high values - hist_scaled = hist_flanked / (hist_flanked.max() / 100) + hist_scale_value = hist_flanked.max() + if np.allclose(hist_scale_value, 0): + hist_scale_value = 1 + hist_scaled = hist_flanked / (hist_scale_value / 100) if edges_flanked.size > hist_scaled.size: # we don't care about accuracy here so if it's off by 1-2 bins that's fine diff --git a/fastplotlib/widgets/image.py b/fastplotlib/widgets/image.py index df9b46b55..60f1720fa 100644 --- a/fastplotlib/widgets/image.py +++ b/fastplotlib/widgets/image.py @@ -368,15 +368,25 @@ def __init__( if all([_is_arraylike(d) for d in data]): # Grid computations if figure_shape is None: - figure_shape = calculate_figure_shape(len(data)) + if figure_kwargs is not None: + if 'shape' in figure_kwargs: + figure_shape = figure_kwargs['shape'] + else: + figure_shape = calculate_figure_shape(len(data)) - # verify that user-specified figure shape is large enough for the number of image arrays passed - elif figure_shape[0] * figure_shape[1] < len(data): + # Regardless of how figure_shape is computed, below code + # verifies that figure shape is large enough for the number of image arrays passed + if figure_shape[0] * figure_shape[1] < len(data): + original_shape = (figure_shape[0], figure_shape[1]) figure_shape = calculate_figure_shape(len(data)) warn( - f"Invalid `figure_shape` passed, setting figure shape to: {figure_shape}" + f"Original `figure_shape` was: {original_shape} " + f" but data length is {len(data)}" + f" Resetting figure shape to: {figure_shape}" ) + + self._data: list[np.ndarray] = data # Establish number of image dimensions and number of scrollable dimensions for each array @@ -506,13 +516,14 @@ def __init__( # update the default kwargs with any user-specified kwargs # user specified kwargs will overwrite the defaults figure_kwargs_default.update(figure_kwargs) + figure_kwargs_default['shape'] = figure_shape if graphic_kwargs is None: graphic_kwargs = dict() graphic_kwargs.update({"cmap": cmap}) - self._figure: Figure = Figure(shape=figure_shape, **figure_kwargs_default) + self._figure: Figure = Figure(**figure_kwargs_default) self._histogram_widget = histogram_widget for data_ix, (d, subplot) in enumerate(zip(self.data, self.figure)): From aad49960ab97e69d86dcf928819047d36263374e Mon Sep 17 00:00:00 2001 From: apasarkar Date: Mon, 15 Jul 2024 14:27:20 -0400 Subject: [PATCH 2/4] Includes formatting on imagewidget code --- fastplotlib/widgets/image.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/fastplotlib/widgets/image.py b/fastplotlib/widgets/image.py index 60f1720fa..6c270b378 100644 --- a/fastplotlib/widgets/image.py +++ b/fastplotlib/widgets/image.py @@ -369,8 +369,8 @@ def __init__( # Grid computations if figure_shape is None: if figure_kwargs is not None: - if 'shape' in figure_kwargs: - figure_shape = figure_kwargs['shape'] + if "shape" in figure_kwargs: + figure_shape = figure_kwargs["shape"] else: figure_shape = calculate_figure_shape(len(data)) @@ -385,8 +385,6 @@ def __init__( f" Resetting figure shape to: {figure_shape}" ) - - self._data: list[np.ndarray] = data # Establish number of image dimensions and number of scrollable dimensions for each array @@ -516,7 +514,7 @@ def __init__( # update the default kwargs with any user-specified kwargs # user specified kwargs will overwrite the defaults figure_kwargs_default.update(figure_kwargs) - figure_kwargs_default['shape'] = figure_shape + figure_kwargs_default["shape"] = figure_shape if graphic_kwargs is None: graphic_kwargs = dict() From c2071675c2b927ccf50c648305f609f87ec017e8 Mon Sep 17 00:00:00 2001 From: apasarkar Date: Mon, 15 Jul 2024 14:51:51 -0400 Subject: [PATCH 3/4] Updates docstring for histogram_lut --- fastplotlib/widgets/histogram_lut.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fastplotlib/widgets/histogram_lut.py b/fastplotlib/widgets/histogram_lut.py index e0f316326..a3b36eb45 100644 --- a/fastplotlib/widgets/histogram_lut.py +++ b/fastplotlib/widgets/histogram_lut.py @@ -25,9 +25,10 @@ def __init__( ---------- data image_graphic - nbins: int, defaut 100. Total number of bins used in the histogram - flank_divisor: float, default 5.0. Fraction of empty histogram bins on the tails of the distribution - set `np.inf` for no flanks + nbins: int, defaut 100. + Total number of bins used in the histogram + flank_divisor: float, default 5.0. + Fraction of empty histogram bins on the tails of the distribution set `np.inf` for no flanks kwargs """ super().__init__(**kwargs) From 90af0d4a136d918f99551b3fead28773693e40cf Mon Sep 17 00:00:00 2001 From: apasarkar Date: Tue, 16 Jul 2024 12:12:08 -0400 Subject: [PATCH 4/4] Changes when figure_kwargs is defined for cleaner conditional logic --- fastplotlib/widgets/image.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fastplotlib/widgets/image.py b/fastplotlib/widgets/image.py index 6c270b378..749403781 100644 --- a/fastplotlib/widgets/image.py +++ b/fastplotlib/widgets/image.py @@ -357,6 +357,9 @@ def __init__( """ self._names = None + if figure_kwargs is None: + figure_kwargs = dict() + # output context self._output = None @@ -368,9 +371,8 @@ def __init__( if all([_is_arraylike(d) for d in data]): # Grid computations if figure_shape is None: - if figure_kwargs is not None: - if "shape" in figure_kwargs: - figure_shape = figure_kwargs["shape"] + if "shape" in figure_kwargs: + figure_shape = figure_kwargs["shape"] else: figure_shape = calculate_figure_shape(len(data)) @@ -508,8 +510,6 @@ def __init__( ) figure_kwargs_default = {"controller_ids": "sync"} - if figure_kwargs is None: - figure_kwargs = dict() # update the default kwargs with any user-specified kwargs # user specified kwargs will overwrite the defaults