def populate_mime_data_for_drag(self, mime_data, size: Geometry.IntSize): if self.__display_item: mime_data.set_data_as_string(MimeTypes.DISPLAY_ITEM_MIME_TYPE, str(self.__display_item.uuid)) rgba_image_data = self.__thumbnail_source.thumbnail_data thumbnail = Image.get_rgba_data_from_rgba(Image.scaled(Image.get_rgba_view_from_rgba_data(rgba_image_data), (size.width, size.height))) if rgba_image_data is not None else None return True, thumbnail return False, None
def function_rgb_channel(data_and_metadata_in: _DataAndMetadataLike, channel: int) -> DataAndMetadata.DataAndMetadata: data_and_metadata = DataAndMetadata.promote_ndarray(data_and_metadata_in) if channel < 0 or channel > 3: raise ValueError("RGB channel: invalid channel.") data = data_and_metadata.data if not Image.is_data_valid(data): raise ValueError("RGB channel: invalid data.") if not data_and_metadata.is_data_rgb_type: raise ValueError("RGB channel: data is not RGB type.") assert data is not None channel_data: _ImageDataType if Image.is_shape_and_dtype_rgb(data.shape, data.dtype): if channel == 3: channel_data = numpy.ones(data.shape, int) else: channel_data = data[..., channel].astype(int) elif Image.is_shape_and_dtype_rgba(data.shape, data.dtype): channel_data = data[..., channel].astype(int) else: raise ValueError("RGB channel: unable to extract channel.") return DataAndMetadata.new_data_and_metadata( channel_data, intensity_calibration=data_and_metadata.intensity_calibration, dimensional_calibrations=data_and_metadata.dimensional_calibrations)
def function_rgb_linear_combine( data_and_metadata_in: _DataAndMetadataLike, red_weight: float, green_weight: float, blue_weight: float) -> DataAndMetadata.DataAndMetadata: data_and_metadata = DataAndMetadata.promote_ndarray(data_and_metadata_in) data = data_and_metadata.data if not Image.is_data_valid(data): raise ValueError("RGB linear combine: invalid data.") if not data_and_metadata.is_data_rgb_type: raise ValueError("RGB linear combine: data is not RGB type.") assert data is not None combined_data: _ImageDataType if Image.is_shape_and_dtype_rgb(data.shape, data.dtype): combined_data = numpy.sum( data[..., :] * (blue_weight, green_weight, red_weight), 2) elif Image.is_shape_and_dtype_rgba(data.shape, data.dtype): combined_data = numpy.sum( data[..., :] * (blue_weight, green_weight, red_weight, 0.0), 2) else: raise ValueError("RGB channel: unable to extract channel.") return DataAndMetadata.new_data_and_metadata( combined_data, intensity_calibration=data_and_metadata.intensity_calibration, dimensional_calibrations=data_and_metadata.dimensional_calibrations)
def test_create_rgba_image_from_array(self) -> None: image_1d_16 = numpy.zeros((16, ), dtype=numpy.double) image_1d_16x1 = numpy.zeros((16, 1), dtype=numpy.double) self.assertIsNotNone(Image.create_rgba_image_from_array(image_1d_16)) self.assertIsNotNone(Image.create_rgba_image_from_array(image_1d_16x1)) image_1d_rgb = numpy.zeros((16, 3), dtype=numpy.uint8) self.assertIsNotNone(Image.create_rgba_image_from_array(image_1d_rgb))
def _repaint(self, drawing_context: DrawingContext.DrawingContext) -> None: """Repaint the canvas item. This will occur on a thread.""" canvas_size = self.canvas_size if canvas_size: with drawing_context.saver(): if self.__color_map_data is not None: rgba_image: numpy.typing.NDArray[numpy.uint32] = numpy.empty((4,) + self.__color_map_data.shape[:-1], dtype=numpy.uint32) Image.get_rgb_view(rgba_image)[:] = self.__color_map_data[numpy.newaxis, :, :] # scalar data assigned to each component of rgb view Image.get_alpha_view(rgba_image)[:] = 255 drawing_context.draw_image(rgba_image, 0, 0, canvas_size.width, canvas_size.height)
def drag_started(self, ui: UserInterface.UserInterface, x: int, y: int, modifiers: UserInterface.KeyboardModifiers) -> typing.Tuple[typing.Optional[UserInterface.MimeData], typing.Optional[numpy.ndarray]]: if self.__display_item: mime_data = self.ui.create_mime_data() if self.__display_item: MimeTypes.mime_data_put_display_item(mime_data, self.__display_item) thumbnail_data = self.calculate_thumbnail_data() if thumbnail_data is not None: # scaling is very slow thumbnail_data = Image.get_rgba_data_from_rgba(Image.scaled(Image.get_rgba_view_from_rgba_data(thumbnail_data), Geometry.IntSize(w=80, h=80))) return mime_data, thumbnail_data return None, None
def calculate_data(): data = data_and_metadata.data if not Image.is_data_valid(data): return None if Image.is_shape_and_dtype_rgb(data.shape, data.dtype): return numpy.sum( data[..., :] * (blue_weight, green_weight, red_weight), 2) elif Image.is_shape_and_dtype_rgba(data.shape, data.dtype): return numpy.sum( data[..., :] * (blue_weight, green_weight, red_weight, 0.0), 2) else: return None
def populate_mime_data_for_drag(self, mime_data: UserInterface.MimeData, size: Geometry.IntSize): if self.__display_item: MimeTypes.mime_data_put_display_item(mime_data, self.__display_item) rgba_image_data = self.__thumbnail_source.thumbnail_data thumbnail = Image.get_rgba_data_from_rgba( Image.scaled( Image.get_rgba_view_from_rgba_data(rgba_image_data), (size.width, size.height))) if rgba_image_data is not None else None return True, thumbnail return False, None
def populate_mime_data_for_drag( self, mime_data: UserInterface.MimeData, size: Geometry.IntSize ) -> typing.Tuple[bool, typing.Optional[_NDArray]]: if self.__display_item: MimeTypes.mime_data_put_display_item(mime_data, self.__display_item) rgba_image_data = self.__thumbnail_source.thumbnail_data if self.__thumbnail_source else None thumbnail = Image.get_rgba_data_from_rgba( Image.scaled( Image.get_rgba_view_from_rgba_data(rgba_image_data), (80, 80))) if rgba_image_data is not None else None return True, thumbnail return False, None
def test_rgba_can_be_created_from_h5py_array(self) -> None: current_working_directory = os.getcwd() workspace_dir = os.path.join(current_working_directory, "__Test") if os.path.exists(workspace_dir): shutil.rmtree(workspace_dir) os.makedirs(workspace_dir) try: with h5py.File(os.path.join(workspace_dir, "file.h5"), "w") as f: dataset = f.create_dataset("data", data=numpy.ones((4, 4, 4), dtype=numpy.uint8)) Image.create_rgba_image_from_array(dataset) finally: # print(f"rmtree {workspace_dir}") shutil.rmtree(workspace_dir)
def calculate_data(): data = data_and_metadata.data if channel < 0 or channel > 3: return None if not Image.is_data_valid(data): return None if Image.is_shape_and_dtype_rgb(data.shape, data.dtype): if channel == 3: return numpy.ones(data.shape, int) return data[..., channel].astype(int) elif Image.is_shape_and_dtype_rgba(data.shape, data.dtype): return data[..., channel].astype(int) else: return None
def test_rebin_expand_has_even_expansion(self) -> None: # NOTE: statistical tests are only valid if expanded length is multiple of src length src = numpy.arange(0, 10) expanded = Image.rebin_1d(src, 50) self.assertAlmostEqual(numpy.mean(src), numpy.mean(expanded)) self.assertAlmostEqual(numpy.var(src), numpy.var(expanded)) src = numpy.arange(0, 10) expanded = Image.rebin_1d(src, 500) self.assertAlmostEqual(numpy.mean(src), numpy.mean(expanded)) self.assertAlmostEqual(numpy.var(src), numpy.var(expanded)) # test larger values to make sure linear mapping works (failed once) src = numpy.arange(0, 200) expanded = Image.rebin_1d(src, 600) self.assertAlmostEqual(numpy.mean(src), numpy.mean(expanded)) self.assertAlmostEqual(numpy.var(src), numpy.var(expanded))
def _repaint(self, drawing_context): """Repaint the canvas item. This will occur on a thread.""" # canvas size canvas_width = self.canvas_size[1] canvas_height = self.canvas_size[0] # draw background if self.background_color: with drawing_context.saver(): drawing_context.begin_path() drawing_context.move_to(0, 0) drawing_context.line_to(canvas_width, 0) drawing_context.line_to(canvas_width, canvas_height) drawing_context.line_to(0, canvas_height) drawing_context.close_path() drawing_context.fill_style = self.background_color drawing_context.fill() # draw the data, if any if (self.data is not None and len(self.data) > 0): # draw the histogram itself with drawing_context.saver(): drawing_context.begin_path() binned_data = Image.rebin_1d( self.data, int(canvas_width), self.__retained_rebin_1d ) if int(canvas_width) != self.data.shape[0] else self.data for i in range(canvas_width): drawing_context.move_to(i, canvas_height) drawing_context.line_to( i, canvas_height * (1 - binned_data[i])) drawing_context.line_width = 1 drawing_context.stroke_style = "#444" drawing_context.stroke()
def read_image_from_file(filename: pathlib.Path) -> _DataArrayType: if str(filename).startswith(":"): return numpy.zeros((20, 20, 4), numpy.uint8) image = imageio.imread(filename) if image is not None: image_u8 = imageio.core.image_as_uint(image) if len(image_u8.shape) == 3: rgba_image: numpy.typing.NDArray[numpy.uint8] if image_u8.shape[-1] == 3: rgba_image = numpy.empty(image_u8.shape[:-1] + (4, ), numpy.uint8) rgba_image[..., 0] = image_u8[..., 2] rgba_image[..., 1] = image_u8[..., 1] rgba_image[..., 2] = image_u8[..., 0] rgba_image[..., 3] = 255 else: assert image_u8.shape[-1] == 4 rgba_image = numpy.empty(image_u8.shape[:-1] + (4, ), numpy.uint8) rgba_image[..., 0] = image_u8[..., 3] rgba_image[..., 1] = image_u8[..., 2] rgba_image[..., 2] = image_u8[..., 1] rgba_image[..., 3] = image_u8[..., 0] if is_grayscale(rgba_image): rgba_image = Image.convert_to_grayscale(rgba_image) else: assert len(image_u8.shape) == 2 rgba_image = image_u8 assert rgba_image is not None return rgba_image raise IOError()
def function_rgba( red_data_and_metadata_in: _DataAndMetadataIndeterminateSizeLike, green_data_and_metadata_in: _DataAndMetadataIndeterminateSizeLike, blue_data_and_metadata_in: _DataAndMetadataIndeterminateSizeLike, alpha_data_and_metadata_in: _DataAndMetadataIndeterminateSizeLike ) -> DataAndMetadata.DataAndMetadata: red_data_and_metadata_c = DataAndMetadata.promote_indeterminate_array( red_data_and_metadata_in) green_data_and_metadata_c = DataAndMetadata.promote_indeterminate_array( green_data_and_metadata_in) blue_data_and_metadata_c = DataAndMetadata.promote_indeterminate_array( blue_data_and_metadata_in) alpha_data_and_metadata_c = DataAndMetadata.promote_indeterminate_array( alpha_data_and_metadata_in) shape = DataAndMetadata.determine_shape(red_data_and_metadata_c, green_data_and_metadata_c, blue_data_and_metadata_c) if shape is None: raise ValueError("RGBA: data shapes do not match or are indeterminate") red_data_and_metadata = DataAndMetadata.promote_constant( red_data_and_metadata_c, shape) green_data_and_metadata = DataAndMetadata.promote_constant( green_data_and_metadata_c, shape) blue_data_and_metadata = DataAndMetadata.promote_constant( blue_data_and_metadata_c, shape) alpha_data_and_metadata = DataAndMetadata.promote_constant( alpha_data_and_metadata_c, shape) channels = (blue_data_and_metadata, green_data_and_metadata, red_data_and_metadata, alpha_data_and_metadata) if any([ not Image.is_data_valid(data_and_metadata.data) for data_and_metadata in channels ]): raise ValueError("RGB: invalid data") rgba_image = numpy.empty(shape + (4, ), numpy.uint8) for channel_index, channel in enumerate(channels): data = channel._data_ex if data.dtype.kind in 'iu': rgba_image[..., channel_index] = numpy.clip(data, 0, 255) elif data.dtype.kind in 'f': rgba_image[..., channel_index] = numpy.clip(numpy.multiply(data, 255), 0, 255) return DataAndMetadata.new_data_and_metadata( rgba_image, intensity_calibration=red_data_and_metadata.intensity_calibration, dimensional_calibrations=red_data_and_metadata.dimensional_calibrations )
def test_scale_linear_is_symmetry(self) -> None: src1 = numpy.zeros((8, 8)) src2 = numpy.zeros((9, 9)) src1[3:5, 3:5] = 1 src2[3:6, 3:6] = 1 src1s: _ImageDataType = typing.cast(_ImageDataType, Image.scaled(src1, (12, 12), 'linear')*1000).astype(numpy.int32) src2s: _ImageDataType = typing.cast(_ImageDataType, Image.scaled(src1, (12, 12), 'linear')*1000).astype(numpy.int32) src1t: _ImageDataType = typing.cast(_ImageDataType, Image.scaled(src1, (13, 13), 'linear')*1000).astype(numpy.int32) src2t: _ImageDataType = typing.cast(_ImageDataType, Image.scaled(src1, (13, 13), 'linear')*1000).astype(numpy.int32) self.assertTrue(numpy.array_equal(src1s[0:6, 0:6], src1s[0:6, 12:5:-1])) self.assertTrue(numpy.array_equal(src1s[0:6, 0:6], src1s[12:5:-1, 12:5:-1])) self.assertTrue(numpy.array_equal(src1s[0:6, 0:6], src1s[12:5:-1, 0:6])) self.assertTrue(numpy.array_equal(src2s[0:6, 0:6], src2s[0:6, 12:5:-1])) self.assertTrue(numpy.array_equal(src2s[0:6, 0:6], src2s[12:5:-1, 12:5:-1])) self.assertTrue(numpy.array_equal(src2s[0:6, 0:6], src2s[12:5:-1, 0:6])) self.assertTrue(numpy.array_equal(src1t[0:6, 0:6], src1t[0:6, 13:6:-1])) self.assertTrue(numpy.array_equal(src1t[0:6, 0:6], src1t[13:6:-1, 13:6:-1])) self.assertTrue(numpy.array_equal(src1t[0:6, 0:6], src1t[13:6:-1, 0:6])) self.assertTrue(numpy.array_equal(src2t[0:6, 0:6], src2t[0:6, 13:6:-1])) self.assertTrue(numpy.array_equal(src2t[0:6, 0:6], src2t[13:6:-1, 13:6:-1])) self.assertTrue(numpy.array_equal(src2t[0:6, 0:6], src2t[13:6:-1, 0:6]))
def plot_features(self, data: _NDArray, offset_m: Geometry.FloatPoint, fov_size_nm: Geometry.FloatSize, extra_nm: Geometry.FloatPoint, center_nm: Geometry.FloatPoint, used_size: Geometry.IntSize) -> None: range_nm = 80 # print(f"{offset_m * 1E9}, {fov_size_nm} {extra_nm}") # calculate destination bounds in nm left_nm = -offset_m.x * 1E9 - (fov_size_nm.width + extra_nm.x) / 2 top_nm = -offset_m.y * 1E9 - (fov_size_nm.height + extra_nm.y) / 2 right_nm = left_nm + fov_size_nm.width + extra_nm.x bottom_nm = top_nm + fov_size_nm.height + extra_nm.y # print(f"{left_nm}, {top_nm} x {right_nm - left_nm}, {bottom_nm - top_nm}") # map into fractional coordinates (0, 1) of source area where (-range_nm, range_nm) is the range in both axes intersection_left_nm = max(left_nm, -range_nm) intersection_top_nm = max(top_nm, -range_nm) intersection_right_nm = min(right_nm, range_nm) intersection_bottom_nm = min(bottom_nm, range_nm) # print(f"{intersection_left_nm}, {intersection_top_nm} x {intersection_right_nm - intersection_left_nm}, {intersection_bottom_nm - intersection_top_nm}") if intersection_left_nm < intersection_right_nm and intersection_top_nm < intersection_bottom_nm: src_left = int(self.__amorphous.shape[1] * max( (intersection_left_nm + range_nm) / (range_nm * 2), 0)) src_top = int(self.__amorphous.shape[0] * max( (intersection_top_nm + range_nm) / (range_nm * 2), 0)) src_right = int(self.__amorphous.shape[1] * min( (intersection_right_nm + range_nm) / (range_nm * 2), 1)) src_bottom = int(self.__amorphous.shape[0] * min( (intersection_bottom_nm + range_nm) / (range_nm * 2), 1)) dst_left = int(data.shape[1] * max( (intersection_left_nm - left_nm) / (right_nm - left_nm), 0)) dst_top = int(data.shape[0] * max( (intersection_top_nm - top_nm) / (bottom_nm - top_nm), 0)) dst_right = int(data.shape[1] * min( (intersection_right_nm - left_nm) / (right_nm - left_nm), 1)) dst_bottom = int(data.shape[0] * min( (intersection_bottom_nm - top_nm) / (bottom_nm - top_nm), 1)) # print(f"{src_left}, {src_top} x {src_right - src_left}, {src_bottom - src_top} => {dst_left}, {dst_top} x {dst_right - dst_left}, {dst_bottom - dst_top}") src = self.__amorphous[src_top:src_bottom, src_left:src_right] src = scipy.ndimage.gaussian_filter(src, 3) # may be faster, but doesn't work for non-square src # src = numpy.fft.ifft2(scipy.ndimage.fourier_gaussian(src * 1j, 3)).real src = 4 * (src - numpy.amin(src)) / numpy.ptp(src) data[dst_top:dst_bottom, dst_left:dst_right] = Image.scaled( src, (dst_bottom - dst_top, dst_right - dst_left))
def test_scale_cubic_is_symmetry(self): src1 = numpy.zeros((8, 8)) src2 = numpy.zeros((9, 9)) src1[3:5, 3:5] = 1 src2[3:6, 3:6] = 1 src1s = (Image.scaled(src1, (12, 12), 'cubic') * 1000).astype(numpy.int32) src2s = (Image.scaled(src1, (12, 12), 'cubic') * 1000).astype(numpy.int32) src1t = (Image.scaled(src1, (13, 13), 'cubic') * 1000).astype(numpy.int32) src2t = (Image.scaled(src1, (13, 13), 'cubic') * 1000).astype(numpy.int32) self.assertTrue(numpy.array_equal(src1s[0:6, 0:6], src1s[0:6, 12:5:-1])) self.assertTrue( numpy.array_equal(src1s[0:6, 0:6], src1s[12:5:-1, 12:5:-1])) self.assertTrue(numpy.array_equal(src1s[0:6, 0:6], src1s[12:5:-1, 0:6])) self.assertTrue(numpy.array_equal(src2s[0:6, 0:6], src2s[0:6, 12:5:-1])) self.assertTrue( numpy.array_equal(src2s[0:6, 0:6], src2s[12:5:-1, 12:5:-1])) self.assertTrue(numpy.array_equal(src2s[0:6, 0:6], src2s[12:5:-1, 0:6])) self.assertTrue(numpy.array_equal(src1t[0:6, 0:6], src1t[0:6, 13:6:-1])) self.assertTrue( numpy.array_equal(src1t[0:6, 0:6], src1t[13:6:-1, 13:6:-1])) self.assertTrue(numpy.array_equal(src1t[0:6, 0:6], src1t[13:6:-1, 0:6])) self.assertTrue(numpy.array_equal(src2t[0:6, 0:6], src2t[0:6, 13:6:-1])) self.assertTrue( numpy.array_equal(src2t[0:6, 0:6], src2t[13:6:-1, 13:6:-1])) self.assertTrue(numpy.array_equal(src2t[0:6, 0:6], src2t[13:6:-1, 0:6]))
def get_processed_data(self, data_sources, values): data = data_sources[0].data if data is None: return None img = Image.create_rgba_image_from_array(data) # inefficient since we're just converting back to gray if id(img) == id(data): img = img.copy() if id(img.base) == id(data): img = img.copy() img = img.view(numpy.uint8).reshape(img.shape + (4,)) # expand the color into uint8s img_gray = cv2.cvtColor(img, cv.CV_RGB2GRAY) img_gray = cv2.equalizeHist(img_gray) rects = detect(img_gray, relative_file(__file__, "haarcascade_frontalface_alt.xml")) draw_rects(img, rects, (0, 255, 0)) return img
def get_processed_data(self, data_sources, values): data = data_sources[0].data if data is None: return None img = Image.create_rgba_image_from_array( data) # inefficient since we're just converting back to gray if id(img) == id(data): img = img.copy() if id(img.base) == id(data): img = img.copy() img = img.view(numpy.uint8).reshape( img.shape + (4, )) # expand the color into uint8s img_gray = cv2.cvtColor(img, cv.CV_RGB2GRAY) img_gray = cv2.equalizeHist(img_gray) rects = detect( img_gray, relative_file(__file__, "haarcascade_frontalface_alt.xml")) draw_rects(img, rects, (0, 255, 0)) return img
def read_data_elements(self, ui, extension, path): data = None try: data = Image.read_image_from_file(ui, path) except Exception as e: pass if data is not None: data_element = dict() data_element["version"] = 1 data_element["data"] = data if os.path.exists(path) or path.startswith(":"): # check for colon is for testing try: file_datetime = datetime.datetime.fromtimestamp(os.path.getmtime(path)) except: file_datetime = None if file_datetime is not None: data_element["datetime_modified"] = Utility.get_datetime_item_from_datetime(file_datetime) return [data_element] return list()
def calculate_statistics(display_data_and_metadata_func, display_data_range, region, displayed_intensity_calibration): display_data_and_metadata = display_data_and_metadata_func() data = display_data_and_metadata.data if display_data_and_metadata else None data_range = display_data_range if data is not None and data.size > 0 and displayed_intensity_calibration: mean = numpy.mean(data) std = numpy.std(data) rms = numpy.sqrt(numpy.mean(numpy.square( numpy.absolute(data)))) sum_data = mean * functools.reduce( operator.mul, Image.dimensional_shape_from_shape_and_dtype( data.shape, data.dtype)) if region is None: data_min, data_max = data_range if data_range is not None else ( None, None) else: data_min, data_max = numpy.amin(data), numpy.amax(data) mean_str = displayed_intensity_calibration.convert_to_calibrated_value_str( mean) std_str = displayed_intensity_calibration.convert_to_calibrated_value_str( std) data_min_str = displayed_intensity_calibration.convert_to_calibrated_value_str( data_min) data_max_str = displayed_intensity_calibration.convert_to_calibrated_value_str( data_max) rms_str = displayed_intensity_calibration.convert_to_calibrated_value_str( rms) sum_data_str = displayed_intensity_calibration.convert_to_calibrated_value_str( sum_data) return { "mean": mean_str, "std": std_str, "min": data_min_str, "max": data_max_str, "rms": rms_str, "sum": sum_data_str } return dict()
def calculate_data(): rgb_image = numpy.empty(shape + (3, ), numpy.uint8) channels = (blue_data_and_metadata, green_data_and_metadata, red_data_and_metadata) for channel_index, channel in enumerate(channels): data = channel.data if not Image.is_data_valid(data): return None if tuple(data.shape) != shape: return None if data.dtype.kind in 'iu': rgb_image[..., channel_index] = numpy.clip(data, 0, 255) elif data.dtype.kind in 'f': rgb_image[..., channel_index] = numpy.clip( numpy.multiply(data, 255), 0, 255) else: return None return rgb_image
def calculate_statistics(display_data_and_metadata_func: typing.Callable[[], typing.Optional[DataAndMetadata.DataAndMetadata]], display_data_range: typing.Optional[typing.Tuple[float, float]], region: typing.Optional[Graphics.Graphic], displayed_intensity_calibration: typing.Optional[Calibration.Calibration]) -> typing.Dict[str, str]: display_data_and_metadata = display_data_and_metadata_func() data = display_data_and_metadata.data if display_data_and_metadata else None data_range = display_data_range if data is not None and data.size > 0 and displayed_intensity_calibration: mean = numpy.mean(data) std = numpy.std(data) rms = numpy.sqrt(numpy.mean(numpy.square(numpy.absolute(data)))) dimensional_shape = Image.dimensional_shape_from_shape_and_dtype(data.shape, data.dtype) or (1, 1) sum_data = mean * functools.reduce(operator.mul, dimensional_shape) if region is None: data_min, data_max = data_range if data_range is not None else (None, None) else: data_min, data_max = numpy.amin(data), numpy.amax(data) mean_str = displayed_intensity_calibration.convert_to_calibrated_value_str(mean) std_str = displayed_intensity_calibration.convert_to_calibrated_value_str(std) data_min_str = displayed_intensity_calibration.convert_to_calibrated_value_str(data_min) if data_min is not None else str() data_max_str = displayed_intensity_calibration.convert_to_calibrated_value_str(data_max) if data_max is not None else str() rms_str = displayed_intensity_calibration.convert_to_calibrated_value_str(rms) sum_data_str = displayed_intensity_calibration.convert_to_calibrated_value_str(sum_data) return { "mean": mean_str, "std": std_str, "min": data_min_str, "max": data_max_str, "rms": rms_str, "sum": sum_data_str } return dict()
def convert_data_element_to_data_and_metadata_1(data_element) -> DataAndMetadata.DataAndMetadata: """Convert a data element to xdata. No data copying occurs. The data element can have the following keys: data (required) is_sequence, collection_dimension_count, datum_dimension_count (optional description of the data) spatial_calibrations (optional list of spatial calibration dicts, scale, offset, units) intensity_calibration (optional intensity calibration dict, scale, offset, units) metadata (optional) properties (get stored into metadata.hardware_source) one of either timestamp or datetime_modified if datetime_modified (dst, tz) it is converted and used as timestamp then timezone gets stored into metadata.description.timezone. """ # data. takes ownership. data = data_element["data"] dimensional_shape = Image.dimensional_shape_from_data(data) is_sequence = data_element.get("is_sequence", False) dimension_count = len(Image.dimensional_shape_from_data(data)) adjusted_dimension_count = dimension_count - (1 if is_sequence else 0) collection_dimension_count = data_element.get("collection_dimension_count", 2 if adjusted_dimension_count in (3, 4) else 0) datum_dimension_count = data_element.get("datum_dimension_count", adjusted_dimension_count - collection_dimension_count) data_descriptor = DataAndMetadata.DataDescriptor(is_sequence, collection_dimension_count, datum_dimension_count) # dimensional calibrations dimensional_calibrations = None if "spatial_calibrations" in data_element: dimensional_calibrations_list = data_element.get("spatial_calibrations") if len(dimensional_calibrations_list) == len(dimensional_shape): dimensional_calibrations = list() for dimension_calibration in dimensional_calibrations_list: offset = float(dimension_calibration.get("offset", 0.0)) scale = float(dimension_calibration.get("scale", 1.0)) units = dimension_calibration.get("units", "") units = str(units) if units is not None else str() if scale != 0.0: dimensional_calibrations.append(Calibration.Calibration(offset, scale, units)) else: dimensional_calibrations.append(Calibration.Calibration()) # intensity calibration intensity_calibration = None if "intensity_calibration" in data_element: intensity_calibration_dict = data_element.get("intensity_calibration") offset = float(intensity_calibration_dict.get("offset", 0.0)) scale = float(intensity_calibration_dict.get("scale", 1.0)) units = intensity_calibration_dict.get("units", "") units = str(units) if units is not None else str() if scale != 0.0: intensity_calibration = Calibration.Calibration(offset, scale, units) # properties (general tags) metadata = dict() if "metadata" in data_element: metadata.update(Utility.clean_dict(data_element.get("metadata"))) if "properties" in data_element and data_element["properties"]: hardware_source_metadata = metadata.setdefault("hardware_source", dict()) hardware_source_metadata.update(Utility.clean_dict(data_element.get("properties"))) # dates are _local_ time and must use this specific ISO 8601 format. 2013-11-17T08:43:21.389391 # time zones are offsets (east of UTC) in the following format "+HHMM" or "-HHMM" # daylight savings times are time offset (east of UTC) in format "+MM" or "-MM" # timezone is for conversion and is the Olson timezone string. # datetime.datetime.strptime(datetime.datetime.isoformat(datetime.datetime.now()), "%Y-%m-%dT%H:%M:%S.%f" ) # datetime_modified, datetime_modified_tz, datetime_modified_dst, datetime_modified_tzname is the time at which this image was modified. # datetime_original, datetime_original_tz, datetime_original_dst, datetime_original_tzname is the time at which this image was created. timestamp = data_element.get("timestamp", datetime.datetime.utcnow()) datetime_item = data_element.get("datetime_modified", Utility.get_datetime_item_from_utc_datetime(timestamp)) local_datetime = Utility.get_datetime_from_datetime_item(datetime_item) dst_value = datetime_item.get("dst", "+00") tz_value = datetime_item.get("tz", "+0000") timezone = datetime_item.get("timezone") time_zone = { "dst": dst_value, "tz": tz_value} if timezone is not None: time_zone["timezone"] = timezone # note: dst is informational only; tz already include dst tz_adjust = (int(tz_value[1:3]) * 60 + int(tz_value[3:5])) * (-1 if tz_value[0] == '-' else 1) utc_datetime = local_datetime - datetime.timedelta(minutes=tz_adjust) # tz_adjust already contains dst_adjust timestamp = utc_datetime return DataAndMetadata.new_data_and_metadata(data, intensity_calibration=intensity_calibration, dimensional_calibrations=dimensional_calibrations, metadata=metadata, timestamp=timestamp, data_descriptor=data_descriptor, timezone=timezone, timezone_offset=tz_value)
def is_grayscale(data: _DataArrayType) -> bool: if Image.is_data_rgb(data) or Image.is_data_rgba(data): return numpy.array_equal(data[..., 0], data[..., 1]) and numpy.array_equal( data[..., 1], data[..., 2]) return True