def test_slider_range(qtbot): """ Tests range of the slider is matched to the range of the dims """ ndim = 4 view = QtDims(Dims(ndim)) qtbot.addWidget(view) # Check the range of slider matches the values of the range of the dims # at initialization first_slider = view.slider_widgets[0].slider assert first_slider.minimum() == view.dims.range[0][0] assert (first_slider.maximum() == view.dims.range[0][1] - view.dims.range[0][2]) assert first_slider.singleStep() == view.dims.range[0][2] # Check the range of slider stays matched to the values of the range of # the dims view.dims.set_range(0, (1, 5, 2)) assert first_slider.minimum() == view.dims.range[0][0] assert (first_slider.maximum() == view.dims.range[0][1] - view.dims.range[0][2]) assert first_slider.singleStep() == view.dims.range[0][2]
def test_order_when_changing_ndim(qtbot): """ Test order of the sliders when changing the number of dimensions. """ ndim = 4 view = QtDims(Dims(ndim)) qtbot.addWidget(view) # Check that values of the dimension slider matches the values of the # dims point after the point has been moved within the dims view.dims.set_point(0, 2) view.dims.set_point(1, 1) for i in range(view.dims.ndim - 2): slider = view.slider_widgets[i].slider assert slider.value() == view.dims.point[i] # Check the matching dimensions and sliders are preserved when # dimensions are added view.dims.ndim = 5 for i in range(view.dims.ndim - 2): slider = view.slider_widgets[i].slider assert slider.value() == view.dims.point[i] # Check the matching dimensions and sliders are preserved when dims # dimensions are removed view.dims.ndim = 4 for i in range(view.dims.ndim - 2): slider = view.slider_widgets[i].slider assert slider.value() == view.dims.point[i] # Check the matching dimensions and sliders are preserved when dims # dimensions are removed view.dims.ndim = 3 for i in range(view.dims.ndim - 2): slider = view.slider_widgets[i].slider assert slider.value() == view.dims.point[i]
def test_changing_display(qtbot): """ Test changing the displayed property of an axis """ ndim = 4 view = QtDims(Dims(ndim)) qtbot.addWidget(view) view.show() assert view.nsliders == view.dims.ndim assert np.sum(view._displayed_sliders) == view.dims.ndim - 2 assert np.all([ s.isVisible() == d for s, d in zip(view.slider_widgets, view._displayed_sliders) ]) # Check changing displayed removes a slider view.dims.ndisplay = 3 assert view.nsliders == view.dims.ndim assert np.sum(view._displayed_sliders) == view.dims.ndim - 3 assert np.all([ s.isVisible() == d for s, d in zip(view.slider_widgets, view._displayed_sliders) ])
def test_slice_labels(qtbot): ndim = 4 dims = Dims(ndim=ndim) dims.set_range(0, (0, 20, 1)) view = QtDims(dims) qtbot.addWidget(view) # make sure the totslice_label is showing the correct number assert int(view.slider_widgets[0].totslice_label.text()) == 19 # make sure setting the dims.point updates the slice label label_edit = view.slider_widgets[0].curslice_label dims.set_point(0, 15) assert int(label_edit.text()) == 15 # make sure setting the current slice label updates the model label_edit.setText(str(8)) label_edit.editingFinished.emit() assert dims.point[0] == 8
def test_axis_labels_str_to_list(): dims = Dims() dims.axis_labels = 'TX' assert dims.axis_labels == ('T', 'X')
def test_labels_order_when_changing_dims(): dims = Dims(ndim=4) dims.ndim = 5 assert dims.axis_labels == ('0', '1', '2', '3', '4')
def test_point_variable_step_size(): dims = Dims(ndim=3) assert dims.point == (0, ) * 3 desired_range = ((0, 6, 0.5), (0, 6, 1), (0, 6, 2)) dims.set_range(range(3), desired_range) assert dims.range == desired_range # set point updates current_step indirectly dims.set_point([0, 1, 2], (2.9, 2.9, 2.9)) assert dims.current_step == (6, 3, 1) # point is a property computed on demand from current_step assert dims.point == (3, 3, 2) # can set step directly as well # note that out of range values get clipped dims.set_current_step((0, 1, 2), (1, -3, 5)) assert dims.current_step == (1, 0, 2) assert dims.point == (0.5, 0, 4) dims.set_current_step(0, -1) assert dims.current_step == (0, 0, 2) assert dims.point == (0, 0, 4) # mismatched len(axis) vs. len(value) with pytest.raises(ValueError): dims.set_point((0, 1), (0, 0, 0)) with pytest.raises(ValueError): dims.set_current_step((0, 1), (0, 0, 0))
def test_wrong_labels(): dims = Dims(3) with pytest.raises(ValueError): dims.axis_labels = ('a', 'b')
def test_changing_focus(): """Test changing focus updates the last_used prop.""" # too-few dims, should have no sliders to update dims = Dims(ndim=2) assert dims.last_used == 0 dims._focus_down() dims._focus_up() assert dims.last_used == 0 dims.ndim = 5 # Note that with no view attached last used remains # None even though new non-displayed dimensions added assert dims.last_used == 0 dims._focus_down() assert dims.last_used == 2 dims._focus_down() assert dims.last_used == 1 dims._focus_up() assert dims.last_used == 2 dims._focus_up() assert dims.last_used == 0 dims._focus_down() assert dims.last_used == 2
def test_labels_with_init(): dims = Dims(ndim=3, axis_labels=('x', 'y', 'z')) assert dims.axis_labels == ('x', 'y', 'z')
def test_wrong_labels(): with pytest.raises(ValueError): Dims(3, axis_labels=['a', 'b'])
def test_axis_labels(): dims = Dims(4) assert dims.axis_labels == ['0', '1', '2', '3']
def test_labels_with_init(): dims = Dims(3, axis_labels=['x', 'y', 'z']) assert dims.axis_labels == ['x', 'y', 'z']
def test_wrong_order(): with pytest.raises(ValueError): Dims(3, order=range(2))
def test_order_with_init(): dims = Dims(3, order=[0, 2, 1]) assert dims.order == [0, 2, 1]
def test_assert_axis_out_of_bounds(ndim, ax_input): dims = Dims(ndim) with pytest.raises(ValueError): dims._assert_axis_in_bounds(ax_input)
def test_assert_axis_in_bounds(ndim, ax_input, expected): dims = Dims(ndim) actual = dims._assert_axis_in_bounds(ax_input) assert actual == expected
def test_roll_skip_dummy_axis_2(): """Test basic roll skips axis with length 1 when not first.""" dims = Dims(ndim=4) dims.set_range(0, (0, 10, 1)) dims.set_range(1, (0, 0, 1)) dims.set_range(2, (0, 10, 1)) dims.set_range(3, (0, 10, 1)) assert dims.order == (0, 1, 2, 3) dims._roll() assert dims.order == (3, 1, 0, 2) dims._roll() assert dims.order == (2, 1, 3, 0)
def test_pad_bad_labels(): dims = Dims(ndim=3) dims.axis_labels = ('a', 'b') assert dims.axis_labels == ('0', 'a', 'b')
def test_roll_skip_dummy_axis_3(): """Test basic roll skips all axes with length 1.""" dims = Dims(ndim=4) dims.set_range(0, (0, 10, 1)) dims.set_range(1, (0, 0, 1)) dims.set_range(2, (0, 10, 1)) dims.set_range(3, (0, 0, 1)) assert dims.order == (0, 1, 2, 3) dims._roll() assert dims.order == (2, 1, 0, 3) dims._roll() assert dims.order == (0, 1, 2, 3)
def test_axis_labels(): dims = Dims(ndim=4) assert dims.axis_labels == ('0', '1', '2', '3')
def test_order_with_init(): dims = Dims(ndim=3, order=(0, 2, 1)) assert dims.order == (0, 2, 1)
def test_roll_skip_dummy_axis_1(): """Test basic roll skips axis with length 1.""" dims = Dims(ndim=4) dims.set_range(0, (0, 1, 1)) dims.set_range(1, (0, 10, 1)) dims.set_range(2, (0, 10, 1)) dims.set_range(3, (0, 10, 1)) assert dims.order == [0, 1, 2, 3] dims._roll() assert dims.order == [0, 3, 1, 2] dims._roll() assert dims.order == [0, 2, 3, 1]
def test_bad_order(): dims = Dims(ndim=3) with pytest.raises(ValueError): dims.order = (0, 0, 1)
def test_range_set_multiple(): """ Tests bulk range setting. """ dims = Dims(ndim=4) assert dims.range == ((0, 2, 1), ) * 4 dims.set_range((0, 3), [(0, 6, 3), (0, 9, 3)]) assert dims.range == ((0, 6, 3), ) + ((0, 2, 1), ) * 2 + ((0, 9, 3), ) # last_used will be set to the smallest axis in range dims.set_range(range(1, 4), ((0, 5, 1), ) * 3) assert dims.range == ((0, 6, 3), ) + ((0, 5, 1), ) * 3 # test with descending axis order dims.set_range(axis=(3, 0), _range=[(0, 4, 1), (0, 6, 1)]) assert dims.range == ((0, 6, 1), ) + ((0, 5, 1), ) * 2 + ((0, 4, 1), ) # out of range axis raises a ValueError with pytest.raises(ValueError): dims.set_range((dims.ndim, 0), [(0.0, 4.0, 1.0)] * 2) # sequence lengths for axis and _range do not match with pytest.raises(ValueError): dims.set_range((0, 1), [(0.0, 4.0, 1.0)] * 3)
def test_keyword_only_dims(): with pytest.raises(TypeError): Dims(3, (1, 2, 3))
def test_wrong_order(): dims = Dims(3) with pytest.raises(ValueError): dims.order = (0, 1)
def test_order_when_changing_ndim(): """ Test order of the dims when changing the number of dimensions. """ dims = Dims(ndim=4) dims.set_range(0, (0, 4, 1)) dims.set_point(0, 2) dims.ndim = 5 # Test that new dims get appended to the beginning of lists assert dims.point == (0, 2, 0, 0, 0) assert dims.order == (0, 1, 2, 3, 4) assert dims.axis_labels == ('0', '1', '2', '3', '4') dims.set_range(2, (0, 4, 1)) dims.set_point(2, 3) dims.ndim = 3 # Test that dims get removed from the beginning of lists assert dims.point == (3, 0, 0) assert dims.order == (0, 1, 2) assert dims.axis_labels == ('2', '3', '4')
@magic_factory( call_button='set axis labels', viewer={'visible': False}, ) def set_axis_labels(viewer: napari.Viewer, axes=''): if type(axes) == str and len(axes) == viewer.dims.ndim: viewer.dims.axis_labels = list(axes) if __name__ == '__main__': from napari._qt.containers import QtListView from napari.components import Dims dims = Dims(ndim=5, ndisplay=2, last_used=0, axis_labels=list('tzcyx')) # create a python model root = SelectableEventedList([AxisModel(dims, i) for i in range(5)]) root.events.reordered.connect( lambda event, dims=dims: set_dims_order(dims, event.value)) # note: we don't yet handle expanding the order dims.events.order.connect( lambda event, axes_list=root: move_indices(axes_list, event.value)) # create Qt views onto the python models view = QtListView(root) w = QWidget() w.setLayout(QHBoxLayout()) w.layout().addWidget(view) w.show()