Skip to content

Commit

Permalink
Fix #998. Improve handling of invalid dimensional calibrations in lin…
Browse files Browse the repository at this point in the history
…e plot. Fall back to top-left-pixel. Tests.
  • Loading branch information
cmeyer committed Jan 19, 2024
1 parent db94bdf commit 7b34bbc
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 4 deletions.
2 changes: 2 additions & 0 deletions nion/swift/LineGraphCanvasItem.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ def __init__(self, data_scale: float, calibrated_data_min: float, calibrated_dat
data_right: int, x_calibration: typing.Optional[Calibration.Calibration],
y_calibration: typing.Optional[Calibration.Calibration], data_style: typing.Optional[str],
y_ticker: Geometry.Ticker) -> None:
assert x_calibration is None or x_calibration.is_valid
assert y_calibration is None or y_calibration.is_valid
# these items are considered to be input items
self.data_scale = data_scale
self.__uncalibrated_left_channel = data_left
Expand Down
1 change: 1 addition & 0 deletions nion/swift/LinePlotCanvasItem.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ def update_display_properties_and_layers(self, display_calibration_info: Display
displayed_dimensional_calibrations = display_calibration_info.displayed_dimensional_calibrations
self.__data_scale = displayed_dimensional_scales[-1] if len(displayed_dimensional_scales) > 0 else 1.0
self.__displayed_dimensional_calibration = displayed_dimensional_calibrations[-1] if len(displayed_dimensional_calibrations) > 0 else Calibration.Calibration(scale=displayed_dimensional_scales[-1])
assert self.__displayed_dimensional_calibration.is_valid
self.__intensity_calibration = display_calibration_info.displayed_intensity_calibration
self.__calibration_style = display_calibration_info.calibration_style
self.__y_min = display_properties.get("y_min")
Expand Down
13 changes: 10 additions & 3 deletions nion/swift/model/DisplayItem.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,9 @@ class CalibrationStyleNative(CalibrationStyle):
is_calibrated = True

def get_dimensional_calibrations(self, dimensional_shape: DataAndMetadata.ShapeType, dimensional_calibrations: DataAndMetadata.CalibrationListType) -> DataAndMetadata.CalibrationListType:
return dimensional_calibrations
if all(calibration.is_valid for calibration in dimensional_calibrations):
return dimensional_calibrations
return [Calibration.Calibration() for _ in dimensional_shape]


class CalibrationStylePixelsTopLeft(CalibrationStyle):
Expand Down Expand Up @@ -2209,8 +2211,12 @@ def __update_displays(self) -> None:
mn = min(mn, v)
mx = max(mx, v)
intensity_calibration = xdata0.intensity_calibration
scales = mn, mx
dimensional_shape = (int(mx - mn), )
if math.isfinite(mn) and math.isfinite(mx):
scales = mn, mx
dimensional_shape = (int(mx - mn), )
else:
scales = 0, xdata0.dimensional_shape[-1]
dimensional_shape = xdata0.dimensional_shape
self.__dimensional_calibrations = dimensional_calibrations
self.__intensity_calibration = intensity_calibration
self.__scales = scales
Expand Down Expand Up @@ -2766,6 +2772,7 @@ def get_cursor_value(display_item: DisplayItem) -> typing.Tuple[str, str]:
class DisplayCalibrationInfo:

def __init__(self, display_item: DisplayItem, display_data_shape: typing.Optional[DataAndMetadata.ShapeType] = None) -> None:
assert all(calibration.is_valid for calibration in display_item.displayed_dimensional_calibrations)
self.display_data_shape = display_data_shape if display_data_shape is not None else display_item.display_data_shape
self.displayed_dimensional_scales = display_item.displayed_dimensional_scales
self.displayed_dimensional_calibrations = copy.deepcopy(display_item.displayed_dimensional_calibrations)
Expand Down
8 changes: 8 additions & 0 deletions nion/swift/test/DisplayItem_test.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# standard libraries
import contextlib
import copy
import math
import typing
import unittest

Expand All @@ -9,6 +10,7 @@

# local libraries
from nion.data import Calibration
from nion.data import DataAndMetadata
from nion.swift import Application
from nion.swift import Facade
from nion.swift.model import DataItem
Expand Down Expand Up @@ -487,6 +489,12 @@ def test_displayed_title_is_inherited_from_source(self):
self.assertEqual("green (Negate)", display_item2.displayed_title)
self.assertEqual("green (Negate) (Negate)", display_item3.displayed_title)

def test_display_item_handles_invalid_calibration(self):
with TestContext.create_memory_context() as test_context:
document_model = test_context.create_document_model()
data_item = DataItem.new_data_item(DataAndMetadata.new_data_and_metadata(numpy.zeros((8,)), dimensional_calibrations=[Calibration.Calibration(0.0, -math.inf, "x")]))
document_model.append_data_item(data_item)

# test_transaction_does_not_cascade_to_data_item_refs
# test_increment_data_ref_counts_cascades_to_data_item_refs
# test_adding_data_item_twice_to_composite_item_fails
Expand Down
22 changes: 21 additions & 1 deletion nion/swift/test/DisplayPanel_test.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# standard libraries
import contextlib
import logging
from math import ceil, floor
import math
import typing
import unittest
import uuid
Expand Down Expand Up @@ -3155,6 +3155,26 @@ def test_hand_tool_undo(self):
document_controller.handle_undo()
self.assertEqual((0.5, 0.5), tuple(display_item.display_properties["image_position"]))

def test_raster_display_handles_invalid_calibration(self):
with TestContext.create_memory_context() as test_context:
document_controller = test_context.create_document_controller()
document_model = document_controller.document_model
display_panel = document_controller.selected_display_panel
data_item = DataItem.new_data_item(DataAndMetadata.new_data_and_metadata(numpy.zeros((8,8)), dimensional_calibrations=[Calibration.Calibration(0.0, -math.inf, "x"), Calibration.Calibration(0.0, -math.inf, "x")]))
document_model.append_data_item(data_item)
display_item = document_model.get_display_item_for_data_item(data_item)
DisplayPanel.preview(DisplayPanel.DisplayPanelUISettings(document_controller.ui), display_item, 512, 512)

def test_line_plot_display_handles_invalid_calibration(self):
with TestContext.create_memory_context() as test_context:
document_controller = test_context.create_document_controller()
document_model = document_controller.document_model
display_panel = document_controller.selected_display_panel
data_item = DataItem.new_data_item(DataAndMetadata.new_data_and_metadata(numpy.zeros((8,)), dimensional_calibrations=[Calibration.Calibration(0.0, -math.inf, "x")]))
document_model.append_data_item(data_item)
display_item = document_model.get_display_item_for_data_item(data_item)
DisplayPanel.preview(DisplayPanel.DisplayPanelUISettings(document_controller.ui), display_item, 512, 128)


if __name__ == '__main__':
logging.getLogger().setLevel(logging.DEBUG)
Expand Down

0 comments on commit 7b34bbc

Please sign in to comment.