def measurement_visibles(m_g): if hasattr(m_g, "remover"): result = [cps.Divider(line=True)] else: result = [] result += [m_g.source_choice] if (m_g.source_choice == S_ALL_OBJECTS or m_g.source_choice == S_AVERAGE_OBJECT): result += [m_g.object_name] if m_g.source_choice == S_RULES or m_g.source_choice == S_CLASSIFIER: result += [ m_g.rules_directory, m_g.rules_file_name, m_g.rules_class ] whatami = "Rules" if m_g.source_choice == S_RULES else "Classifier" for setting, s in ( (m_g.rules_directory, "%s file location"), (m_g.rules_file_name, "%s file name"), ): setting.text = s % whatami else: result += [m_g.measurement, m_g.wants_minimum] if m_g.wants_minimum.value: result += [m_g.minimum_value] result += [m_g.wants_maximum] if m_g.wants_maximum.value: result += [m_g.maximum_value] if hasattr(m_g, "remover"): result += [m_g.remover, cps.Divider(line=True)] return result
def create_settings(self): self.divider_top = cps.Divider(line=False) self.images = [] self.image_count = cps.HiddenCount(self.images, "Image count") self.add_image(can_remove=False) self.add_button = cps.DoSomething("", "Add another image", self.add_image) self.divider_bottom = cps.Divider(line=False)
def create_settings(self): '''Create the initial settings for the module''' self.image_groups = [] self.add_image(can_delete=False) self.spacer_1 = cps.Divider() self.add_image(can_delete=False) self.image_count = cps.HiddenCount(self.image_groups) self.add_image_button = cps.DoSomething("", 'Add another image', self.add_image) self.spacer_2 = cps.Divider() self.thr = cps.Float( "Set threshold as percentage of maximum intensity for the images", 15, minval=0, maxval=99, doc='''\ Select the threshold as a percentage of the maximum intensity of the above image [0-99].''') self.images_or_objects = cps.Choice( 'Select where to measure correlation', [M_IMAGES, M_OBJECTS, M_IMAGES_AND_OBJECTS], doc=''' You can measure the correlation in several ways: <ul> <li><i>%(M_OBJECTS)s:</i> Measure correlation only in those pixels previously identified as an object. You will be asked to specify which object to measure from.</li> <li><i>%(M_IMAGES)s:</i> Measure the correlation across all pixels in the images.</li> <li><i>%(M_IMAGES_AND_OBJECTS)s:</i> Calculate both measurements above.</li> </ul> All methods measure correlation on a pixel by pixel basis.''' % globals()) self.object_groups = [] self.add_object(can_delete=False) self.object_count = cps.HiddenCount(self.object_groups) self.spacer_2 = cps.Divider(line=True) self.add_object_button = cps.DoSomething("", 'Add another object', self.add_object)
def add_image(self, can_delete=True): '''Add an image to the image_groups collection can_delete - set this to False to keep from showing the "remove" button for images that must be present. ''' group = cps.SettingsGroup() if can_delete: group.append("divider", cps.Divider(line=False)) group.append( "image_name", cps.ImageNameSubscriber( 'Select an image to measure', cps.NONE, doc= 'Select an image to measure the correlation/colocalization in.' )) if len(self.image_groups ) == 0: # Insert space between 1st two images for aesthetics group.append("extra_divider", cps.Divider(line=False)) if can_delete: group.append( "remover", cps.RemoveSettingButton("", "Remove this image", self.image_groups, group)) self.image_groups.append(group)
def create_settings(self): """Create the settings for the module at startup. """ self.image_groups = [] self.image_count = cps.HiddenCount(self.image_groups) self.add_image_cb(can_remove=False) self.add_images = cps.DoSomething("", "Add another image", self.add_image_cb) self.image_divider = cps.Divider() self.object_groups = [] self.object_count = cps.HiddenCount(self.object_groups) self.add_object_cb(can_remove=True) self.add_objects = cps.DoSomething("", "Add another object", self.add_object_cb) self.object_divider = cps.Divider() self.moms = cps.MultiChoice( "Moments to compute", MOM_ALL, MOM_ALL, doc= """Moments are statistics describing the distribution of values in the set of pixels of interest: <p><ul> <li><i>%(MOM_1)s</i> - the first image moment, which corresponds to the central value of the collection of pixels of interest.</li> <li><i>%(MOM_2)s</i> - the second image moment, which measures the amount of variation or dispersion of pixel values about its mean.</li> <li><i>%(MOM_3)s</i> - a scaled version of the third moment, which measures the asymmetry of the pixel values distribution about its mean.</li> <li><i>%(MOM_4)s</i> - a scaled version of the fourth moment, which measures the "peakedness" of the pixel values distribution.</li> </ul><p> Choose one or more moments to measure.""" % globals())
def create_settings(self): '''Create the settings & name the module''' self.divider_top = cps.Divider(line=False) self.images = [] self.add_image_measurement(can_remove=False) self.add_button = cps.DoSomething("", "Add another image", self.add_image_measurement) self.divider_bottom = cps.Divider(line=False)
def create_settings(self): """Create the settings for the module at startup. The module allows for an unlimited number of measured objects, each of which has an entry in self.object_groups. """ self.image_groups = [] self.object_groups = [] self.scale_groups = [] self.image_count = cps.HiddenCount(self.image_groups) self.object_count = cps.HiddenCount(self.object_groups) self.scale_count = cps.HiddenCount(self.scale_groups) self.add_image_cb(can_remove=False) self.add_images = cps.DoSomething("", "Add another image", self.add_image_cb) self.image_divider = cps.Divider() self.add_object_cb(can_remove=True) self.add_objects = cps.DoSomething("", "Add another object", self.add_object_cb) self.object_divider = cps.Divider() self.add_scale_cb(can_remove=False) self.add_scales = cps.DoSomething("", "Add another scale", self.add_scale_cb) self.scale_divider = cps.Divider() self.wants_gabor = cps.Binary( "Measure Gabor features?", True, doc="""The Gabor features measure striped texture in an object. They take a substantial time to calculate. Check this setting to measure the Gabor features. Uncheck this setting to skip the Gabor feature calculation if it is not informative for your images""") self.gabor_angles = cps.Integer( "Number of angles to compute for Gabor", 4, 2, doc=""" <i>(Used only if Gabor features are measured)</i><br> How many angles do you want to use for each Gabor texture measurement? The default value is 4 which detects bands in the horizontal, vertical and diagonal orientations.""") self.gabor_divider = cps.Divider() self.wants_tamura = cps.Binary( "Measure Tamura features?", True, doc="""The Tamura features are very ugly.""") self.tamura_feats = cps.MultiChoice("Features to compute", F_ALL, F_ALL, doc="""Tamura Features: <p><ul> <li><i>%(F_1)s</i> - bla.</li> <li><i>%(F_2)s</i> - bla.</li> <li><i>%(F_3)s</i> - bla.</li> </ul><p> Choose one or more features to compute.""" % globals())
def create_settings(self): """Create the settings for the module at startup. The module allows for an unlimited number of measured objects, each of which has an entry in self.object_groups. """ self.image_groups = [] self.object_groups = [] self.scale_groups = [] self.image_count = cps.HiddenCount(self.image_groups) self.object_count = cps.HiddenCount(self.object_groups) self.scale_count = cps.HiddenCount(self.scale_groups) self.add_image_cb(can_remove=False) self.add_images = cps.DoSomething("", "Add another image", self.add_image_cb) self.image_divider = cps.Divider() self.add_object_cb(can_remove=True) self.add_objects = cps.DoSomething("", "Add another object", self.add_object_cb) self.object_divider = cps.Divider() self.add_scale_cb(can_remove=False) self.add_scales = cps.DoSomething("", "Add another scale", self.add_scale_cb) self.scale_divider = cps.Divider() self.wants_gabor = cps.Binary( "Measure Gabor features?", True, doc= """The Gabor features measure striped texture in an object, and can take a substantial time to calculate. <p>Select <i>%(YES)s</i> to measure the Gabor features. Select <i>%(NO)s</i> to skip the Gabor feature calculation if it is not informative for your images.</p>""" % globals()) self.gabor_angles = cps.Integer( "Number of angles to compute for Gabor", 4, 2, doc=""" <i>(Used only if Gabor features are measured)</i><br> Enter the number of angles to use for each Gabor texture measurement. The default value is 4 which detects bands in the horizontal, vertical and diagonal orientations.""") self.images_or_objects = cps.Choice( "Measure images or objects?", [IO_IMAGES, IO_OBJECTS, IO_BOTH], value=IO_BOTH, doc="""This setting determines whether the module computes image-wide measurements, per-object measurements or both. <ul> <li><i>%(IO_IMAGES)s:</i> Select if you only want to measure the texture of objects.</li> <li><i>%(IO_OBJECTS)s:</i> Select if your pipeline does not contain objects or if you only want to make per-image measurements.</li> <li><i>%(IO_BOTH)s:</i> Select to make both image and object measurements.</li> </ul>""" % globals())
def create_settings(self): self.images = [] self.objects = [] self.bin_counts = [] self.heatmaps = [] self.image_count = cps.HiddenCount(self.images) self.object_count = cps.HiddenCount(self.objects) self.bin_counts_count = cps.HiddenCount(self.bin_counts) self.heatmap_count = cps.HiddenCount(self.heatmaps) self.wants_zernikes = cps.Choice( "Calculate intensity Zernikes?", Z_ALL, doc="""This setting determines whether the intensity Zernike moments are calculated. Choose <i>%(Z_NONE)s</i> to save computation time by not calculating the Zernike moments. Choose <i>%(Z_MAGNITUDES)s</i> to only save the magnitude information and discard information related to the object's angular orientation. Choose <i>%(Z_MAGNITUDES_AND_PHASE)s</i> to save the phase information as well. The last option lets you recover each object's rough appearance from the Zernikes but may not contribute useful information if used to classify phenotypes.""" % globals()) self.zernike_degree = cps.Integer( "Maximum zernike moment", value=9, minval=1, maxval=20, doc="""(<i>Only if "%s" is %s or %s</i>)<br> This is the maximum radial moment that will be calculated. There are increasing numbers of azimuthal moments as you increase the radial moment, so higher values are increasingly expensive to calculate.""" % (self.wants_zernikes.text, Z_MAGNITUDES, Z_MAGNITUDES_AND_PHASE)) self.add_image_button = cps.DoSomething("", "Add another image", self.add_image) self.spacer_1 = cps.Divider() self.add_object_button = cps.DoSomething("", "Add another object", self.add_object) self.spacer_2 = cps.Divider() self.add_bin_count_button = cps.DoSomething("", "Add another set of bins", self.add_bin_count) self.spacer_3 = cps.Divider() self.add_heatmap_button = cps.DoSomething( "", "Add another heatmap display", self.add_heatmap, doc=""" Press this button to add a display of one of the radial distribution measurements. Each radial band of the object is colored using a heatmap according to the measurement value for that band.""") self.add_image(can_remove=False) self.add_object(can_remove=False) self.add_bin_count(can_remove=False)
def flag_visibles(flag): if hasattr(flag, "remover"): result = [cps.Divider(line=True), cps.Divider(line=True)] else: result = [] result += [flag.category, flag.feature_name, flag.wants_skip] if len(flag.measurement_settings) > 1: result += [flag.combination_choice] for measurement_settings in flag.measurement_settings: result += measurement_visibles(measurement_settings) result += [flag.add_measurement_button] if hasattr(flag, "remover"): result += [flag.remover, cps.Divider(line=True), cps.Divider(line=True)] return result
def add_image(self, removable=True): # The text for these settings will be replaced in renumber_settings() group = cps.SettingsGroup() group.removable = removable group.append("image_or_measurement", cps.Choice( "Image or measurement?", [IM_IMAGE, IM_MEASUREMENT], doc=""" You can perform math operations using two images or you can use a measurement for one of the operands. For instance, to divide the intensity of one image by another, choose <i>%(IM_IMAGE)s</i> for both and pick the respective images. To divide the intensity of an image by its median intensity, use <b>MeasureImageIntensity</b> prior to this module to calculate the median intensity, then select <i>%(IM_MEASUREMENT)s</i> and use the median intensity measurement as the denominator""" % globals())) group.append("image_name", cps.ImageNameSubscriber("", "", doc=""" Selec the image that you want to use for this operation.""")) group.append("measurement", cps.Measurement( "Measurement", lambda: cpmeas.IMAGE, "", doc=""" This is a measurement made on the image. The value of the measurement is used for the operand for all of the pixels of the other operand's image.""")) group.append("factor", cps.Float("", 1, doc=""" Enter the number that you would like to multiply the above image by. This multiplication is applied before other operations.""")) if removable: group.append("remover", cps.RemoveSettingButton("", "Remove this image", self.images, group)) group.append("divider", cps.Divider()) self.images.append(group)
def add_image(self, can_remove=True): '''Add an image + associated questions and buttons''' group = cps.SettingsGroup() if can_remove: group.append("divider", cps.Divider(line=False)) group.append("input_image_name", cps.ImageNameSubscriber( "Select the additional image", cps.NONE, doc=""" Select the additional image to align?""")) group.append("output_image_name", cps.ImageNameProvider( "Name the output image", "AlignedBlue", doc=""" Enter the name of the aligned image?""")) group.append("align_choice", cps.Choice( "Select how the alignment is to be applied", [A_SIMILARLY, A_SEPARATELY], doc=""" An additional image can either be aligned similarly to the second one or a separate alignment to the first image can be calculated: <ul> <li><i>%(A_SIMILARLY)s:</i> The same alignment measurements obtained from the first two input images are applied to this additional image.</li> <li><i>%(A_SEPARATELY)s:</i> A new set of alignment measurements are calculated for this additional image using the alignment method specified with respect to the first input image.</li> </ul>""" % globals())) if can_remove: group.append("remover", cps.RemoveSettingButton("", "Remove above image", self.additional_images, group)) self.additional_images.append(group)
def add_dose_value(self, can_remove=True): '''Add a dose value measurement to the list can_delete - set this to False to keep from showing the "remove" button for images that must be present.''' group = cps.SettingsGroup() group.append("measurement", cps.Measurement("Select the image measurement describing the treatment dose", lambda: cpmeas.IMAGE, doc="""\ The V and Z’ factors, metrics of assay quality, and the EC50, indicating dose-response, are calculated by this module based on each image being specified as a particular treatment dose. Choose a measurement that gives the dose of some treatment for each of your images. See the help for the previous setting for details.""")) group.append("log_transform", cps.Binary( "Log-transform the dose values?", False, doc='''\ Select *%(YES)s* if you have dose-response data and you want to log-transform the dose values before fitting a sigmoid curve. Select *%(NO)s* if your data values indicate only positive vs. negative controls. ''' % globals())) group.append('wants_save_figure', cps.Binary( '''Create dose-response plots?''', False, doc='''Select *%(YES)s* if you want to create and save dose-response plots. You will be asked for information on how to save the plots.''' % globals())) group.append('figure_name', cps.Text( "Figure prefix", "", doc='''\ *(Used only when creating dose-response plots)* CellProfiler will create a file name by appending the measurement name to the prefix you enter here. For instance, if you specify a prefix of “Dose\_”, when saving a file related to objects you have chosen (for example, *Cells*) and a particular measurement (for example, *AreaShape_Area*), CellProfiler will save the figure as *Dose_Cells_AreaShape_Area.m*. Leave this setting blank if you do not want a prefix. ''' )) group.append('pathname', cps.DirectoryPath( "Output file location", dir_choices=[ cps.DEFAULT_OUTPUT_FOLDER_NAME, cps.DEFAULT_INPUT_FOLDER_NAME, cps.ABSOLUTE_FOLDER_NAME, cps.DEFAULT_OUTPUT_SUBFOLDER_NAME, cps.DEFAULT_INPUT_SUBFOLDER_NAME], doc="""\ *(Used only when creating dose-response plots)* This setting lets you choose the folder for the output files. %(IO_FOLDER_CHOICE_HELP_TEXT)s %(IO_WITH_METADATA_HELP_TEXT)s """ % globals())) group.append("divider", cps.Divider()) group.append("remover", cps.RemoveSettingButton("", "Remove this dose measurement", self.dose_values, group)) self.dose_values.append(group)
def add_image_measurement(self, can_remove=True): group = cps.SettingsGroup() if can_remove: group.append("divider", cps.Divider()) group.append("image_name", cps.ImageNameSubscriber( "Select the image to measure", cps.NONE, doc="""\ Choose an image name from the drop-down menu to calculate intensity for that image. Use the *Add another image* button below to add additional images to be measured. You can add the same image multiple times if you want to measure the intensity within several different objects.""")) group.append("wants_objects", cps.Binary( "Measure the intensity only from areas enclosed by objects?", False, doc="""\ Select *%(YES)s* to measure only those pixels within an object type you choose, identified by a prior module. Note that this module will aggregate intensities across all objects in the image: to measure each object individually, see **MeasureObjectIntensity** instead. """ % globals())) group.append("object_name", cps.ObjectNameSubscriber( "Select the input objects", cps.NONE, doc="""\ *(Used only when measuring intensity from area occupied by objects)* Select the objects that the intensity will be aggregated within. The intensity measurement will be restricted to the pixels within these objects.""")) if can_remove: group.append("remover", cps.RemoveSettingButton("", "Remove this image", self.images, group)) self.images.append(group)
def add_channelfn(self, can_remove=True): '''Add another image channel can_remove - true if we are allowed to remove this channel ''' group = cps.SettingsGroup() self.channels.append(group) # Check which cellprofiler image we are in the group # (each channel translates to a single cellprofiler image) cpimg_index = 0 for channel in self.channels: if id(channel) == id(group): break cpimg_index += 1 group.append("divider", cps.Divider(line=True)) group.append("cpimage_name", cps.ImageNameProvider( 'Image name', default_cpimage_name(cpimg_index))) channel_numbers = [ str(x) for x in range(0, max(10, len(self.channels) + 2))] group.append("channel_number", cps.Choice( "Channel number:", channel_numbers, channel_numbers[len(self.channels) - 1], doc="""(Used only for multichannel images) The channels of a multichannel image are numbered starting from 0 (zero). Each channel is a greyscale image, acquired using different illumination sources and/or optics. Use this setting to pick the channel to associate with the image or images you load from OMERO.""")) group.can_remove = can_remove if can_remove: group.append("remover", cps.RemoveSettingButton( "Remove this channel", "Remove channel", self.channels, group))
def add_object_cb(self, can_remove=True): '''Add an object to the object_groups collection can_delete - set this to False to keep from showing the "remove" button for objects that must be present. ''' group = cps.SettingsGroup() if can_remove: group.append("divider", cps.Divider(line=False)) group.append( 'object_name', cps.ObjectNameSubscriber("Select objects to measure", "None", doc=""" What did you call the objects whose texture you want to measure? If you only want to measure the texture for the image overall, you can remove all objects using the "Remove this object" button. <p>Objects specified here will have their texture measured against <i>all</i> images specfied above, which may lead to image-object combinations that are unneccesary. If you do not want this behavior, use multiple <b>EnhancedMeasureTexture</b> modules to specify the particular image-object measures that you want.</p>""" )) if can_remove: group.append( "remover", cps.RemoveSettingButton("", "Remove this object", self.object_groups, group)) self.object_groups.append(group)
def add_image(self, can_remove=True): '''Add an image + associated questions and buttons''' group = cps.SettingsGroup() if can_remove: group.append("divider", cps.Divider(line=False)) group.append( "input_image_name", cps.ImageNameSubscriber("Select the additional image?", cps.NONE, doc=""" What is the name of the additional image to resize? This image will be resized with the same settings as the first image.""" )) group.append( "output_image_name", cps.ImageNameProvider("Name the output image", "ResizedBlue", doc=""" What is the name of the additional resized image?""" )) if can_remove: group.append( "remover", cps.RemoveSettingButton("", "Remove above image", self.additional_images, group)) self.additional_images.append(group)
def create_settings(self): self.flags = [] self.flag_count = cps.HiddenCount(self.flags) self.add_flag_button = cps.DoSomething("", "Add another flag", self.add_flag) self.spacer_1 = cps.Divider() self.add_flag(can_delete=False)
def add_object_group(self, can_remove: bool = True) -> None: group = cps.SettingsGroup() if can_remove: group.append("divider", cps.Divider(line=False)) group.append( "name", cps.ObjectNameSubscriber( text="Select objects to measure", value="None", doc="Select the objects that you want to measure.", ), ) if can_remove: group.append( "remove", cps.RemoveSettingButton( text="", label="Remove this object", list=self.object_groups, entry=group, ), ) self.object_groups.append(group)
def add_mapping(self): group = cps.SettingsGroup() group.append("local_directory", cps.Text( "Local root path", cpprefs.get_default_image_directory(), doc=""" Enter the path to files on this computer. This is the root path on the local machine (i.e., the computer setting up the batch files). If <b>CreateBatchFiles</b> finds any pathname that matches the local root path at the begining, it will replace the start with the cluster root path. <p>For example, if you have mapped the remote cluster machine like this:<br><br> <tt>Z:\your_data\images</tt> (on a Windows machine, for instance)<br><br> and the cluster machine sees the same folder like this:<br><br> <tt>/server_name/your_name/your_data/images</tt><br><br> you would enter <tt>Z:\</tt> here and <t>/server_name/your_name/</tt> for the cluster path in the next setting.""")) group.append("remote_directory", cps.Text( "Cluster root path", cpprefs.get_default_image_directory(), doc=""" Enter the path to files on the cluster. This is the cluster root path, i.e., how the cluster machine sees the top-most folder where your input/output files are stored. <p>For example, if you have mapped the remote cluster machine like this:<br><br> <tt>Z:\your_data\images</tt> (on a Windows machine, for instance)<br><br> and the cluster machine sees the same folder like this:<br><br> <tt>/server_name/your_name/your_data/images</tt><br><br> you would enter <tt>Z:\</tt> in the previous setting for the local machine path and <t>/server_name/your_name/</tt> here. """)) group.append("remover", cps.RemoveSettingButton("", "Remove this path mapping", self.mappings, group)) group.append("divider", cps.Divider(line=False)) self.mappings.append(group)
def add_image(self, can_remove=True): '''Add an image to the list of image names''' group = cps.SettingsGroup() group.append('divider', cps.Divider(line=False)) group.append('image_name', cps.ExternalImageNameProvider('Give this image a name')) if can_remove: group.append('remover', cps.RemoveSettingButton('', 'Remove this image name', self.image_names, group)) self.image_names.append(group)
def create_settings(self): self.images = [] self.add_image(can_remove=False) self.image_count = cps.HiddenCount(self.images) self.add_image_button = cps.DoSomething("", "Add another image", self.add_image) self.divider = cps.Divider() self.objects = [] self.add_object(can_remove=False) self.add_object_button = cps.DoSomething("", "Add another object", self.add_object)
def add_image(self, can_delete=True): '''Add an image and its settings to the list of images''' image_name = cps.ImageNameSubscriber( "Select the input image", cps.NONE, doc="Select the image to be corrected.") corrected_image_name = cps.ImageNameProvider( "Name the output image", "CorrBlue", doc="Enter a name for the corrected image.") illum_correct_function_image_name = cps.ImageNameSubscriber( "Select the illumination function", cps.NONE, doc="""\ Select the illumination correction function image that will be used to carry out the correction. This image is usually produced by another module or loaded as a .npy format image using the **Images** module or **LoadSingleImage**. """) divide_or_subtract = cps.Choice( "Select how the illumination function is applied", [DOS_DIVIDE, DOS_SUBTRACT], doc="""\ This choice depends on how the illumination function was calculated and on your physical model of the way illumination variation affects the background of images relative to the objects in images; it is also somewhat empirical. - *%(DOS_SUBTRACT)s:* Use this option if the background signal is significant relative to the real signal coming from the cells. If you created the illumination correction function using *%(IC_BACKGROUND)s*, then you will want to choose *%(DOS_SUBTRACT)s* here. - *%(DOS_DIVIDE)s:* Choose this option if the signal to background ratio is high (the cells are stained very strongly). If you created the illumination correction function using *%(IC_REGULAR)s*, then you will want to choose *%(DOS_DIVIDE)s* here. """ % globals()) image_settings = cps.SettingsGroup() image_settings.append("image_name", image_name) image_settings.append("corrected_image_name", corrected_image_name) image_settings.append("illum_correct_function_image_name", illum_correct_function_image_name) image_settings.append("divide_or_subtract", divide_or_subtract) image_settings.append("rescale_option", RE_NONE) if can_delete: image_settings.append( "remover", cps.RemoveSettingButton("", "Remove this image", self.images, image_settings)) image_settings.append("divider", cps.Divider()) self.images.append(image_settings)
def add_function(self, can_remove=True): group = MorphSettingsGroup() group.can_remove = can_remove if can_remove: group.append("divider", cps.Divider(line=False)) group.append( "function", cps.Choice( "Select the operation to perform", F_ALL, doc= """Choose one of the operations described in this module's help.""" )) group.append( "repeats_choice", cps.Choice("Number of times to repeat operation", R_ALL, doc="""\ This setting controls the number of times that the same operation is applied successively to the image. - *%(R_ONCE)s:* Perform the operation once on the image. - *%(R_FOREVER)s:* Perform the operation on the image until successive iterations yield the same image. - *%(R_CUSTOM)s:* Perform the operation a custom number of times.""" % globals())) group.append( "custom_repeats", cps.Integer(self.CUSTOM_REPEATS_TEXT, 2, 1, doc=self.CUSTOM_REPEATS_DOC)) group.append( "rescale_values", cps.Binary("Rescale values from 0 to 1?", True, doc="""\ *(Used only for the "%(F_DISTANCE)s" operation).* Select "*%(YES)s*" to rescale the transformed values to lie between 0 and 1. This is the option to use if the distance transformed image is to be used for thresholding by an **Identify** module or the like, which assumes a 0-1 scaling. Select "*%(NO)s*" to leave the values in absolute pixel units. This useful in cases where the actual pixel distances are to be used downstream as input for a measurement module.""" % globals())) if can_remove: group.append( "remove", cps.RemoveSettingButton("", "Remove this operation", self.functions, group)) self.functions.append(group)
def add_heatmap(self): group = cps.SettingsGroup() if len(self.heatmaps) > 0: group.append("divider", cps.Divider(line=False)) group.append("image_name", MORDImageNameSubscriber( "Image", doc=""" The heatmap will be displayed with measurements taken using this image. The setting will let you choose from among the images you have specified in "Select image to measure". """)) group.image_name.set_module(self) group.append("object_name", MORDObjectNameSubscriber( "Objects to display", doc=""" The objects to display in the heatmap. You can select any of the objects chosen in "Select objects to measure". """)) group.object_name.set_module(self) group.append("bin_count", cps.Choice( "Number of bins", self.get_bin_count_choices(), choices_fn=self.get_bin_count_choices)) def get_number_of_bins(module=self, group=group): if len(module.bin_counts) == 1: return module.bin_counts[0].bin_count.value else: return int(group.bin_count.value) group.get_number_of_bins = get_number_of_bins group.append("measurement", cps.Choice( "Measurement", MEASUREMENT_CHOICES, doc="""The measurement to display.""")) group.append("colormap", cps.Colormap( "Color map", doc=""" The color map setting chooses the color palette that will be used to render the different values for your measurement. If you choose "gray", the image will label each of the bins with the actual image measurement. """)) group.append("wants_to_save_display", cps.Binary( "Save display as image?", False, doc="""This setting allows you to save the heatmap display as an image that can be output using the <b>SaveImages</b> module. Choose <i>%(YES)s</i> to save the display or <i>%(NO)s</i> if the display is not needed.""" % globals())) group.append("display_name", cps.ImageNameProvider( "Output image name", "Heatmap", doc=""" <i>(Only used if "Save display as image?" is "%(YES)s")</i><br> This setting names the heatmap image so that the name you enter here can be selected in a later <b>SaveImages</b> or other module. """ % globals())) group.append("remover", cps.RemoveSettingButton( "", "Remove this heatmap display", self.heatmaps, group)) self.heatmaps.append(group)
def add_bin_count(self, can_remove=True): '''Add another radial bin count at which to measure''' group = cps.SettingsGroup() if can_remove: group.append("divider", cps.Divider(line=False)) group.append( "wants_scaled", cps.Binary("Scale the bins?", True, doc=""" <p>Select <i>%(YES)s</i> to divide the object radially into the number of bins that you specify. </p> <p>Select <i>%(NO)s</i> to create the number of bins you specify based on distance. For this option, the user will be asked to specify a maximum distance so that each object will have the same measurements (which might be zero for small objects) and so that the measurements can be taken without knowing the maximum object radius before the run starts.</p>""" % globals())) group.append( "bin_count", cps.Integer("Number of bins", 4, 2, doc=""" Specify the number of bins that you want to use to measure the distribution. Radial distribution is measured with respect to a series of concentric rings starting from the object center (or more generally, between contours at a normalized distance from the object center). This number specifies the number of rings into which the distribution is to be divided. Additional ring counts can be specified by clicking the <i>Add another set of bins</i> button.""")) group.append( "maximum_radius", cps.Integer("Maximum radius", 100, minval=1, doc=""" Specify the maximum radius for the unscaled bins. The unscaled binning method creates the number of bins that you specify and creates equally spaced bin boundaries up to the maximum radius. Parts of the object that are beyond this radius will be counted in an overflow bin. The radius is measured in pixels.""" )) group.can_remove = can_remove if can_remove: group.append( "remover", cps.RemoveSettingButton("", "Remove this set of bins", self.bin_counts, group)) self.bin_counts.append(group)
def add_image(self, can_remove=True): '''Add an image to be measured''' group = cps.SettingsGroup() if can_remove: group.append("divider", cps.Divider(line=False)) group.append("image_name", cps.ImageNameSubscriber( "Select an image to measure", cps.NONE, doc=""" Select the image that you want to measure the intensity from.""")) if can_remove: group.append("remover", cps.RemoveSettingButton("", "Remove this image", self.images, group)) self.images.append(group)
def add_image(self, can_remove=True): '''Add an image + associated questions and buttons''' group = cps.SettingsGroup() if can_remove: group.append("divider", cps.Divider(line=True)) group.append("input_image_name", cps.ImageNameSubscriber("Select an additional image to tile", cps.NONE, doc="""Select an additional image to tile?""")) if can_remove: group.append("remover", cps.RemoveSettingButton("", "Remove above image", self.additional_images, group)) self.additional_images.append(group)
def add_outline(self, can_remove=True): group = cps.SettingsGroup() if can_remove: group.append("divider", cps.Divider(line=False)) group.append( "outline_choice", cps.Choice("Load outlines from an image or objects?", [FROM_OBJECTS, FROM_IMAGES], doc=""" This setting selects what source the outlines come from: <ul> <li><i>%(FROM_OBJECTS)s:</i> Create the image directly from the objects. This option will improve the functionality of the contrast options for this module's interactive display and will save memory.</li> <li><i>%(FROM_IMAGES)s:</i> Prior versions of <b>OverlayOutlines</b> would only display outline images which were optional outputs of the identify modules. For legacy pipelines or to continue using the outline images instead of objects, choose this option.</li> </ul> """ % globals())) group.append( "objects_name", cps.ObjectNameSubscriber( "Select objects to display", cps.NONE, doc="""Choose the objects whose outlines you would like to display.""")) group.append( "outline_name", cps.OutlineNameSubscriber("Select outlines to display", cps.NONE, doc=""" Choose outlines to display, from a previous <b>Identify</b> module. Each of the <b>Identify</b> modules has a checkbox that determines whether the outlines are saved. If you have checked this, you were asked to supply a name for the outline; you can then select that name here. """)) default_color = (COLOR_ORDER[len(self.outlines)] if len(self.outlines) < len(COLOR_ORDER) else COLOR_ORDER[0]) group.append("color", cps.Color("Select outline color", default_color)) if can_remove: group.append( "remover", cps.RemoveSettingButton("", "Remove this outline", self.outlines, group)) self.outlines.append(group)
def add_scale_cb(self, can_remove=True): '''Add a scale to the scale_groups collection can_delete - set this to False to keep from showing the "remove" button for scales that must be present. ''' group = cps.SettingsGroup() if can_remove: group.append("divider", cps.Divider(line=False)) group.append( 'scale', cps.Integer( "Texture scale to measure", len(self.scale_groups) + 3, doc= """You can specify the scale of texture to be measured, in pixel units; the texture scale is the distance between correlated intensities in the image. A higher number for the scale of texture measures larger patterns of texture whereas smaller numbers measure more localized patterns of texture. It is best to measure texture on a scale smaller than your objects' sizes, so be sure that the value entered for scale of texture is smaller than most of your objects. For very small objects (smaller than the scale of texture you are measuring), the texture cannot be measured and will result in a undefined value in the output file.""" )) group.append( 'angles', cps.MultiChoice( "Angles to measure", H_ALL, H_ALL, doc= """The Haralick texture measurements are based on the correlation between pixels offset by the scale in one of four directions: <p><ul> <li><i>%(H_HORIZONTAL)s</i> - the correlated pixel is "scale" pixels to the right of the pixel of interest.</li> <li><i>%(H_VERTICAL)s</i> - the correlated pixel is "scale" pixels below the pixel of interest.</li> <li><i>%(H_DIAGONAL)s</i> - the correlated pixel is "scale" pixels to the right and "scale" pixels below the pixel of interest.</li> <li><i>%(H_ANTIDIAGONAL)s</i> - the correlated pixel is "scale" pixels to the left and "scale" pixels below the pixel of interest.</li> </ul><p> Choose one or more directions to measure.""" % globals())) if can_remove: group.append( "remover", cps.RemoveSettingButton("", "Remove this scale", self.scale_groups, group)) self.scale_groups.append(group)