def testGeneral(self): # --------------------- # pulse-resolved data # --------------------- data = ProcessedData(1234) self.assertEqual(1234, data.tid) self.assertEqual(0, data.n_pulses) data.image = ImageData.from_array(np.zeros((1, 2, 2))) self.assertEqual(1, data.n_pulses) data = ProcessedData(1235) data.image = ImageData.from_array(np.zeros((3, 2, 2))) self.assertEqual(3, data.n_pulses) # --------------------- # train-resolved data # --------------------- data = ProcessedData(1236) data.image = ImageData.from_array(np.zeros((2, 2))) self.assertEqual(1236, data.tid) self.assertEqual(1, data.n_pulses)
def testInitWithSpecifiedParametersPS(self): with self.assertRaises(ValueError): ImageData.from_array(np.ones((2, 2, 2)), sliced_indices=[0, 1, 2]) with self.assertRaises(ValueError): ImageData.from_array(np.ones((2, 2, 2)), sliced_indices=[1, 1, 1]) imgs = np.ones((3, 2, 3)) imgs[:, 0, :] = 2 image_mask = np.zeros((2, 3), dtype=np.bool) image_mask[::2, ::2] = True image_data = ImageData.from_array(imgs, image_mask=image_mask, threshold_mask=(0, 1), poi_indices=[0, 1]) self.assertEqual(2e-3, image_data.pixel_size) self.assertIsInstance(image_data.images, list) self.assertEqual(3, image_data.n_images) self.assertListEqual([0, 1, 2], image_data.sliced_indices) np.testing.assert_array_equal(np.array([[np.nan, np.nan, np.nan], [1., 1., 1.]]), image_data.images[0]) np.testing.assert_array_equal(np.array([[np.nan, np.nan, np.nan], [1., 1., 1.]]), image_data.images[1]) self.assertIsNone(image_data.images[2]) np.testing.assert_array_equal(np.array([[2., 2., 2.], [1., 1., 1.]]), image_data.mean) np.testing.assert_array_equal(np.array([[np.nan, np.nan, np.nan], [1., 1., 1.]]), image_data.masked_mean) self.assertIsNone(image_data.gain_mean) self.assertIsNone(image_data.offset_mean) self.assertEqual((0, 1), image_data.threshold_mask)
def processed_data(cls, tid, shape, *, gen='random', dtype=config['SOURCE_PROC_IMAGE_DTYPE'], roi_histogram=False, histogram=False, correlation=False, binning=False, **kwargs): processed = ProcessedData(tid) imgs = cls._gen_images(gen, shape, dtype) processed.image = ImageData.from_array(imgs, **kwargs) if roi_histogram: pass if histogram: hist = processed.hist hist.hist = np.arange(10) hist.bin_centers = np.arange(10) / 100. hist.mean, hist.median, hist.std = 1., 0, 0.1 if correlation: pass if binning: pass return processed
def testSetImage(self): widget = ImageAnalysis() item = widget._mask_item with self.assertRaisesRegex(TypeError, "ImageData"): widget.setImage([1, 2]) with patch.object(item, "maybeInitializeMask") as init: with patch.object(item, "setMask") as set_mask: # test set valid data image_data = ImageData.from_array(np.ones((2, 10, 10))) widget.setImage(image_data) np.testing.assert_array_equal(image_data.image_mask_in_modules, widget._mask_in_modules) np.testing.assert_array_equal(image_data.masked_mean, widget._image) init.assert_called_once() init.reset_mock() set_mask.assert_not_called() # test set image with different shape with patch( "extra_foam.gui.items.GeometryItem.geometry") as geom: image_data = ImageData.from_array(np.ones((2, 4, 4))) # image_mask_in_modules is None widget.setImage(image_data) geom.output_array_for_position_fast.assert_not_called() geom.position_all_modules.assert_not_called() init.assert_called_once() init.reset_mock() set_mask.assert_not_called() # set image_mask_in_modules image_data = ImageData.from_array(np.ones((2, 8, 8))) image_data.image_mask_in_modules = np.ones((4, 2, 2)) widget.setImage(image_data) geom.output_array_for_position_fast.assert_called_once() geom.position_all_modules.assert_called_once() init.assert_called_once() init.reset_mock() set_mask.assert_called_once() # test set with image = None image_data = ImageData() widget.setImage(image_data) self.assertIsNone(widget._mask_in_modules) self.assertIsNone(widget._image) init.assert_not_called()
def testInitWithSpecifiedParametersTS(self): with self.assertRaises(ValueError): ImageData.from_array(np.ones((2, 2)), sliced_indices=[0]) img = np.array([[2, 1], [1, 1]]) image_data = ImageData.from_array(img, threshold_mask=(0, 1)) self.assertEqual([0], image_data.sliced_indices) self.assertEqual([None], image_data.images) self.assertEqual(1, image_data.n_images) np.testing.assert_array_equal(np.array([[2., 1.], [1., 1.]]), image_data.mean) np.testing.assert_array_equal(np.array([[np.nan, 1.], [1., 1.]]), image_data.masked_mean) self.assertEqual((0, 1), image_data.threshold_mask)
def testInitWithSpecifiedParameters(self): # --------------------- # pulse-resolved data # --------------------- with self.assertRaises(ValueError): ImageData.from_array(np.ones((2, 2, 2)), sliced_indices=[0, 1, 2]) with self.assertRaises(ValueError): ImageData.from_array(np.ones((2, 2, 2)), sliced_indices=[1, 1, 1]) imgs = np.ones((3, 2, 2)) imgs[:, 0, :] = 2 image_data = ImageData.from_array(imgs, threshold_mask=(0, 1), poi_indices=[0, 1]) self.assertEqual(2e-3, image_data.pixel_size) self.assertIsInstance(image_data.images, list) self.assertEqual(3, image_data.n_images) self.assertListEqual([0, 1, 2], image_data.sliced_indices) np.testing.assert_array_equal(np.array([[2., 2.], [1., 1.]]), image_data.images[0]) np.testing.assert_array_equal(np.array([[2., 2.], [1., 1.]]), image_data.images[1]) self.assertIsNone(image_data.images[2]) np.testing.assert_array_equal(np.array([[2., 2.], [1., 1.]]), image_data.mean) np.testing.assert_array_equal(np.array([[0., 0.], [1., 1.]]), image_data.masked_mean) self.assertIsNone(image_data.gain_mean) self.assertIsNone(image_data.offset_mean) self.assertEqual((0, 1), image_data.threshold_mask) # --------------------- # train-resolved data # --------------------- with self.assertRaises(ValueError): ImageData.from_array(np.ones((2, 2)), sliced_indices=[0]) img = np.array([[2, 1], [1, 1]]) image_data = ImageData.from_array(img, threshold_mask=(0, 1)) self.assertEqual([0], image_data.sliced_indices) self.assertEqual([None], image_data.images) self.assertEqual(1, image_data.n_images) np.testing.assert_array_equal(np.array([[2., 1.], [1., 1.]]), image_data.mean) np.testing.assert_array_equal(np.array([[0., 1.], [1., 1.]]), image_data.masked_mean) self.assertEqual((0, 1), image_data.threshold_mask)
def testFromArray(self): with self.assertRaises(TypeError): ImageData.from_array() with self.assertRaises(ValueError): ImageData.from_array(np.ones(2)) with self.assertRaises(ValueError): ImageData.from_array(np.ones((2, 2, 2, 2))) image_data = ImageData.from_array(np.ones((2, 2, 3))) self.assertEqual((2, 3), image_data.mask.shape) image_data = ImageData.from_array(np.ones((3, 2))) self.assertEqual((3, 2), image_data.mask.shape)
def testFromArray(self): with self.assertRaises(TypeError): ImageData.from_array() with self.assertRaises(ValueError): ImageData.from_array(np.ones(2)) with self.assertRaises(ValueError): ImageData.from_array(np.ones((2, 2, 2, 2)))
def testBulletinView(self): processed = ProcessedData(1357) processed.image = ImageData.from_array(np.ones((10, 4, 4), np.float32)) processed.image.dark_count = 99 processed.image.n_dark_pulses = 10 processed.pidx.mask([1, 3, 5, 6]) self.gui._queue.append(processed) self.image_tool.updateWidgetsF() view = self.image_tool._bulletin_view self.assertEqual(1357, int(view._latest_tid.intValue())) self.assertEqual(10, int(view._n_total_pulses.intValue())) self.assertEqual(6, int(view._n_kept_pulses.intValue())) self.assertEqual(99, int(view._dark_train_counter.intValue())) self.assertEqual(10, int(view._n_dark_pulses.intValue()))
def processed_data(cls, tid, shape, *, gen='random', dtype=config['SOURCE_PROC_IMAGE_DTYPE'], roi_histogram=False, histogram=False, correlation=False, binning=False, **kwargs): processed = ProcessedData(tid) imgs = cls._gen_images(gen, shape, dtype) processed.image = ImageData.from_array(imgs, **kwargs) if roi_histogram: pass if histogram: hist = processed.hist hist.hist = np.arange(10) hist.bin_centers = np.arange(10) / 100. hist.mean, hist.median, hist.std = 1., 0, 0.1 if correlation: corr_resolution = 2 for i in range(2): corr = processed.corr[i] if i == 0: data = SimplePairSequence() else: data = OneWayAccuPairSequence(corr_resolution) for j in range(5): data.append((j, 5 * j)) corr.x, corr.y = data.data() corr.source = f"abc - {i}" corr.resolution = 0 if i == 0 else corr_resolution if binning: pass return processed
def testBulletinView(self): processed = ProcessedData(1357) processed.image = ImageData.from_array(np.ones((10, 4, 4), np.float32)) processed.image.dark_count = 99 processed.image.n_dark_pulses = 10 processed.pidx.mask([1, 3, 5, 6]) self.gui._queue.append(processed) self.image_tool.updateWidgetsF() view = self.image_tool._bulletin_view self.assertEqual(1357, int(view._displayed_tid.intValue())) self.assertEqual(10, int(view._n_total_pulses.intValue())) self.assertEqual(6, int(view._n_kept_pulses.intValue())) self.assertEqual(99, int(view._dark_train_counter.intValue())) self.assertEqual(10, int(view._n_dark_pulses.intValue())) with patch.object(view._mon, "reset_process_count") as reset: view._reset_process_count_btn.clicked.emit() reset.assert_called_once()
def data_with_assembled(cls, tid, shape, *, src_type=DataSource.BRIDGE, dtype=config['SOURCE_PROC_IMAGE_DTYPE'], gen='random', slicer=None, with_xgm=False, with_digitizer=False, **kwargs): imgs = cls._gen_images(gen, shape, dtype) processed = ProcessedData(tid) processed.image = ImageData.from_array(imgs, **kwargs) if imgs.ndim == 2: slicer = None else: slicer = slice(None, None) if slicer is None else slicer src_list = [('Foo', 'oof'), ('Bar', 'rab'), ('karaboFAI', 'extra_foam')] src_name, key_name = random.choice(src_list) catalog = SourceCatalog() ctg = 'ABCD' src = f'{src_name} {key_name}' catalog.add_item(SourceItem(ctg, src_name, [], key_name, slicer, None)) catalog._main_detector = src n_pulses = processed.n_pulses if with_xgm: # generate XGM data processed.pulse.xgm.intensity = np.random.rand(n_pulses) processed.xgm.intensity = random.random() processed.xgm.x = random.random() processed.xgm.y = random.random() if with_digitizer: # generate digitizer data digitizer = processed.pulse.digitizer digitizer.ch_normalizer = 'B' for ch in digitizer: digitizer[ch].pulse_integral = np.random.rand(n_pulses) data = { 'processed': processed, 'catalog': catalog, 'meta': { src: { 'timestamp.tid': tid, 'source_type': src_type, } }, 'raw': { src: dict() }, 'assembled': { 'data': imgs, } } if imgs.ndim == 2: data['assembled']['sliced'] = imgs else: data['assembled']['sliced'] = imgs[slicer] return data, processed
def testSaveLoadImageMask(self, mocked_pub, mocked_set_mask, mocked_open, mocked_save): def save_mask_in_file(_fp, arr): _fp.seek(0) np.save(_fp, arr) _fp.seek(0) widget = ImageAnalysis() fp = tempfile.NamedTemporaryFile(suffix=".npy") img = np.arange(100, dtype=np.float).reshape(10, 10) # if image_data is None, it does not raise but only logger.error() with self.assertLogs(logger, level="ERROR") as cm: widget.saveImageMask() self.assertEqual('Image mask does not exist without an image!', cm.output[0].split(':')[-1]) with self.assertLogs(logger, level="ERROR") as cm: widget.loadImageMask() self.assertEqual(cm.output[0].split(':')[-1], 'Cannot load image mask without image!') widget.setImage(ImageData.from_array(img)) # -------------------- # test failing to save # -------------------- # test saving a mask in modules without geometry widget._mask_save_in_modules = True with self.assertLogs(logger, level='ERROR') as cm: widget.saveImageMask() # geometry file is not specified self.assertIn('Failed to create geometry to dismantle image mask', cm.output[0]) # -------------------- # test fail to load # -------------------- # the IOError mocked_open.return_value = ['abc'] with self.assertLogs(logger, level="ERROR") as cm: widget.loadImageMask() self.assertIn('Cannot load mask from abc', cm.output[0]) # test mask data with dimension not equal to 2 or 3 mocked_open.return_value = [fp.name] new_mask = np.ones(3, dtype=bool) save_mask_in_file(fp, new_mask) with self.assertLogs(logger, level='ERROR') as cm: widget.loadImageMask() self.assertIn('Expect array with dimensions (2, 3): actual 1', cm.output[0]) mocked_set_mask.assert_not_called() # test loading a mask in modules without geometry new_mask = np.ones((3, 3, 3), dtype=bool) save_mask_in_file(fp, new_mask) with patch("extra_foam.gui.items.GeometryItem._detector", new_callable=PropertyMock, create=True) as mocked: with self.assertLogs(logger, level='ERROR') as cm: mocked.return_value = "FastCCD" widget._require_geometry = False widget.loadImageMask() self.assertIn( 'Only detectors with a geometry can have image mask in modules', cm.output[0]) with self.assertLogs(logger, level='ERROR') as cm: mocked.return_value = "LPD" widget._require_geometry = True widget.loadImageMask() # geometry file is not specified self.assertIn( 'Failed to create geometry to assemble image mask', cm.output[0]) mocked_set_mask.assert_not_called() # test (assembled) mask shape is different from the image new_mask = np.ones((3, 3), dtype=bool) save_mask_in_file(fp, new_mask) with self.assertLogs(logger, level='ERROR') as cm: widget.loadImageMask() self.assertIn( 'Shape of the image mask (3, 3) is different from the image (10, 10)', cm.output[0]) mocked_set_mask.assert_not_called() # -------------------- # test save and load # -------------------- # first save a valid assembled mask widget._mask_save_in_modules = False mocked_save.return_value = [fp.name] with self.assertLogs(logger, level="INFO"): widget.saveImageMask() # then load fp.seek(0) with self.assertLogs(logger, level="INFO"): widget.loadImageMask() mocked_set_mask.assert_called_once() mocked_set_mask.reset_mock() # save and load another mask mask_item = widget._mask_item mask_item._mask.setPixelColor(0, 0, mask_item._fill_color) mask_item._mask.setPixelColor(5, 5, mask_item._fill_color) fp.seek(0) widget.saveImageMask() fp.seek(0) widget.loadImageMask() mocked_set_mask.assert_called_once() mocked_set_mask.reset_mock() # ----------------------------- # test saving mask in modules # ----------------------------- widget._mask_save_in_modules = True def dismantle_side_effect(*args, **kwargs): raise ValueError with patch("extra_foam.gui.items.GeometryItem.geometry") as geom: mask_in_modules = np.ones_like((3, 3, 3), dtype=bool) geom.output_array_for_dismantle_fast.return_value = mask_in_modules widget.saveImageMask() geom.output_array_for_dismantle_fast.assert_called_once() geom.dismantle_all_modules.assert_called_once() geom.dismantle_all_modules.side_effect = dismantle_side_effect with self.assertLogs(logger, level='ERROR') as cm: widget.saveImageMask() self.assertIn("Geometry does not match the assembled image", cm.output[0]) # ----------------------------- # test loading mask in modules # ----------------------------- new_mask = np.ones((3, 3, 3), dtype=bool) save_mask_in_file(fp, new_mask) fp.seek(0) with patch("extra_foam.gui.items.GeometryItem.geometry") as geom: assembled_mask = np.ones_like(img, dtype=bool) geom.output_array_for_position_fast.return_value = assembled_mask widget.loadImageMask() geom.output_array_for_position_fast.assert_called_once() geom.position_all_modules.assert_called_once() mocked_set_mask.assert_called_once_with(assembled_mask) fp.close()