def __calculate_layout_size( self, canvas_size: Geometry.IntSize) -> Geometry.IntSize: # update the layout based on the current canvas size canvas_size = Geometry.IntSize.make(canvas_size) item_size = self.__calculate_item_size(canvas_size) item_count = self.__delegate.item_count if self.__delegate else 0 if self.direction == Direction.Row: items_per_row = max( 1, int(canvas_size.width / item_size.width) if self.wrap else item_count) item_rows = max((item_count + items_per_row - 1) // items_per_row, 1) width = canvas_size.width if self.wrap else item_count * item_size.width canvas_size = Geometry.IntSize(height=item_rows * item_size.height, width=width) else: items_per_column = max( 1, int(canvas_size.height / item_size.height) if self.wrap else item_count) item_columns = max( (item_count + items_per_column - 1) // items_per_column, 1) height = canvas_size.height if self.wrap else item_count * item_size.height canvas_size = Geometry.IntSize(height=height, width=item_columns * item_size.width) return canvas_size
def test_eels_data_camera_current_is_consistent(self): instrument = InstrumentDevice.Instrument("usim_stem_controller") # set up the scan context; these are here temporarily until the scan context architecture is fully implemented instrument._update_scan_context(Geometry.IntSize(256, 256), Geometry.FloatPoint(), 10, 0.0) instrument._set_scan_context_probe_position( instrument.scan_context, Geometry.FloatPoint(0.5, 0.5)) # grab scan data instrument.get_scan_data( scan_base.ScanFrameParameters({ "size": (256, 256), "pixel_time_us": 1, "fov_nm": 10 }), 0) instrument.validate_probe_position() camera = instrument._get_camera_simulator("eels") camera_size = camera._camera_shape camera.noise.enabled = False readout_area = Geometry.IntRect(origin=Geometry.IntPoint(), size=camera_size) binning_shape = Geometry.IntSize(1, 1) # get the value at 200eV and ZLP offset of 0 instrument.ZLPoffset = -20 exposure_s = 0.01 d = xd.sum(instrument.get_camera_data("eels", readout_area, binning_shape, exposure_s), axis=0).data # confirm it is a reasonable value camera_current_pA = numpy.sum( d) / exposure_s / instrument.counts_per_electron / 6.242e18 * 1e12 # print(f"current {camera_current_pA :#.2f}pA") self.assertTrue(190 < camera_current_pA < 210)
def test_eels_data_thickness_is_consistent(self): instrument = InstrumentDevice.Instrument("usim_stem_controller") # use the flake sample instrument.sample_index = 0 # set up the scan context; these are here temporarily until the scan context architecture is fully implemented instrument._update_scan_context(Geometry.IntSize(256, 256), Geometry.FloatPoint(), 10, 0.0) instrument._set_scan_context_probe_position( instrument.scan_context, Geometry.FloatPoint(0.5, 0.5)) # grab scan data instrument.get_scan_data( scan_base.ScanFrameParameters({ "size": (256, 256), "pixel_time_us": 1, "fov_nm": 10 }), 0) instrument.validate_probe_position() camera = instrument._get_camera_simulator("eels") camera_size = camera._camera_shape camera.noise.enabled = False readout_area = Geometry.IntRect(origin=Geometry.IntPoint(), size=camera_size) binning_shape = Geometry.IntSize(1, 1) # get the value at 200eV and ZLP offset of 0 instrument.ZLPoffset = -20 d = xd.sum(instrument.get_camera_data("eels", readout_area, binning_shape, 0.01), axis=0).data # confirm it is a reasonable value # print(measure_thickness(d)) self.assertTrue(0.40 < measure_thickness(d) < 1.00)
def test_add_item_to_string_list_widget_causes_container_to_relayout(self): from nion.ui import Widgets ui = TestUI.UserInterface() widget = Widgets.StringListWidget(ui) with contextlib.closing(widget): canvas_item = widget.content_widget.children[0].canvas_item canvas_item.update_layout(Geometry.IntPoint(x=0, y=0), Geometry.IntSize(width=300, height=200), immediate=True) scroll_area_canvas_item = canvas_item.canvas_items[0].canvas_items[ 0] canvas_item.layout_immediate( Geometry.IntSize(width=300, height=200)) # check assumptions self.assertEqual(scroll_area_canvas_item.canvas_rect.height, 200) self.assertEqual( scroll_area_canvas_item.content.canvas_rect.height, 0) # add item self.assertFalse(canvas_item._needs_layout_for_testing) widget.items = ["abc"] # self.assertTrue(canvas_item._needs_layout_for_testing) # check that column was laid out again canvas_item.layout_immediate(Geometry.IntSize(width=300, height=200), force=False) self.assertEqual(scroll_area_canvas_item.canvas_rect.height, 200) self.assertEqual( scroll_area_canvas_item.content.canvas_rect.height, 20)
def __calculate_item_size(self, canvas_size: Geometry.IntSize) -> Geometry.IntSize: if self.wrap: target_size = 80 item_width = max(60, int(canvas_size.width / max(1, ((canvas_size.width + target_size // 4) // target_size)))) return Geometry.IntSize(item_width, item_width) else: if self.direction == Direction.Row: return Geometry.IntSize(canvas_size.height, canvas_size.height) else: return Geometry.IntSize(canvas_size.width, canvas_size.width)
def __init__(self, instrument_id: str): super().__init__() self.priority = 20 self.instrument_id = instrument_id self.property_changed_event = Event.Event() self.__camera_frame_event = threading.Event() self.__camera_frame_event_ack = threading.Event() # define the STEM geometry limits self.stage_size_nm = 1000 self.max_defocus = 5000 / 1E9 # define the samples self.__samples = [ SampleSimulator.RectangleFlakeSample(self.stage_size_nm), SampleSimulator.AmorphousSample() ] self.__sample_index = 0 self.__stage_position_m = Geometry.FloatPoint() self.__drift_controller = DriftController() self.__slit_in = False self.__energy_per_channel_eV = 0.5 self.__beam_current = 200E-12 # 200 pA self.__blanked = False self.__ronchigram_shape = Geometry.IntSize(2048, 2048) self.__eels_shape = Geometry.IntSize(256, 1024) self.__scan_context = stem_controller.ScanContext() self.__probe_position = None self.__live_probe_position = None self.__sequence_progress = 0 self._is_synchronized = False self.__lock = threading.Lock() self.__controls = dict() built_in_controls = self.__create_built_in_controls() for control in built_in_controls: self.add_control(control) # We need to set the expressions after adding the controls to InstrumentDevice self.__set_expressions() self.__cameras = { "ronchigram": RonchigramCameraSimulator.RonchigramCameraSimulator( self, self.__ronchigram_shape, self.counts_per_electron, self.stage_size_nm), "eels": EELSCameraSimulator.EELSCameraSimulator(self, self.__eels_shape, self.counts_per_electron) }
def test_add_item_to_string_list_widget_causes_container_to_relayout( self) -> None: # ugly type casting from nion.ui import Widgets ui = TestUI.UserInterface() widget = Widgets.StringListWidget(ui) with contextlib.closing(widget): canvas_item = typing.cast( CanvasItem.CanvasItemComposition, typing.cast( UserInterface.CanvasWidget, typing.cast( UserInterface.BoxWidget, widget.content_widget).children[0]).canvas_item) canvas_item.update_layout(Geometry.IntPoint(x=0, y=0), Geometry.IntSize(width=300, height=200), immediate=True) scroll_area_canvas_item = typing.cast( CanvasItem.ScrollAreaCanvasItem, typing.cast(CanvasItem.CanvasItemComposition, canvas_item.canvas_items[0]).canvas_items[0]) canvas_item.layout_immediate( Geometry.IntSize(width=300, height=200)) # check assumptions scroll_canvas_rect = scroll_area_canvas_item.canvas_rect or Geometry.IntRect.empty_rect( ) scroll_content = scroll_area_canvas_item.content assert scroll_content self.assertEqual(scroll_canvas_rect.height, 200) scroll_content_rect = scroll_content.canvas_rect or Geometry.IntRect.empty_rect( ) self.assertEqual(scroll_content_rect.height, 0) # add item self.assertFalse(canvas_item._needs_layout_for_testing) widget.items = ["abc"] # self.assertTrue(canvas_item._needs_layout_for_testing) # check that column was laid out again canvas_item.layout_immediate(Geometry.IntSize(width=300, height=200), force=False) scroll_canvas_rect = scroll_area_canvas_item.canvas_rect or Geometry.IntRect.empty_rect( ) scroll_content = scroll_area_canvas_item.content assert scroll_content scroll_content_rect = scroll_content.canvas_rect or Geometry.IntRect.empty_rect( ) self.assertEqual(scroll_canvas_rect.height, 200) self.assertEqual(scroll_content_rect.height, 20)
def get_scan_data(self, frame_parameters, channel) -> numpy.ndarray: size = Geometry.IntSize.make(frame_parameters.subscan_pixel_size if frame_parameters.subscan_pixel_size else frame_parameters.size) offset_m = self.stage_position_m - self.GetVal2D("beam_shift_m") fov_size_nm = Geometry.FloatSize.make(frame_parameters.fov_size_nm) if frame_parameters.fov_size_nm else Geometry.FloatSize(frame_parameters.fov_nm, frame_parameters.fov_nm) if frame_parameters.subscan_fractional_size: subscan_fractional_size = Geometry.FloatSize.make(frame_parameters.subscan_fractional_size) used_fov_size_nm = Geometry.FloatSize(height=fov_size_nm.height * subscan_fractional_size.height, width=fov_size_nm.width * subscan_fractional_size.width) else: used_fov_size_nm = fov_size_nm center_nm = Geometry.FloatPoint.make(frame_parameters.center_nm) if frame_parameters.subscan_fractional_center: subscan_fractional_center = Geometry.FloatPoint.make(frame_parameters.subscan_fractional_center) center_nm += Geometry.FloatPoint(y=(subscan_fractional_center.y - 0.5) * fov_size_nm.height, x=(subscan_fractional_center.x - 0.5) * fov_size_nm.width) extra = int(math.ceil(max(size.height * math.sqrt(2) - size.height, size.width * math.sqrt(2) - size.width))) extra_nm = Geometry.FloatPoint(y=(extra / size.height) * used_fov_size_nm[0], x=(extra / size.width) * used_fov_size_nm[1]) used_size = size + Geometry.IntSize(height=extra, width=extra) data = numpy.zeros((used_size.height, used_size.width), numpy.float32) self.sample.plot_features(data, offset_m, used_fov_size_nm, extra_nm, center_nm, used_size) noise_factor = 0.3 if frame_parameters.rotation_rad != 0: inner_height = size.height / used_size.height inner_width = size.width / used_size.width inner_bounds = ((1.0 - inner_height) * 0.5, (1.0 - inner_width) * 0.5), (inner_height, inner_width) data = Core.function_crop_rotated(DataAndMetadata.new_data_and_metadata(data), inner_bounds, -frame_parameters.rotation_rad).data # TODO: data is not always the correct size else: data = data[extra // 2:extra // 2 + size.height, extra // 2:extra // 2 + size.width] return (data + numpy.random.randn(size.height, size.width) * noise_factor) * frame_parameters.pixel_time_us
def draw_list_item(self, drawing_context: DrawingContext.DrawingContext, rect: Geometry.IntRect) -> None: with drawing_context.saver(): draw_rect = Geometry.IntRect(origin=rect.top_left + Geometry.IntPoint(y=4, x=4), size=Geometry.IntSize(h=72, w=72)) drawing_context.add(self.__create_thumbnail(draw_rect)) drawing_context.fill_style = "#000" drawing_context.font = "11px serif" drawing_context.fill_text(self.title_str, rect.left + 4 + 72 + 4, rect.top + 4 + 12) drawing_context.fill_text(self.format_str, rect.left + 4 + 72 + 4, rect.top + 4 + 12 + 15) drawing_context.fill_text(self.datetime_str, rect.left + 4 + 72 + 4, rect.top + 4 + 12 + 15 + 15) if self.status_str: drawing_context.fill_text(self.status_str, rect.left + 4 + 72 + 4, rect.top + 4 + 12 + 15 + 15 + 15) else: drawing_context.fill_style = "#888" drawing_context.fill_text(self.project_str, rect.left + 4 + 72 + 4, rect.top + 4 + 12 + 15 + 15 + 15)
def test_data_item_display_thumbnail_source_produces_data_item_mime_data( self): with TestContext.create_memory_context() as test_context: document_controller = test_context.create_document_controller() document_model = document_controller.document_model data_item = DataItem.DataItem(numpy.random.randn(8, 8)) document_model.append_data_item(data_item) display_item = document_model.get_display_item_for_data_item( data_item) display_item.display_type = "image" thumbnail_source = DataItemThumbnailWidget.DataItemThumbnailSource( document_controller.ui) finished = threading.Event() def thumbnail_data_changed(data): finished.set() thumbnail_source.on_thumbnail_data_changed = thumbnail_data_changed thumbnail_source.set_display_item(display_item) finished.wait(1.0) finished.clear() finished.wait(1.0) mime_data = document_controller.ui.create_mime_data() valid, thumbnail = thumbnail_source.populate_mime_data_for_drag( mime_data, Geometry.IntSize(64, 64)) self.assertTrue(valid) self.assertIsNotNone(thumbnail) self.assertTrue( mime_data.has_format(MimeTypes.DISPLAY_ITEM_MIME_TYPE))
def _repaint_visible(self, drawing_context: DrawingContext.DrawingContext, visible_rect: Geometry.IntRect) -> None: canvas_bounds = self.canvas_bounds if self.__delegate and canvas_bounds: item_width = canvas_bounds.width item_height = self.__item_height with drawing_context.saver(): items = self.__delegate.items max_index = len(items) top_visible_row = visible_rect.top // item_height bottom_visible_row = visible_rect.bottom // item_height for index in range(top_visible_row, bottom_visible_row + 1): if 0 <= index < max_index: rect = Geometry.IntRect(origin=Geometry.IntPoint(y=index * item_height, x=0), size=Geometry.IntSize(width=item_width, height=item_height)) if rect.intersects_rect(visible_rect): is_selected = self.__selection.contains(index) if is_selected: with drawing_context.saver(): drawing_context.begin_path() drawing_context.rect(rect.left, rect.top, rect.width, rect.height) drawing_context.fill_style = "#3875D6" if self.focused else "#DDD" drawing_context.fill() self.__delegate.paint_item(drawing_context, items[index], rect, is_selected) if index == self.__drop_index: with drawing_context.saver(): drop_border_width = 2.5 rect_in = rect.to_float_rect().inset(drop_border_width / 2, drop_border_width / 2).to_int_rect() drawing_context.begin_path() drawing_context.rect(rect_in.left, rect_in.top, rect_in.width, rect_in.height) drawing_context.line_width = drop_border_width drawing_context.stroke_style = "rgba(56, 117, 214, 0.8)" drawing_context.stroke()
def __init__(self, ui, text: str): super().__init__(ui.create_column_widget()) self.on_button_clicked = None font = "normal 11px serif" font_metrics = ui.get_font_metrics(font, text) text_button_canvas_item = TextButtonCanvasItem(text) text_button_canvas_item.sizing.set_fixed_size( Geometry.IntSize(height=font_metrics.height + 6, width=font_metrics.width + 6)) def button_clicked(): if callable(self.on_button_clicked): self.on_button_clicked() text_button_canvas_item.on_button_clicked = button_clicked text_button_canvas_widget = ui.create_canvas_widget(properties={ "height": 20, "width": 20 }) text_button_canvas_widget.canvas_item.add_canvas_item( text_button_canvas_item) # ugh. this is a partially working stop-gap when a canvas item is in a widget it will not get mouse exited reliably text_button_canvas_widget.on_mouse_exited = text_button_canvas_item.root_container.canvas_widget.on_mouse_exited self.content_widget.add(text_button_canvas_widget)
def __init__(self, ui: UserInterface.UserInterface, text: str) -> None: column_widget = ui.create_column_widget() super().__init__(column_widget) self.on_button_clicked: typing.Optional[typing.Callable[[], None]] = None font = "normal 11px serif" font_metrics = ui.get_font_metrics(font, text) text_button_canvas_item = TextButtonCanvasItem(text) text_button_canvas_item.update_sizing( text_button_canvas_item.sizing.with_fixed_size( Geometry.IntSize(height=font_metrics.height + 6, width=font_metrics.width + 6))) def button_clicked() -> None: if callable(self.on_button_clicked): self.on_button_clicked() text_button_canvas_item.on_button_clicked = button_clicked text_button_canvas_widget = ui.create_canvas_widget(properties={ "height": 20, "width": 20 }) text_button_canvas_widget.canvas_item.add_canvas_item( text_button_canvas_item) # ugh. this is a partially working stop-gap when a canvas item is in a widget it will not get mouse exited reliably root_container = text_button_canvas_item.root_container if root_container: text_button_canvas_widget.on_mouse_exited = root_container.canvas_widget.on_mouse_exited column_widget.add(text_button_canvas_widget)
def __acquisition_thread(self): while True: if self.__cancel: # case where exposure was canceled. break self.__thread_event.wait() self.__thread_event.clear() if self.__cancel: break while (self.__is_playing or self.__is_acquiring) and not self.__cancel: start = time.time() readout_area = self.readout_area binning_shape = Geometry.IntSize( self.__binning, self.__binning if self.__symmetric_binning else 1) xdata = self.__instrument.get_camera_data( self.camera_type, Geometry.IntRect.from_tlbr(*readout_area), binning_shape, self.__exposure) self.__acquired_one_event.set() elapsed = time.time() - start wait_s = max(self.__exposure - elapsed, 0) if not self.__thread_event.wait(wait_s): # thread event was not triggered during wait; signal that we have data xdata._set_timestamp(datetime.datetime.utcnow()) self.__xdata_buffer = xdata self.__has_data_event.set() self.__instrument.trigger_camera_frame() else: # thread event was triggered during wait; continue loop self.__has_data_event.clear() self.__thread_event.clear()
def plot(self, data: numpy.ndarray, offset_m: Geometry.FloatPoint, fov_nm: Geometry.FloatSize, center_nm: Geometry.FloatPoint, shape: Geometry.IntSize) -> int: # TODO: how does center_nm interact with stage position? # TODO: take into account feature angle # TODO: take into account frame parameters angle # TODO: expand features to other shapes than rectangle scan_rect_m = self.get_scan_rect_m(offset_m, fov_nm, center_nm) feature_rect_m = self.get_feature_rect_m() sum = 0 if scan_rect_m.intersects_rect(feature_rect_m): feature_rect_top_px = int(shape[0] * (feature_rect_m.top - scan_rect_m.top) / scan_rect_m.height) feature_rect_left_px = int(shape[1] * (feature_rect_m.left - scan_rect_m.left) / scan_rect_m.width) feature_rect_height_px = int(shape[0] * feature_rect_m.height / scan_rect_m.height) feature_rect_width_px = int(shape[1] * feature_rect_m.width / scan_rect_m.width) if feature_rect_top_px < 0: feature_rect_height_px += feature_rect_top_px feature_rect_top_px = 0 if feature_rect_left_px < 0: feature_rect_width_px += feature_rect_left_px feature_rect_left_px = 0 if feature_rect_top_px + feature_rect_height_px > shape[0]: feature_rect_height_px = shape[0] - feature_rect_top_px if feature_rect_left_px + feature_rect_width_px > shape[1]: feature_rect_width_px = shape[1] - feature_rect_left_px feature_rect_origin_px = Geometry.IntPoint(y=feature_rect_top_px, x=feature_rect_left_px) feature_rect_size_px = Geometry.IntSize(height=feature_rect_height_px, width=feature_rect_width_px) feature_rect_px = Geometry.IntRect(feature_rect_origin_px, feature_rect_size_px) data[feature_rect_px.top:feature_rect_px.bottom, feature_rect_px.left:feature_rect_px.right] += 1.0 sum += (feature_rect_px.bottom - feature_rect_px.top) * (feature_rect_px.right - feature_rect_px.left) return sum
def _repaint_visible(self, drawing_context, visible_rect): if self.__delegate: canvas_bounds = self.canvas_bounds item_width = int(canvas_bounds.width) item_height = self.__item_height with drawing_context.saver(): items = self.__delegate.items max_index = len(items) top_visible_row = visible_rect.top // item_height bottom_visible_row = visible_rect.bottom // item_height for index in range(top_visible_row, bottom_visible_row + 1): if 0 <= index < max_index: rect = Geometry.IntRect(origin=Geometry.IntPoint(y=index * item_height, x=0), size=Geometry.IntSize(width=item_width, height=item_height)) if rect.intersects_rect(visible_rect): is_selected = self.__selection.contains(index) if is_selected: drawing_context.save() drawing_context.begin_path() drawing_context.rect(rect.left, rect.top, rect.width, rect.height) drawing_context.fill_style = "#3875D6" if self.focused else "#DDD" drawing_context.fill() drawing_context.restore() self.__delegate.paint_item(drawing_context, items[index], rect, is_selected)
def __init__(self, instrument: InstrumentDevice.Instrument, camera_type: str, sensor_dimensions: Geometry.IntSize, counts_per_electron: int) -> None: self.__instrument = instrument self._camera_type = camera_type self._sensor_dimensions = sensor_dimensions self._counts_per_electron = counts_per_electron self._needs_recalculation = True self._last_frame_settings = [ Geometry.IntRect((0, 0), (0, 0)), Geometry.IntSize(), 0.0, None ] def property_changed(name: str) -> None: if name in self.depends_on: self._needs_recalculation = True self.__property_changed_event_listener = instrument.property_changed_event.listen( property_changed) # we also need to inform the cameras about changes to the (parked) probe position def probe_state_changed( probe_state: str, probe_position: typing.Optional[Geometry.FloatPoint]) -> None: property_changed("probe_state") property_changed("probe_position") self.__probe_state_changed_event_listener = instrument.probe_state_changed_event.listen( probe_state_changed)
def test_eels_data_is_consistent_when_energy_offset_changes(self): instrument = InstrumentDevice.Instrument("usim_stem_controller") instrument.get_scan_data( scan_base.ScanFrameParameters({ "size": (256, 256), "pixel_time_us": 1, "fov_nm": 10 }), 0) instrument.validate_probe_position() camera = instrument._get_camera_simulator("eels") camera_size = camera._camera_shape camera.noise.enabled = False readout_area = Geometry.IntRect(origin=Geometry.IntPoint(), size=camera_size) binning_shape = Geometry.IntSize(1, 1) # get the value at 200eV and ZLP offset of 0 instrument.ZLPoffset = 0 d = xd.sum(instrument.get_camera_data("eels", readout_area, binning_shape, 0.01), axis=0) index200_0 = int( d.dimensional_calibrations[-1].convert_from_calibrated_value(200)) value200_0 = d.data[index200_0] # get the value at 200eV and ZLP offset of 100 instrument.ZLPoffset = 100 d = xd.sum(instrument.get_camera_data("eels", readout_area, binning_shape, 0.01), axis=0) index200_100 = int( d.dimensional_calibrations[-1].convert_from_calibrated_value(200)) value200_100 = d.data[index200_100] self.assertEqual(int(value200_0 / 100), int(value200_100 / 100))
def test_data_item_display_thumbnail_source_produces_data_item_mime_data( self): app = Application.Application(TestUI.UserInterface(), set_global=False) document_model = DocumentModel.DocumentModel() document_controller = DocumentController.DocumentController( app.ui, document_model, workspace_id="library") with contextlib.closing(document_controller): data_item = DataItem.DataItem(numpy.random.randn(8, 8)) document_model.append_data_item(data_item) display_item = document_model.get_display_item_for_data_item( data_item) display_item.display_type = "image" thumbnail_source = DataItemThumbnailWidget.DataItemThumbnailSource( app.ui) finished = threading.Event() def thumbnail_data_changed(data): finished.set() thumbnail_source.on_thumbnail_data_changed = thumbnail_data_changed thumbnail_source.set_display_item(display_item) finished.wait(1.0) finished.clear() finished.wait(1.0) mime_data = app.ui.create_mime_data() valid, thumbnail = thumbnail_source.populate_mime_data_for_drag( mime_data, Geometry.IntSize(64, 64)) self.assertTrue(valid) self.assertIsNotNone(thumbnail) self.assertTrue( mime_data.has_format(MimeTypes.DISPLAY_ITEM_MIME_TYPE))
def test_display_data_panel_reuses_existing_display(self): with create_memory_profile_context() as profile_context: document_model = DocumentModel.DocumentModel(profile=profile_context.create_profile()) document_controller = self.app.create_document_controller(document_model, "library") with contextlib.closing(document_controller): # configure data item data_item = DataItem.DataItem(numpy.arange(64).reshape(8, 8)) document_model.append_data_item(data_item) # configure workspace d = {"type": "splitter", "orientation": "vertical", "splits": [0.5, 0.5], "children": [ {"type": "image", "uuid": "0569ca31-afd7-48bd-ad54-5e2bb9f21102", "identifier": "a", "selected": True}, {"type": "image", "uuid": "acd77f9f-2f6f-4fbf-af5e-94330b73b997", "identifier": "b"}]} workspace_2x1 = document_controller.workspace_controller.new_workspace("2x1", d) document_controller.workspace_controller.change_workspace(workspace_2x1) root_canvas_item = document_controller.workspace_controller.image_row.children[0]._root_canvas_item() root_canvas_item.layout_immediate(Geometry.IntSize(width=640, height=480)) self.assertIsNone(document_controller.workspace_controller.display_panels[0].data_item) self.assertIsNone(document_controller.workspace_controller.display_panels[1].data_item) # test display_data_item api = Facade.get_api("~1.0", "~1.0") library = api.library document_controller_ref = api.application.document_controllers[0] data_item_ref = library.data_items[0] # display data item and verify it is displayed display_panal_ref = document_controller_ref.display_data_item(data_item_ref) self.assertEqual(document_controller.workspace_controller.display_panels[0].data_item, data_item_ref._data_item) self.assertIsNone(document_controller.workspace_controller.display_panels[1].data_item) self.assertEqual(document_controller.workspace_controller.display_panels[0], display_panal_ref._display_panel) # display data item again and verify it is displayed only once display_panal_ref = document_controller_ref.display_data_item(data_item_ref) self.assertEqual(document_controller.workspace_controller.display_panels[0].data_item, data_item_ref._data_item) self.assertIsNone(document_controller.workspace_controller.display_panels[1].data_item) self.assertEqual(document_controller.workspace_controller.display_panels[0], display_panal_ref._display_panel)
def _repaint_visible(self, drawing_context: DrawingContext.DrawingContext, visible_rect: Geometry.IntRect) -> None: canvas_size = self.canvas_size if self.__delegate and canvas_size and canvas_size.height > 0 and canvas_size.width > 0: item_size = self.__calculate_item_size(canvas_size) items = self.__delegate.items if self.__delegate else list() item_count = len(items) items_per_row = max(1, int(canvas_size.width / item_size.width) if self.wrap else item_count) items_per_column = max(1, int(canvas_size.height / item_size.height) if self.wrap else item_count) with drawing_context.saver(): top_visible_row = visible_rect.top // item_size.height bottom_visible_row = visible_rect.bottom // item_size.height left_visible_column = visible_rect.left // item_size.width right_visible_column = visible_rect.right // item_size.width for row in range(top_visible_row, bottom_visible_row + 1): for column in range(left_visible_column, right_visible_column + 1): if self.direction == Direction.Row: index = row * items_per_row + column else: index = row + column * items_per_column if 0 <= index < item_count: rect = Geometry.IntRect(origin=Geometry.IntPoint(y=row * item_size.height, x=column * item_size.width), size=Geometry.IntSize(width=item_size.width, height=item_size.height)) if rect.intersects_rect(visible_rect): is_selected = self.__selection.contains(index) if is_selected: with drawing_context.saver(): drawing_context.begin_path() drawing_context.rect(rect.left, rect.top, rect.width, rect.height) drawing_context.fill_style = "#3875D6" if self.focused else "#BBB" drawing_context.fill() self.__delegate.paint_item(drawing_context, items[index], rect, is_selected)
def __init__(self, size=None): self.has_event_loop = False self.root_widget = None self.__menus = list() self.__size = size if size is not None else Geometry.IntSize( height=720, width=960) self.__dock_widgets = list() self.display_scaling = 1.0
def content_height_changed(content_height): desired_height = content_height + 12 metadata_editor_canvas_item.sizing.set_fixed_height(desired_height) metadata_editor_widget.canvas_item.update_layout( Geometry.IntPoint(), scroll_area.size) if metadata_editor_canvas_item._has_layout: column.size = Geometry.IntSize(height=desired_height, width=column.size.width)
def test_draw_data_with_color_table(self): dc = DrawingContext.DrawingContext() data = numpy.zeros((4, 4), numpy.float32) color_map_data = numpy.zeros((256, ), numpy.uint32) color_map_data[:] = 0xFF010203 dc.draw_data(data, 0, 0, 4, 4, 0, 1, color_map_data) dc.to_svg(Geometry.IntSize(4, 4), Geometry.IntRect.from_tlbr(0, 0, 4, 4))
def update_layout(self, canvas_origin, canvas_size, *, immediate=False): """Override from abstract canvas item. Adjust the canvas height based on the constraints. """ canvas_size = Geometry.IntSize.make(canvas_size) canvas_size = Geometry.IntSize(height=self.__calculate_layout_height(), width=canvas_size.width) super().update_layout(canvas_origin, canvas_size, immediate=immediate)
def create_dock_widget(self, widget: UserInterfaceModule.Widget, panel_id: str, title: str, positions: typing.Sequence[str], position: str) -> UserInterfaceModule.DockWidget: dock_widget = DockWidget(self, widget, panel_id, title, positions, position) dock_widget.size_changed(Geometry.IntSize(height=320, width=480)) return dock_widget
def __rect_for_index(self, index: int) -> Geometry.IntRect: canvas_bounds = self.canvas_bounds if canvas_bounds: item_width = canvas_bounds.width item_height = self.__item_height return Geometry.IntRect(origin=Geometry.IntPoint(y=index * item_height, x=0), size=Geometry.IntSize(width=item_width, height=item_height)) return Geometry.IntRect.empty_rect()
def drag_pressed(x, y, modifiers): on_drag = self.on_drag if callable(on_drag): mime_data = ui.create_mime_data() valid, thumbnail = thumbnail_source.populate_mime_data_for_drag( mime_data, Geometry.IntSize(width=80, height=80)) if valid: on_drag(mime_data, thumbnail, x, y)
def update_layout(self, canvas_origin: typing.Optional[Geometry.IntPoint], canvas_size: typing.Optional[Geometry.IntSize], *, immediate: bool = False) -> None: """Override from abstract canvas item. Adjust the canvas height based on the constraints. """ if canvas_size: canvas_size = Geometry.IntSize(height=self.__calculate_layout_height(), width=canvas_size.width) super().update_layout(canvas_origin, canvas_size, immediate=immediate)
def drag_pressed(x: int, y: int, modifiers: UserInterface.KeyboardModifiers) -> None: on_drag = self.on_drag if callable(on_drag): mime_data = ui.create_mime_data() valid, thumbnail = thumbnail_source.populate_mime_data_for_drag( mime_data, Geometry.IntSize(width=80, height=80)) if valid: on_drag(mime_data, thumbnail, x, y)