def test_03_03_color_mask(self): image_set_list = cpi.ImageSetList() image_set = image_set_list.get_image_set(0) np.random.seed(0) pixel_data = np.random.uniform(size=(10, 15, 3)).astype(np.float32) image_set.add(IMAGE_NAME, cpi.Image(pixel_data)) masking_image = np.random.uniform(size=(10, 15)) image_set.add(MASKING_IMAGE_NAME, cpi.Image(masking_image)) expected_mask = masking_image > 0.5 pipeline = cpp.Pipeline() module = M.MaskImage() module.source_choice.value = M.IO_IMAGE module.object_name.value = OBJECTS_NAME module.image_name.value = IMAGE_NAME module.masking_image_name.value = MASKING_IMAGE_NAME module.masked_image_name.value = MASKED_IMAGE_NAME module.invert_mask.value = False module.module_num = 1 workspace = cpw.Workspace( pipeline, module, image_set, cpo.ObjectSet(), cpmeas.Measurements(), image_set_list, ) module.run(workspace) masked_image = workspace.image_set.get_image(MASKED_IMAGE_NAME) self.assertTrue(isinstance(masked_image, cpi.Image)) self.assertTrue( np.all(masked_image.pixel_data[expected_mask, :] == pixel_data[ expected_mask, :])) self.assertTrue( np.all(masked_image.pixel_data[~expected_mask, :] == 0)) self.assertTrue(np.all(masked_image.mask == expected_mask)) self.assertFalse(masked_image.has_masking_objects)
def make_workspace(self, input_pixels, crop_image=None, cropping=None, crop_objects=None): """Return a workspace with the given images installed and the crop module""" image_set_list = cpi.ImageSetList() image_set = image_set_list.get_image_set(0) module = cpmc.Crop() module.module_num = 1 image_set.add(INPUT_IMAGE, cpi.Image(input_pixels)) module.image_name.value = INPUT_IMAGE module.cropped_image_name.value = OUTPUT_IMAGE if crop_image is not None: image_set.add(CROP_IMAGE, cpi.Image(crop_image)) module.image_mask_source.value = CROP_IMAGE if cropping is not None: image_set.add( CROPPING, cpi.Image(np.zeros(cropping.shape), crop_mask=cropping)) module.cropping_mask_source.value = CROPPING object_set = cpo.ObjectSet() if crop_objects is not None: objects = cpo.Objects() objects.segmented = crop_objects object_set.add_objects(objects, CROP_OBJECTS) pipeline = cpp.Pipeline() def callback(caller, event): self.assertFalse(isinstance(event, cpp.RunExceptionEvent)) pipeline.add_listener(callback) pipeline.add_module(module) m = cpm.Measurements() workspace = cpw.Workspace(pipeline, module, image_set, object_set, m, image_set_list) m.add_measurement(cpm.IMAGE, cpm.GROUP_INDEX, 0, image_set_number=1) m.add_measurement(cpm.IMAGE, cpm.GROUP_NUMBER, 1, image_set_number=1) return workspace, module
def execute(self, image, function, mask=None, custom_repeats=None, scale=None, module=None): """Run the morph module on an input and return the resulting image""" INPUT_IMAGE_NAME = "input" OUTPUT_IMAGE_NAME = "output" if module is None: module = morph.Morph() module.functions[0].function.value = function module.image_name.value = INPUT_IMAGE_NAME module.output_image_name.value = OUTPUT_IMAGE_NAME if custom_repeats is None: module.functions[0].repeats_choice.value = morph.R_ONCE elif custom_repeats == -1: module.functions[0].repeats_choice.value = morph.R_FOREVER else: module.functions[0].repeats_choice.value = morph.R_CUSTOM module.functions[0].custom_repeats.value = custom_repeats if scale is not None: module.functions[0].scale.value = scale pipeline = cpp.Pipeline() object_set = cpo.ObjectSet() image_set_list = cpi.ImageSetList() image_set = image_set_list.get_image_set(0) workspace = cpw.Workspace( pipeline, module, image_set, object_set, cpmeas.Measurements(), image_set_list, ) image_set.add(INPUT_IMAGE_NAME, cpi.Image(image, mask=mask)) module.run(workspace) output = image_set.get_image(OUTPUT_IMAGE_NAME) return output.pixel_data
def run_workspace(self, operation, m1_is_image_measurement, m1_data, m2_is_image_measurement, m2_data, setup_fn=None): '''Create and run a workspace, returning the measurements m<n>_is_image_measurement - true for an image measurement, false for object m<n>_data - either a single value or an array setup_fn - this gets called with the module before running ''' module = C.CalculateMath() module.operation.value = operation measurements = cpmeas.Measurements() for i, operand, is_image_measurement, data in \ ((0, module.operands[0], m1_is_image_measurement, m1_data), (1, module.operands[1], m2_is_image_measurement, m2_data)): measurement = "measurement%d" % i if is_image_measurement: operand.operand_choice.value = C.MC_IMAGE measurements.add_image_measurement(measurement, data) else: operand.operand_choice.value = C.MC_OBJECT operand.operand_objects.value = OBJECT[i] measurements.add_measurement(OBJECT[i], measurement, data) operand.operand_measurement.value = measurement module.output_feature_name.value = OUTPUT_MEASUREMENTS pipeline = cpp.Pipeline() image_set_list = cpi.ImageSetList() workspace = cpw.Workspace(pipeline, module, image_set_list.get_image_set(0), cpo.ObjectSet(), measurements, image_set_list) if setup_fn is not None: setup_fn(module, workspace) module.run(workspace) return measurements
def test_01_01_divide(self): """Test correction by division""" np.random.seed(0) image = np.random.uniform(size=(10, 10)).astype(np.float32) illum = np.random.uniform(size=(10, 10)).astype(np.float32) expected = image / illum pipeline = cpp.Pipeline() pipeline.add_listener(self.error_callback) input_module = inj.InjectImage("InputImage", image) input_module.module_num = 1 pipeline.add_module(input_module) illum_module = inj.InjectImage("IllumImage", illum) illum_module.module_num = 2 pipeline.add_module(illum_module) module = cpmcia.CorrectIlluminationApply() module.module_num = 3 pipeline.add_module(module) image = module.images[0] image.image_name.value = "InputImage" image.illum_correct_function_image_name.value = "IllumImage" image.corrected_image_name.value = "OutputImage" image.divide_or_subtract.value = cpmcia.DOS_DIVIDE image.rescale_option = cpmcia.RE_NONE image_set_list = cpi.ImageSetList() measurements = cpm.Measurements() workspace = cpw.Workspace(pipeline, None, None, None, measurements, image_set_list) pipeline.prepare_run(workspace) input_module.prepare_group(workspace, {}, [1]) illum_module.prepare_group(workspace, {}, [1]) module.prepare_group(workspace, {}, [1]) image_set = image_set_list.get_image_set(0) object_set = cpo.ObjectSet() workspace = cpw.Workspace(pipeline, input_module, image_set, object_set, measurements, image_set_list) input_module.run(workspace) illum_module.run(workspace) module.run(workspace) output_image = workspace.image_set.get_image("OutputImage") self.assertTrue(np.all(output_image.pixel_data == expected))
def make_workspace(self, image, mask=None): """Make a workspace for testing FindEdges""" module = F.FindEdges() module.image_name.value = INPUT_IMAGE_NAME module.output_image_name.value = OUTPUT_IMAGE_NAME pipeline = cpp.Pipeline() object_set = cpo.ObjectSet() image_set_list = cpi.ImageSetList() image_set = image_set_list.get_image_set(0) workspace = cpw.Workspace( pipeline, module, image_set, object_set, cpmeas.Measurements(), image_set_list, ) image_set.add( INPUT_IMAGE_NAME, cpi.Image(image) if mask is None else cpi.Image(image, mask), ) return workspace, module
def test_03_02_zernikes_are_different(self): '''Regression test of IMG-773''' np.random.seed(32) labels = np.zeros((40, 20), int) # # Make two "objects" composed of random foreground/background # labels[1:19, 1:19] = (np.random.uniform(size=(18, 18)) > .5).astype(int) labels[21:39, 1:19] = (np.random.uniform(size=(18, 18)) > .5).astype(int) * 2 objects = cpo.Objects() objects.segmented = labels object_set = cpo.ObjectSet() object_set.add_objects(objects, "SomeObjects") module = cpmoas.MeasureObjectAreaShape() module.object_groups[0].name.value = "SomeObjects" module.calculate_zernikes.value = True module.module_num = 1 image_set_list = cpi.ImageSetList() measurements = cpmeas.Measurements() pipeline = cpp.Pipeline() pipeline.add_module(module) def callback(caller, event): self.assertFalse(isinstance(event, cpp.RunExceptionEvent)) pipeline.add_listener(callback) workspace = cpw.Workspace(pipeline, module, image_set_list.get_image_set(0), object_set, measurements, image_set_list) module.run(workspace) features = [x[1] for x in module.get_measurement_columns(pipeline) if x[0] == "SomeObjects" and x[1].startswith("AreaShape_Zernike")] for feature in features: values = measurements.get_current_measurement( "SomeObjects", feature) self.assertEqual(len(values), 2) self.assertNotEqual(values[0], values[1])
def make_workspace(self, file_names): module = L.LoadSingleImage() module.module_num = 1 module.directory.set_dir_choice(L.DEFAULT_INPUT_FOLDER_NAME) for i, file_name in enumerate(file_names): if i > 0: module.add_file() module.file_settings[i].image_name.value = self.get_image_name(i) module.file_settings[i].file_name.value = file_name pipeline = cpp.Pipeline() def callback(caller, event): self.assertFalse(isinstance(event, cpp.RunExceptionEvent)) pipeline.add_listener(callback) pipeline.add_module(module) image_set_list = cpi.ImageSetList() workspace = cpw.Workspace(pipeline, module, image_set_list.get_image_set(0), cpo.ObjectSet(), cpmeas.Measurements(), image_set_list) return workspace, module
def make_workspace(self, pixels, choices): """Make a workspace for running UnmixColors pixels - input image choices - a list of choice strings for the images desired """ pipeline = cpp.Pipeline() def callback(caller, event): self.assertFalse(isinstance(event, cpp.RunExceptionEvent)) pipeline.add_listener(callback) module = U.UnmixColors() module.input_image_name.value = INPUT_IMAGE module.outputs[0].image_name.value = output_image_name(0) module.outputs[0].stain_choice.value = choices[0] for i, choice in enumerate(choices[1:]): module.add_image() module.outputs[i + 1].image_name.value = output_image_name(i + 1) module.outputs[i + 1].stain_choice.value = choice module.module_num = 1 pipeline.add_module(module) image_set_list = cpi.ImageSetList() image_set = image_set_list.get_image_set(0) image = cpi.Image(pixels) image_set.add(INPUT_IMAGE, image) workspace = cpw.Workspace( pipeline, module, image_set, cpo.ObjectSet(), cpmeas.Measurements(), image_set_list, ) return workspace, module
def test_02_03_double_mask(self): labels = np.zeros((10, 15), int) labels[2:5, 3:8] = 1 labels[5:8, 10:14] = 2 object_set = cpo.ObjectSet() objects = cpo.Objects() objects.segmented = labels object_set.add_objects(objects, OBJECTS_NAME) image_set_list = cpi.ImageSetList() image_set = image_set_list.get_image_set(0) np.random.seed(0) pixel_data = np.random.uniform(size=(10, 15)).astype(np.float32) mask = np.random.uniform(size=(10, 15)) > .5 image_set.add(IMAGE_NAME, cpi.Image(pixel_data, mask)) expected_mask = (mask & (labels > 0)) pipeline = cpp.Pipeline() module = M.MaskImage() module.source_choice.value = M.IO_OBJECTS module.object_name.value = OBJECTS_NAME module.image_name.value = IMAGE_NAME module.masked_image_name.value = MASKED_IMAGE_NAME module.invert_mask.value = False module.module_num = 1 workspace = cpw.Workspace(pipeline, module, image_set, object_set, cpmeas.Measurements(), image_set_list) module.run(workspace) masked_image = workspace.image_set.get_image(MASKED_IMAGE_NAME) self.assertTrue(isinstance(masked_image, cpi.Image)) self.assertTrue( np.all(masked_image.pixel_data[expected_mask] == pixel_data[expected_mask])) self.assertTrue(np.all(masked_image.pixel_data[~expected_mask] == 0)) self.assertTrue(np.all(masked_image.mask == expected_mask)) self.assertTrue( np.all(masked_image.masking_objects.segmented == labels))
def test_01_03_combine_channels(self): np.random.seed(13) image = np.random.uniform(size=(20, 10, 5)) image_set_list = cpi.ImageSetList() image_set = image_set_list.get_image_set(0) image_set.add(IMAGE_NAME, cpi.Image(image)) module = cpm_ctg.ColorToGray() module.module_num = 1 module.image_name.value = IMAGE_NAME module.combine_or_split.value = cpm_ctg.COMBINE module.grayscale_name.value = OUTPUT_IMAGE_F % 1 module.rgb_or_channels.value = cpm_ctg.CH_CHANNELS module.add_channel() module.add_channel() channel_indexes = np.array([2, 0, 3]) factors = np.random.uniform(size=3) divisor = np.sum(factors) expected = np.zeros((20, 10)) for i, channel_index in enumerate(channel_indexes): module.channels[i].channel_choice.value = module.channel_names[channel_index] module.channels[i].contribution.value_text = "%.10f" % factors[i] expected += image[:, :, channel_index] * factors[i] / divisor pipeline = cpp.Pipeline() def callback(caller, event): self.assertFalse(isinstance(event, cpp.RunExceptionEvent)) pipeline.add_listener(callback) pipeline.add_module(module) workspace = Workspace(pipeline, module, image_set, cpo.ObjectSet(), cpm.Measurements(), image_set_list) module.run(workspace) pixels = image_set.get_image(module.grayscale_name.value).pixel_data self.assertEqual(pixels.ndim, 2) self.assertEqual(tuple(pixels.shape), (20, 10)) np.testing.assert_almost_equal(expected, pixels)
def make_workspace(self, image_measurements, object_measurements): '''Make a workspace with a FlagImage module and the given measurements image_measurements - a sequence of single image measurements. Use image_measurement_name(i) to get the name of the i th measurement object_measurements - a seequence of sequences of object measurements. These are stored under object, OBJECT_NAME with measurement name object_measurement_name(i) for the i th measurement. returns module, workspace ''' module = F.FlagImage() measurements = cpmeas.Measurements() for i in range(len(image_measurements)): measurements.add_image_measurement(image_measurement_name(i), image_measurements[i]) for i in range(len(object_measurements)): measurements.add_measurement(OBJECT_NAME, object_measurement_name(i), np.array(object_measurements[i])) flag = module.flags[0] self.assertTrue(isinstance(flag, cps.SettingsGroup)) flag.category.value = MEASUREMENT_CATEGORY flag.feature_name.value = MEASUREMENT_FEATURE module.module_num = 1 pipeline = cpp.Pipeline() def callback(caller, event): self.assertFalse(isinstance(event, cpp.RunExceptionEvent)) pipeline.add_listener(callback) pipeline.add_module(module) image_set_list = cpi.ImageSetList() image_set = image_set_list.get_image_set(0) workspace = cpw.Workspace(pipeline, module, image_set, cpo.ObjectSet(), measurements, image_set_list) return module, workspace
def make_workspace(self, ground_truth, test): '''Make a workspace with a ground-truth image and a test image ground_truth and test are dictionaries with the following keys: image - the pixel data mask - (optional) the mask data crop_mask - (optional) a cropping mask returns a workspace and module ''' module = C.CalculateImageOverlap() module.module_num = 1 module.obj_or_img.value = O_IMG module.ground_truth.value = GROUND_TRUTH_IMAGE_NAME module.test_img.value = TEST_IMAGE_NAME module.wants_emd.value = True pipeline = cpp.Pipeline() def callback(caller, event): self.assertFalse(isinstance(event, cpp.RunExceptionEvent)) pipeline.add_listener(callback) pipeline.add_module(module) image_set_list = cpi.ImageSetList() image_set = image_set_list.get_image_set(0) for name, d in ((GROUND_TRUTH_IMAGE_NAME, ground_truth), (TEST_IMAGE_NAME, test)): image = cpi.Image(d["image"], mask=d.get("mask"), crop_mask=d.get("crop_mask")) image_set.add(name, image) workspace = cpw.Workspace(pipeline, module, image_set, cpo.ObjectSet(), cpmeas.Measurements(), image_set_list) return workspace, module
def test_02_03_use_background_image(self): x = YS.IdentifyYeastCells() x.object_name.value = OBJECTS_NAME x.input_image_name.value = IMAGE_NAME x.segmentation_precision.value = 11 x.background_image_name.value = BACKGROUND_IMAGE_NAME x.background_elimination_strategy.value = YS.BKG_FILE x.background_brighter_then_cell_inside.value = False x.average_cell_diameter.value = 30 img = np.ones((200, 200)) * 0.5 draw_brightfield_cell(img, 100, 100, 20, False) draw_brightfield_cell(img, 25, 25, 10, False) draw_brightfield_cell(img, 150, 150, 15, False) # background blob bkg = np.ones((200, 200)) * 0.5 draw_brightfield_cell(bkg, 150, 150, 15, False) # background blob image = cpi.Image(img, file_name="test_02_03_use_background_image") background = cpi.Image(bkg) image_set_list = cpi.ImageSetList() image_set = image_set_list.get_image_set(0) image_set.providers.append(cpi.VanillaImageProvider(IMAGE_NAME, image)) image_set.providers.append( cpi.VanillaImageProvider(BACKGROUND_IMAGE_NAME, background)) object_set = cpo.ObjectSet() measurements = cpmeas.Measurements() pipeline = cellprofiler.pipeline.Pipeline() x.run(Workspace(pipeline, x, image_set, object_set, measurements, None)) objects = object_set.get_objects(OBJECTS_NAME) self.assertEqual(objects.segmented[25, 25] > 0, 1, "The small object was not there") self.assertEqual(objects.segmented[100, 100] > 0, 1, "The large object was not there") self.assertEqual(objects.segmented[150, 150] > 0, 0, "The background blob was not filtered out")
def run_imagemath(self, images, modify_module_fn=None, measurement=None): '''Run the ImageMath module, returning the image created images - a list of dictionaries. The dictionary has keys: pixel_data - image pixel data mask - mask for image cropping - cropping mask for image modify_module_fn - a function of the signature, fn(module) that allows the test to modify the module. measurement - an image measurement value ''' image_set_list = cpi.ImageSetList() image_set = image_set_list.get_image_set(0) module = I.ImageMath() module.module_num = 1 for i, image in enumerate(images): pixel_data = image['pixel_data'] mask = image.get('mask', None) cropping = image.get('cropping', None) if i >= 2: module.add_image() name = 'inputimage%s' % i module.images[i].image_name.value = name img = cpi.Image(pixel_data, mask=mask, crop_mask=cropping) image_set.add(name, img) module.output_image_name.value = 'outputimage' if modify_module_fn is not None: modify_module_fn(module) pipeline = cpp.Pipeline() pipeline.add_module(module) measurements = cpmeas.Measurements() if measurement is not None: measurements.add_image_measurement(MEASUREMENT_NAME, str(measurement)) workspace = cpw.Workspace(pipeline, module, image_set, cpo.ObjectSet(), measurements, image_set_list) module.run(workspace) return image_set.get_image('outputimage')
def make_place_workspace(self, images): image_set_list = cpi.ImageSetList() image_set = image_set_list.get_image_set(0) module = T.Tile() module.module_num = 1 module.tile_method.value = T.T_WITHIN_CYCLES module.output_image.value = OUTPUT_IMAGE_NAME module.wants_automatic_rows.value = False module.wants_automatic_columns.value = True module.rows.value = 1 for i, image in enumerate(images): image_name = input_image_name(i) if i == 0: module.input_image.value = image_name else: if len(module.additional_images) <= i: module.add_image() module.additional_images[i - 1].input_image_name.value = image_name image_set.add(image_name, cpi.Image(image)) pipeline = cpp.Pipeline() def callback(caller, event): self.assertFalse(isinstance(event, cpp.RunExceptionEvent)) pipeline.add_listener(callback) pipeline.add_module(module) workspace = cpw.Workspace( pipeline, module, image_set, cpo.ObjectSet(), cpmeas.Measurements(), image_set_list, ) return workspace, module
def make_workspace(self, image_set_count): image_set_list = cpi.ImageSetList() for i in range(image_set_count): image_set = image_set_list.get_image_set(i) module = L.LabelImages() pipeline = cpp.Pipeline() def callback(caller, event): self.assertFalse(isinstance(event, cpp.RunExceptionEvent)) pipeline.add_listener(callback) module.module_num = 1 pipeline.add_module(module) workspace = cpw.Workspace( pipeline, module, image_set_list.get_image_set(0), cpo.ObjectSet(), cpmeas.Measurements(), image_set_list, ) return workspace, module
def make_workspace(self, pixel_data, mask=None, objects=None): image_set_list = cpi.ImageSetList() image_set = image_set_list.get_image_set(0) object_set = cpo.ObjectSet() image = cpi.Image(pixel_data) if not mask is None: image.mask = mask image_set.add(MY_IMAGE, image) if not objects is None: o = cpo.Objects() o.segmented = objects object_set.add_objects(o, MY_OBJECTS) module = miq.MeasureImageQuality() module.images_choice.value = miq.O_SELECT module.image_groups[0].include_image_scalings.value = False module.image_groups[0].image_names.value = MY_IMAGE module.image_groups[0].use_all_threshold_methods.value = False module.module_num = 1 pipeline = cpp.Pipeline() pipeline.add_module(module) workspace = cpw.Workspace(pipeline, module, image_set, object_set, cpmeas.Measurements(), image_set_list) return workspace
def run_module(self, image, mask=None, fn=None): '''Run the FlipAndRotate module image - pixel data to be transformed mask - optional mask on the pixel data fn - function with signature, "fn(module)" that will be called with the FlipAndRotate module returns an Image object containing the flipped/rotated/masked/cropped image and the angle measurement. ''' img = cpi.Image(image, mask) image_set_list = cpi.ImageSetList() image_set = image_set_list.get_image_set(0) image_set.add(IMAGE_NAME, img) module = F.FlipAndRotate() module.image_name.value = IMAGE_NAME module.output_name.value = OUTPUT_IMAGE module.module_num = 1 if fn is not None: fn(module) pipeline = cpp.Pipeline() pipeline.add_module(module) def error_callback(caller, event): self.assertFalse(isinstance(event, cpp.RunExceptionEvent)) pipeline.add_listener(error_callback) measurements = cpmeas.Measurements() workspace = cpw.Workspace(pipeline, module, image_set, cpo.ObjectSet(), measurements, image_set_list) module.run(workspace) feature = F.M_ROTATION_F % OUTPUT_IMAGE self.assertTrue( feature in measurements.get_feature_names(cpmeas.IMAGE)) angle = measurements.get_current_image_measurement(feature) output_image = image_set.get_image(OUTPUT_IMAGE) return output_image, angle
def make_workspace(self, gridding, labels=None): module = I.IdentifyObjectsInGrid() module.module_num = 1 module.grid_name.value = GRID_NAME module.output_objects_name.value = OUTPUT_OBJECTS_NAME module.guiding_object_name.value = GUIDING_OBJECTS_NAME image_set_list = cpi.ImageSetList() object_set = cpo.ObjectSet() if labels is not None: my_objects = cpo.Objects() my_objects.segmented = labels object_set.add_objects(my_objects, GUIDING_OBJECTS_NAME) pipeline = cpp.Pipeline() def callback(caller, event): self.assertFalse(isinstance(event, cpp.RunExceptionEvent)) pipeline.add_listener(callback) pipeline.add_module(module) workspace = cpw.Workspace(pipeline, module, image_set_list.get_image_set(0), object_set, cpmeas.Measurements(), image_set_list) workspace.set_grid(GRID_NAME, gridding) return workspace, module
def test_13_04_extra_lines(self): # # Regression test of issue #1211 - extra line at end / blank lines # dir = os.path.join(example_images_directory(), "ExampleSBSImages") file_name = 'Channel2-01-A-01.tif' csv_text = '''"Image_FileName_DNA","Image_PathName_DNA" "%s","%s" ''' % (file_name, dir) pipeline, module, filename = self.make_pipeline(csv_text) try: assert isinstance(module, L.LoadData) m = cpmeas.Measurements() workspace = cpw.Workspace(pipeline, module, m, cpo.ObjectSet(), m, cpi.ImageSetList()) self.assertTrue(module.prepare_run(workspace)) self.assertTrue(isinstance(m, cpmeas.Measurements)) self.assertEqual(m.image_set_count, 1) self.assertTrue('FileName_DNA' in m.get_feature_names(cpmeas.IMAGE)) self.assertEqual(m[cpmeas.IMAGE, 'FileName_DNA', 1], file_name) finally: os.remove(filename)
def make_workspace(self, pixel_data, mask=None): image = cpi.Image(pixel_data, mask) image_set_list = cpi.ImageSetList() image_set = image_set_list.get_image_set(0) image_set.add(IMAGE_NAME, image) module = ID.IdentifyDeadWorms() module.module_num = 1 module.image_name.value = IMAGE_NAME module.object_name.value = OBJECTS_NAME pipeline = cpp.Pipeline() def callback(caller, event): self.assertFalse(isinstance(event, cpp.LoadExceptionEvent)) self.assertFalse(isinstance(event, cpp.RunExceptionEvent)) pipeline.add_listener(callback) pipeline.add_module(module) workspace = cpw.Workspace(pipeline, module, image_set, cpo.ObjectSet(), cpmeas.Measurements(), image_set_list) return workspace, module
def make_tile_workspace(self, images): module = T.Tile() module.module_num = 1 module.tile_method.value = T.T_ACROSS_CYCLES module.input_image.value = INPUT_IMAGE_NAME module.output_image.value = OUTPUT_IMAGE_NAME pipeline = cpp.Pipeline() def callback(caller, event): self.assertFalse(isinstance(event, cpp.RunExceptionEvent)) pipeline.add_listener(callback) pipeline.add_module(module) image_set_list = cpi.ImageSetList() for i, image in enumerate(images): image_set = image_set_list.get_image_set(i) image_set.add(INPUT_IMAGE_NAME, cpi.Image(image)) workspace = cpw.Workspace(pipeline, module, image_set_list.get_image_set(0), cpo.ObjectSet(), cpmeas.Measurements(), image_set_list) return workspace, module
def test_00_00_init(self): x = cpi.ImageSetList() self.assertEqual( x.count(), 0, "# of elements of an empty image set list is %d, not zero" % (x.count()))
def make_workspace(self, scheme, images, adjustments=None, colors=None, weights=None): module = G.GrayToColor() module.scheme_choice.value = scheme if scheme not in (G.SCHEME_COMPOSITE, G.SCHEME_STACK): image_names = [ "image%d" % i if images[i] is not None else G.LEAVE_THIS_BLACK for i in range(7) ] for image_name_setting, image_name, adjustment_setting, adjustment \ in zip((module.red_image_name, module.green_image_name, module.blue_image_name, module.cyan_image_name, module.magenta_image_name, module.yellow_image_name, module.gray_image_name), image_names, (module.red_adjustment_factor, module.green_adjustment_factor, module.blue_adjustment_factor, module.cyan_adjustment_factor, module.magenta_adjustment_factor, module.yellow_adjustment_factor, module.gray_adjustment_factor), adjustments): image_name_setting.value = image_name adjustment_setting.value = adjustment else: while len(module.stack_channels) < len(images): module.add_stack_channel_cb() image_names = [] if weights is None: weights = [1.0] * len(images) if colors is None: colors = [ G.DEFAULT_COLORS[i % len(G.DEFAULT_COLORS)] for i in range(len(images)) ] for i, (image, color, weight) in enumerate(zip(images, colors, weights)): image_name = 'image%d' % (i + 1) image_names.append(image_name) module.stack_channels[i].image_name.value = image_name module.stack_channels[i].color.value = color module.stack_channels[i].weight.value = weight module.rgb_image_name.value = OUTPUT_IMAGE_NAME module.module_num = 1 pipeline = cpp.Pipeline() def callback(caller, event): self.assertFalse(isinstance(event, cpp.RunExceptionEvent)) pipeline.add_listener(callback) pipeline.add_module(module) image_set_list = cpi.ImageSetList() image_set = image_set_list.get_image_set(0) for image, image_name in zip(images, image_names): if image is not None: image_set.add(image_name, cpi.Image(image)) workspace = cpw.Workspace(pipeline, module, image_set, cpo.ObjectSet(), cpmeas.Measurements(), image_set_list) return workspace, module
def run_module( self, color_image=None, red_image=None, green_image=None, blue_image=None, fn=None, ): """Run the InvertForPrinting module Call this with Numpy arrays for the images and optionally specify a function (fn) whose argument is an InvertForPrinting module. You can specialize the module inside this function. Returns a dictionary of the pixel data of the images in the image set """ image_set_list = cpi.ImageSetList() image_set = image_set_list.get_image_set(0) module = I.InvertForPrinting() module.module_num = 1 for image, name, setting, check in ( (color_image, I_COLOR_IN, module.color_input_image, None), (red_image, I_RED_IN, module.red_input_image, module.wants_red_input), ( green_image, I_GREEN_IN, module.green_input_image, module.wants_green_input, ), (blue_image, I_BLUE_IN, module.blue_input_image, module.wants_blue_input), ): if image is not None: img = cpi.Image(image) image_set.add(name, img) setting.value = name if check is not None: check.value = True elif check is not None: check.value = False for name, setting in ( (I_COLOR_OUT, module.color_output_image), (I_RED_OUT, module.red_output_image), (I_GREEN_OUT, module.green_output_image), (I_BLUE_OUT, module.blue_output_image), ): setting.value = name if fn is not None: fn(module) pipeline = cpp.Pipeline() pipeline.add_module(module) def callback(caller, event): self.assertFalse(isinstance(event, cpp.RunExceptionEvent)) pipeline.add_listener(callback) workspace = cpw.Workspace( pipeline, module, image_set, cpo.ObjectSet(), cpm.Measurements(), image_set_list, ) module.run(workspace) result = {} for provider in image_set.providers: result[provider.get_name()] = provider.provide_image( image_set).pixel_data return result
def make_workspace(self, control_points, lengths, radii, image, mask=None, auximage=None): '''Create a workspace containing the control point measurements control_points - an n x 2 x m array where n is the # of control points, and m is the number of objects. lengths - the length of each object radii - the radii_from_training defining the radius at each control pt image - the image to be straightened mask - the mask associated with the image (default = no mask) auximage - a second image to be straightnened (default = no second image) ''' module = S.StraightenWorms() module.objects_name.value = OBJECTS_NAME module.straightened_objects_name.value = STRAIGHTENED_OBJECTS_NAME module.images[0].image_name.value = IMAGE_NAME module.images[ 0].straightened_image_name.value = STRAIGHTENED_IMAGE_NAME module.flip_image.value = IMAGE_NAME module.module_num = 1 # Trick the module into thinking it's read the data file class P: def __init__(self): self.radii_from_training = radii module.training_set_directory.dir_choice = cps.URL_FOLDER_NAME module.training_set_directory.custom_path = "http://www.cellprofiler.org" module.training_set_file_name.value = "TrainingSet.xml" module.training_params = {"TrainingSet.xml": (P(), "URL")} pipeline = cpp.Pipeline() pipeline.add_module(module) def callback(caller, event): self.assertFalse(isinstance(event, cpp.RunExceptionEvent)) pipeline.add_listener(callback) m = cpmeas.Measurements() for i, (y, x) in enumerate(control_points): for v, f in ((x, S.F_CONTROL_POINT_X), (y, S.F_CONTROL_POINT_Y)): feature = "_".join((S.C_WORM, f, str(i + 1))) m.add_measurement(OBJECTS_NAME, feature, v) feature = "_".join((S.C_WORM, S.F_LENGTH)) m.add_measurement(OBJECTS_NAME, feature, lengths) image_set_list = cpi.ImageSetList() image_set = image_set_list.get_image_set(0) image_set.add(IMAGE_NAME, cpi.Image(image, mask)) if auximage is not None: image_set.add(AUX_IMAGE_NAME, cpi.Image(auximage)) module.add_image() module.images[1].image_name.value = AUX_IMAGE_NAME module.images[ 1].straightened_image_name.value = AUX_STRAIGHTENED_IMAGE_NAME object_set = cpo.ObjectSet() objects = cpo.Objects() labels = np.zeros(image.shape, int) for i in range(control_points.shape[2]): if lengths[i] == 0: continue self.rebuild_worm_from_control_points_approx( control_points[:, :, i], radii, labels, i + 1) objects.segmented = labels object_set.add_objects(objects, OBJECTS_NAME) workspace = cpw.Workspace(pipeline, module, image_set, object_set, m, image_set_list) return workspace, module
def test_03_01_save_and_load(self): """Save a pipeline to batch data, open it to check and load it""" data = ("eJztWW1PGkEQXhC1WtPYTzb9tB+llROoGiWNgi9NSYUSIbZGbbvCApvu7ZJ7" "UWlj0o/9Wf1J/QndxTs4tsoBRS3JHbkcMzfPPDOzs8uxl8uU9jPbcFWLw1ym" "FKsSimGBIqvKDT0FmbUEdwyMLFyBnKVgycYwY9dgIgET8dTqRmolCZPx+AYY" "7ghlc0/EJf4cgClxfSTOsHNr0pFDnlPKRWxZhNXMSRABzxz9L3EeIoOgM4oP" "EbWx2aFw9VlW5aVmo30rxys2xXmke43Fkbf1M2yY76su0LldIJeYFsk3rKTg" "mh3gc2ISzhy841/Vtnm5pfDKOhTmOnUIKXWQdVnw6KX9W9Cxj9xQt6ce+3lH" "JqxCzknFRhQSHdXaUbTGwcffRJe/CXAk0BKX9sHNK3HIs4QvrdjeJSpbUEdW" "uS79rPv4mVb8SLmcOrGw3ugr/lAXPgRe9Zl3uAsXBnkO+sp7VolXyrscMm5B" "28T91/02/lHgphSce7i4GdCJ0y/fOSVfKe9RE1/UsYE1TXP91H38rCh+pCzG" "uYwpbRhcLlHGiWXY7OuJaCC9ISZ3q5NdqbhdzLZb+yH4hpmXy3I2ioVtGTFE" "myYZxbwcdpzvu68eku8+cGmf/GZAdz9IeaeOGMM0ERtx3P30z24+c6d86jqc" "uOP8Il18EdE/DP8L3w8fvnegezyl/Glxq/BaPljhTe1l9LOUPoj15YBfbB5n" "YoXTqKvZ4dTW2eZxPLZx+j2xlLy6Ni4SgWwpozfmPUj8fuvhuhK/lGUMRxgZ" "TmArV9GYVOU4s+qOLunodlGzo3mgeZMcxbwZir9p8QZFpj4C/kHnUfKO+YJ5" "NJ7z6OPsYP8rxuV3NcAFuAAX4P43XNqD63c/pLUZUzO43YCEVXBjnPINcOON" "S4OgXwPc8DipvO35Ut2/kfZfQO9+ewG6+03K3s04TW9topsa5ahyvYut7Yuv" "Wc+Gdj/P52sKz9ptPOXWK5AzuU8tb5ja9TuRbal4Q1rvCNT6zdzA561DWHwW" "pnvXXa13Zxx+bw3DFwn9zffYBxdxKidxP8Fg47zYw97NbVj7P/nFW+E=") def callback(caller, event): self.assertFalse(isinstance(event, cpp.LoadExceptionEvent)) self.assertFalse(isinstance(event, cpp.RunExceptionEvent)) T.maybe_download_sbs() for windows_mode in ((False, True) if sys.platform.startswith("win") else (False, )): pipeline = cpp.Pipeline() pipeline.add_listener(callback) pipeline.load(StringIO(zlib.decompress(base64.b64decode(data)))) ipath = os.path.join(T.example_images_directory(), "ExampleSBSImages") bpath = tempfile.mkdtemp() bfile = os.path.join(bpath, C.F_BATCH_DATA) hfile = os.path.join(bpath, C.F_BATCH_DATA_H5) try: li = pipeline.modules()[0] self.assertTrue(isinstance(li, LI.LoadImages)) module = pipeline.modules()[1] self.assertTrue(isinstance(module, C.CreateBatchFiles)) li.location.dir_choice = cps.ABSOLUTE_FOLDER_NAME li.location.custom_path = ipath module.wants_default_output_directory.value = False module.custom_output_directory.value = bpath module.remote_host_is_windows.value = windows_mode self.assertEqual(len(module.mappings), 1) mapping = module.mappings[0] mapping.local_directory.value = ipath self.assertFalse(pipeline.in_batch_mode()) measurements = cpmeas.Measurements(mode="memory") image_set_list = cpi.ImageSetList() result = pipeline.prepare_run( cpw.Workspace(pipeline, None, None, None, measurements, image_set_list)) self.assertFalse(pipeline.in_batch_mode()) self.assertFalse(result) self.assertFalse(module.batch_mode.value) self.assertTrue( measurements.has_feature(cpmeas.EXPERIMENT, cpp.M_PIPELINE)) pipeline = cpp.Pipeline() pipeline.add_listener(callback) image_set_list = cpi.ImageSetList() measurements = cpmeas.Measurements(mode="memory") workspace = cpw.Workspace(pipeline, None, None, None, cpmeas.Measurements(), image_set_list) workspace.load(hfile, True) measurements = workspace.measurements self.assertTrue(pipeline.in_batch_mode()) module = pipeline.modules()[1] self.assertTrue(isinstance(module, C.CreateBatchFiles)) self.assertTrue(module.batch_mode.value) image_numbers = measurements.get_image_numbers() self.assertTrue( [x == i + 1 for i, x in enumerate(image_numbers)]) pipeline.prepare_run(workspace) pipeline.prepare_group(workspace, {}, list(range(1, 97))) for i in range(96): image_set = image_set_list.get_image_set(i) for image_name in ("DNA", "Cytoplasm"): pathname = measurements.get_measurement( cpmeas.IMAGE, "PathName_" + image_name, i + 1) self.assertEqual( pathname, "\\imaging\\analysis" if windows_mode else "/imaging/analysis", ) measurements.close() finally: if os.path.exists(bfile): os.unlink(bfile) if os.path.exists(hfile): os.unlink(hfile) os.rmdir(bpath)
def interface(self, start_signal, image_set_start=1, image_set_end=None, overwrite=True): '''Top-half thread for running an analysis. Sets up grouping for jobs, deals with returned measurements, reports status periodically. start_signal- signal this semaphore when jobs are ready. image_set_start - beginning image set number to process image_set_end - last image set number to process overwrite - whether to recompute imagesets that already have data in initial_measurements. ''' from javabridge import attach, detach posted_analysis_started = False acknowledged_thread_start = False measurements = None workspace = None attach() try: # listen for pipeline events, and pass them upstream self.pipeline.add_listener(lambda pipe, evt: self.post_event(evt)) initial_measurements = None if self.output_path is None: # Caller wants a temporary measurements file. fd, filename = tempfile.mkstemp( ".h5", dir=cpprefs.get_temporary_directory()) try: fd = os.fdopen(fd, "wb") fd.write(self.initial_measurements_buf) fd.close() initial_measurements = cpmeas.Measurements( filename=filename, mode="r") measurements = cpmeas.Measurements( image_set_start=None, copy=initial_measurements, mode="a") finally: if initial_measurements is not None: initial_measurements.close() os.unlink(filename) else: with open(self.output_path, "wb") as fd: fd.write(self.initial_measurements_buf) measurements = cpmeas.Measurements(image_set_start=None, filename=self.output_path, mode="a") # The shared dicts are needed in jobserver() self.shared_dicts = [m.get_dictionary() for m in self.pipeline.modules()] workspace = cpw.Workspace(self.pipeline, None, None, None, measurements, cpimage.ImageSetList()) if image_set_end is None: image_set_end = measurements.get_image_numbers()[-1] image_sets_to_process = filter( lambda x: x >= image_set_start and x <= image_set_end, measurements.get_image_numbers()) self.post_event(AnalysisStarted()) posted_analysis_started = True # reset the status of every image set that needs to be processed has_groups = measurements.has_groups() if self.pipeline.requires_aggregation(): overwrite = True if has_groups and not overwrite: if not measurements.has_feature(cpmeas.IMAGE, self.STATUS): overwrite = True else: group_status = {} for image_number in measurements.get_image_numbers(): group_number = measurements[ cpmeas.IMAGE, cpmeas.GROUP_NUMBER, image_number] status = measurements[cpmeas.IMAGE, self.STATUS, image_number] if status != self.STATUS_DONE: group_status[group_number] = self.STATUS_UNPROCESSED elif group_number not in group_status: group_status[group_number] = self.STATUS_DONE new_image_sets_to_process = [] for image_set_number in image_sets_to_process: needs_reset = False if (overwrite or (not measurements.has_measurements( cpmeas.IMAGE, self.STATUS, image_set_number)) or (measurements[cpmeas.IMAGE, self.STATUS, image_set_number] != self.STATUS_DONE)): needs_reset = True elif has_groups: group_number = measurements[ cpmeas.IMAGE, cpmeas.GROUP_NUMBER, image_set_number] if group_status[group_number] != self.STATUS_DONE: needs_reset = True if needs_reset: measurements[cpmeas.IMAGE, self.STATUS, image_set_number] = \ self.STATUS_UNPROCESSED new_image_sets_to_process.append(image_set_number) image_sets_to_process = new_image_sets_to_process # Find image groups. These are written into measurements prior to # analysis. Groups are processed as a single job. if has_groups or self.pipeline.requires_aggregation(): worker_runs_post_group = True job_groups = {} for image_set_number in image_sets_to_process: group_number = measurements[cpmeas.IMAGE, cpmeas.GROUP_NUMBER, image_set_number] group_index = measurements[cpmeas.IMAGE, cpmeas.GROUP_INDEX, image_set_number] job_groups[group_number] = job_groups.get(group_number, []) + [(group_index, image_set_number)] job_groups = [[isn for _, isn in sorted(job_groups[group_number])] for group_number in sorted(job_groups)] else: worker_runs_post_group = False # prepare_group will be run in worker, but post_group is below. job_groups = [[image_set_number] for image_set_number in image_sets_to_process] # XXX - check that any constructed groups are complete, i.e., # image_set_start and image_set_end shouldn't carve them up. if not worker_runs_post_group: # put the first job in the queue, then wait for the first image to # finish (see the check of self.finish_queue below) to post the rest. # This ensures that any shared data from the first imageset is # available to later imagesets. self.work_queue.put((job_groups[0], worker_runs_post_group, True)) waiting_for_first_imageset = True del job_groups[0] else: waiting_for_first_imageset = False for job in job_groups: self.work_queue.put((job, worker_runs_post_group, False)) job_groups = [] start_signal.release() acknowledged_thread_start = True # We loop until every image is completed, or an outside event breaks the loop. while not self.cancelled: # gather measurements while not self.received_measurements_queue.empty(): image_numbers, buf = self.received_measurements_queue.get() image_numbers = [int(i) for i in image_numbers] recd_measurements = cpmeas.load_measurements_from_buffer(buf) self.copy_recieved_measurements(recd_measurements, measurements, image_numbers) recd_measurements.close() del recd_measurements # check for jobs in progress while not self.in_process_queue.empty(): image_set_numbers = self.in_process_queue.get() for image_set_number in image_set_numbers: measurements[cpmeas.IMAGE, self.STATUS, int(image_set_number)] = self.STATUS_IN_PROCESS # check for finished jobs that haven't returned measurements, yet while not self.finished_queue.empty(): finished_req = self.finished_queue.get() measurements[ cpmeas.IMAGE, self.STATUS, int(finished_req.image_set_number)] = self.STATUS_FINISHED_WAITING if waiting_for_first_imageset: assert isinstance(finished_req, ImageSetSuccessWithDictionary) self.shared_dicts = finished_req.shared_dicts waiting_for_first_imageset = False assert len(self.shared_dicts) == len(self.pipeline.modules()) # if we had jobs waiting for the first image set to finish, # queue them now that the shared state is available. for job in job_groups: self.work_queue.put((job, worker_runs_post_group, False)) finished_req.reply(Ack()) # check progress and report counts = collections.Counter(measurements[cpmeas.IMAGE, self.STATUS, image_set_number] for image_set_number in image_sets_to_process) self.post_event(AnalysisProgress(counts)) # Are we finished? if counts[self.STATUS_DONE] == len(image_sets_to_process): last_image_number = measurements.get_image_numbers()[-1] measurements.image_set_number = last_image_number if not worker_runs_post_group: self.pipeline.post_group(workspace, {}) workspace = cpw.Workspace(self.pipeline, None, None, None, measurements, None, None) workspace.post_run_display_handler = \ self.post_run_display_handler self.pipeline.post_run(workspace) break measurements.flush() # not done, wait for more work with self.interface_work_cv: while (self.paused or ((not self.cancelled) and self.in_process_queue.empty() and self.finished_queue.empty() and self.received_measurements_queue.empty())): self.interface_work_cv.wait() # wait for a change of status or work to arrive finally: detach() # Note - the measurements file is owned by the queue consumer # after this post_event. # if not acknowledged_thread_start: start_signal.release() if posted_analysis_started: was_cancelled = self.cancelled self.post_event(AnalysisFinished(measurements, was_cancelled)) self.stop_workers() self.analysis_id = False # this will cause the jobserver thread to exit
def test_01_02_run(self): """Run with a rectangle, cross and circle""" object_set = cpo.ObjectSet() labels = np.zeros((10, 20), int) labels[1:9, 1:5] = 1 labels[1:9, 11] = 2 labels[4, 6:19] = 2 objects = cpo.Objects() objects.segmented = labels object_set.add_objects(objects, "SomeObjects") labels = np.zeros((115, 115), int) x, y = np.mgrid[-50:51, -50:51] labels[:101, :101][x ** 2 + y ** 2 <= 2500] = 1 objects = cpo.Objects() objects.segmented = labels object_set.add_objects(objects, "OtherObjects") module = cpmoas.MeasureObjectAreaShape() settings = ["SomeObjects", "OtherObjects", "Yes"] module.set_settings_from_values(settings, 1, module.module_class()) module.module_num = 1 image_set_list = cpi.ImageSetList() measurements = cpmeas.Measurements() pipeline = cpp.Pipeline() pipeline.add_module(module) workspace = cpw.Workspace(pipeline, module, image_set_list.get_image_set(0), object_set, measurements, image_set_list) module.run(workspace) self.features_and_columns_match(measurements, module) a = measurements.get_current_measurement('SomeObjects', 'AreaShape_Area') self.assertEqual(len(a), 2) self.assertEqual(a[0], 32) self.assertEqual(a[1], 20) # # Mini-test of the form factor of a circle # ff = measurements.get_current_measurement('OtherObjects', 'AreaShape_FormFactor') self.assertEqual(len(ff), 1) perim = measurements.get_current_measurement('OtherObjects', 'AreaShape_Perimeter') area = measurements.get_current_measurement('OtherObjects', 'AreaShape_Area') # The perimeter is obtained geometrically and is overestimated. expected = 100 * np.pi diff = abs((perim[0] - expected) / (perim[0] + expected)) self.assertTrue(diff < .05, "perimeter off by %f" % diff) wrongness = (perim[0] / expected) ** 2 # It's an approximate circle... expected = np.pi * 50.0 ** 2 diff = abs((area[0] - expected) / (area[0] + expected)) self.assertTrue(diff < .05, "area off by %f" % diff) wrongness *= expected / area[0] self.assertAlmostEqual(ff[0] * wrongness, 1.0) for object_name, object_count in (('SomeObjects', 2), ('OtherObjects', 1)): for measurement in module.get_measurements(pipeline, object_name, 'AreaShape'): feature_name = 'AreaShape_%s' % measurement m = measurements.get_current_measurement(object_name, feature_name) self.assertEqual(len(m), object_count)