def create_settings(self): self.object_name = cps.ObjectNameSubscriber( "Input objects", "None", doc="""Enter the name of the objects whose population context is to be measured.""") self.operation = cps.Choice( "Operation", choices=(O_POPULATION_DENSITY, O_DISTANCE_TO_EDGE, O_BOTH), doc="""Select the measurements you wish to perform. The choices are:<br><ul> <li><i>%(O_POPULATION_DENSITY)s</i> - calculate the population density within a radius from each cell.</li> <li><i>%(O_DISTANCE_TO_EDGE)s</i> - calculate the distance of each cell from the edge of a binary mask.</li> <li><i>%(O_BOTH)s</i> - make both measurements""" % globals()) self.radius = cps.Integer( "Search radius", 50, minval=1, doc="""Count all objects within this radius""") self.object_diameter = cps.Integer( "Object diameter", 20, minval=0, doc="""The average diameter of objects in the image. This number is used to adjust the area of the image to account for objects that would otherwise be excluded because they were touching the border.""") self.edge_image = cps.ImageNameSubscriber( "Edge image", doc="""For measuring distance to an edge, this is the reference image. Cell distances will be computed to the nearest foreground / background edge in the reference image.""")
def create_settings(self): self.image_name = cps.ImageNameSubscriber("Select the input image", "None", doc = '''What did you call the image to be resized?''') self.resized_image_name = cps.ImageNameProvider("Name the output image", "ResizedBlue", doc = '''What do you want to call the resized image?''') self.size_method = cps.Choice("Select resizing method", R_ALL, doc = """How do you want to resize the image? <ul><li><i>Resize by a fraction or multiple of the original size:</i> Enter a single value which specifies the scaling. </li> <li><i>Resize by specifying desired final dimensions:</i></li> Enter the new height and width of the resized image.</ul>""") self.resizing_factor = cps.Float("Resizing factor", .25, minval=0, doc = ''' <i>(Used only if resizing by a fraction or multiple of the original size)</i><br> Numbers less than one (that is, fractions) will shrink the image; numbers greater than one (that is, multiples) will enlarge the image.''') self.use_manual_or_image = cps.Choice("How do you want to specify the dimensions?",C_ALL, doc = """ <i>(Used only if resizing by specifying the dimensions)</i><br> You have two options on how to resize your image: <ul> <li><i>Manual:</i> Specify the height and width of the output image.</li> <li><i>Image:</i> Specify an image and the input image will be resized to the same dimensions.</li> </ul>""") self.specific_width = cps.Integer("Width of the final image, in pixels", 100, minval=1, doc = ''' <i>(Used only if resizing by specifying desired final dimensions)</i><br> Enter the desired width of the final image.''') self.specific_height = cps.Integer("Height of the final image, in pixels", 100, minval=1, doc = ''' <i>(Used only if resizing by specifying desired final dimensions)</i><br> Enter the desired height of the final image.''') self.specific_image = cps.ImageNameSubscriber("Select the image with the desired dimensions", "None", doc = """" <i>(Used only if resizing by specifying desired final dimensions using an image)</i><br> The input image will be resized to the dimensions of the specified image.""") self.interpolation = cps.Choice("Interpolation method", I_ALL, doc = '''<ul><li><i>Nearest Neighbor:</i> Each output pixel is given the intensity of the nearest corresponding pixel in the input image.</li> <li><i>Bilinear:</i> Each output pixel is given the intensity of the weighted average of the 2x2 neighborhood at the corresponding position in the input image.</li> <li><i>Bicubic:</i> Each output pixel is given the intensity of the weighted average of the 4x4 neighborhood at the corresponding position in the input image.</li> </ul>''') self.separator = cps.Divider(line=False) self.additional_images = [] self.additional_image_count = cps.HiddenCount( self.additional_images, "Additional image count") self.add_button = cps.DoSomething("", "Add another image", self.add_image)
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=""" If you check this setting, <b>MeasureObjectRadialDistribution</b> will divide the object radially into the number of bins you specify. If you leave the setting unchecked, <b>MeasureObjectRadialDistribution</b> will ask for a maximum radial distance and will divide that distance into the number of bins you specify. It is necessary 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.""")) 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_when(self, can_delete = True): group = cps.SettingsGroup() group.append("choice", cps.Choice( "When should the email be sent?", S_ALL, doc="""Select the kind of event that causes <b>SendEmail</b> to send an email. You have the following choices: <br><ul><li><i>After first cycle:</i> Send an email during processing of the first image cycle.</li> <li><i>After last cycle:</i> Send an email after all processing is complete.</li> <li><i>After group start:</i> Send an email during the first cycle of each group of images.</li> <li><i>After group end:</i> Send an email after all processing for a group is complete.</li> <li><i>Every # of cycles</i> Send an email each time a certain number of image cycles have been processed. You will be prompted for the number of image cycles if you select this choice.</li> <li><i>After cycle #:</i> Send an email after the given number of image cycles have been processed. You will be prompted for the image cycle number if you select this choice. You can add more events if you want emails after more than one image cycle.</li> </ul>""")) group.append("image_set_number", cps.Integer( "Image cycle number", 1, minval = 1, doc=''' <i>(Used only if sending email after a particular cycle number)</i><br> Send an email during processing of the given image cycle. For instance, if you enter 4, then <b>SendEmail</b> will send an email during processing of the fourth image cycle.''')) group.append("image_set_count", cps.Integer( "Image cycle count", 1, minval = 1, doc=''' <i>(Used only if sending email after every N cycles)</i><br> Send an email each time this number of image cycles have been processed. For instance, if you enter 4, then <b>SendEmail</b> will send an email during processing of the fourth, eighth, twelfth, etc. image cycles.''')) group.append("message", cps.Text( "Message text","Notification from CellProfiler", metadata=True, doc="""The body of the message sent from CellProfiler. Your message can include metadata values. For instance, if you group by plate and want to send an email after processing each plate, you could use the message "Finished processing plate \\g<Plate>". """)) if can_delete: group.append("remover", cps.RemoveSettingButton( "Remove this email event", "Remove event", self.when, group)) group.append("divider", cps.Divider()) self.when.append(group)
def add_image(self, can_remove=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_remove: group.append("divider", cps.Divider(line=False)) group.append( "name", cps.ImageNameSubscriber("Select an image to measure", cps.NONE, doc=""" Select the grayscale images whose intensity you want to measure.""" )) group.append( "nchannels", cps.Integer("Number of channels", 1, minval=1, doc=""" Indicate the number of channels of the image stack""")) if can_remove: group.append( "remover", cps.RemoveSettingButton("", "Remove this image", self.images, group)) self.images.append(group)
def add_function(self, can_remove = True): group = MorphSettingsGroup() if can_remove: group.append("divider", cps.Divider(line=False)) group.append("function", cps.Choice("Select the operation to perform", F_ALL, F_OPEN,doc=""" What operation do you want to perform? 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. <ul> <li><i>Once:</i> Perform the operation once on the image.</li> <li><i>Forever:</i> Perform the operation on the image until successive iterations yield the same image.</li> <li><i>Custom:</i> Perform the operation a custom number of times.</li> </ul>""")) group.append("custom_repeats", cps.Integer(self.CUSTOM_REPEATS_TEXT,2,1, doc=self.CUSTOM_REPEATS_DOC)) group.append("scale", cps.Float( "Scale",3, minval=3, doc="""Morphological open, close, erode and dialate are performed with structuring elements which determine the diameter of the circle enclosing the pixels to consider when applying the operation. This setting controls the diameter of the structuring element.""")) if can_remove: group.append("remove", cps.RemoveSettingButton("", "Remove this operation", self.functions, group)) self.functions.append(group)
def test_01_02_set_value(self): s = cps.Integer("foo", value = 5) for test_case in ("06", "-1"): s.value_text = test_case self.assertEqual(s, int(test_case)) self.assertEqual(s.value_text, test_case) s.test_valid(None)
def create_settings(self): # # Put your ImageNameProvider and ImageNameSubscriber here # # use self.input_image_name as the ImageNameSubscriber # use self.output_image_name as the ImageNameProvider # # Those are the names that are expected by the unit tests. # ##self.input_image_name = cps.ImageNameSubscriber("Input image") ##self.output_image_name = cps.ImageNameProvider("Output image", ## "Sharpened") self.scale = cps.Float( "Scale", .5, 0, doc= """This is the sigma of the Gaussian used as the point spread function""" ) # # We use a number of iterations to perform. An alternative or adjunct # would be to have the loop exit based on the estimated error reaching # a certain value # self.iterations = cps.Integer( "Iterations", 10, 1, doc="""The number of times to iterate toward maximum likelihood estimate.""")
def add_probability_map(self, can_remove=True): group = cps.SettingsGroup() group.can_remove = can_remove self.probability_maps.append(group) # The following settings are used for the combine option group.output_image = cps.ImageNameProvider( "Name the output probability map", "ProbabilityMap") group.class_sel = cps.Integer( "Select the class", 0, 0, 42, doc='''Select the class you want to use. The class number corresponds to the label-class in ilastik''') if can_remove: group.remover = cps.RemoveSettingButton("Remove probability map", "Remove", self.probability_maps, group, doc=""" Press the <i>Remove</i> button to remove the probability map image from the list of images produced by this module""")
def create_settings(self): # "self" refers to the module's class attributes self.text_setting = cps.Text("Text setting", "suggested value") self.choice_setting = cps.Choice( "Choice setting", ["Choice 1", "Choice 2", "Choice 3"]) self.binary_setting = cps.Binary("Binary setting", False) self.integer_setting = cps.Integer("Integer setting", 15) self.float_setting = cps.Float("Float setting", 1.5)
def create_settings(self): self.object_name = cps.ObjectNameSubscriber("Select the input objects", "None", doc=''' What did you call the objects you want to expand or shrink?''' ) self.output_object_name = cps.ObjectNameProvider( "Name the output objects", "ShrunkenNuclei", doc=''' What do you want to call the resulting objects?''' ) self.operation = cps.Choice("Select the operation", O_ALL, doc=''' What operation do you want to perform? <ul> <li><i>Shrink objects to a point:</i> Remove all pixels but one from filled objects. Thin objects with holes to loops unless the "fill" option is checked.</li> <li><i>Expand objects until touching:</i> Expand objects, assigning every pixel in the image to an object. Background pixels are assigned to the nearest object.</li> <li><i>Add partial dividing lines between objects:</i> Remove pixels from an object that are adjacent to another object's pixels unless doing so would change the object's Euler number (break an object in two, remove the object completely or open a hole in an object).</li> <li><i>Shrink objects by a specified number of pixels:</i> Remove pixels around the perimeter of an object unless doing so would change the object's Euler number (break the object in two, remove the object completely or open a hole in the object). You can specify the number of times perimeter pixels should be removed. Processing stops automatically when there are no more pixels to remove.</li> <li><i>Expand objects by a specified number of pixels:</i> Expand each object by adding background pixels adjacent to the image. You can choose the number of times to expand. Processing stops automatically if there are no more background pixels.</li> <li><i>Skeletonize each object:</i> Erode each object to its skeleton.</li> <li><i>Remove spurs:</i> Remove or reduce the length of spurs in a skeletonized image. The algorithm reduces spur size by the number of pixels indicated in the setting <i>Number of pixels by which to expand or shrink</i>.</li> </ul> ''') self.iterations = cps.Integer( "Number of pixels by which to expand or shrink", 1, minval=1) self.wants_fill_holes = cps.Binary( "Fill holes in objects so that all objects shrink to a single point?", False, doc=DOC_FILL_HOLES) self.wants_outlines = cps.Binary( "Retain the outlines of the identified objects for use later in the pipeline (for example, in SaveImages)?", False) self.outlines_name = cps.OutlineNameProvider("Name the outline image", "ShrunkenNucleiOutlines", doc=""" <i>(Used only if outlines are to be retained for later use in the pipeline)</i><br> Choose a name for the outlines of the identified objects that will allow them to be selected as an image later in the pipeline.""" )
def create_settings(self): '''Create the module settings and name the module''' self.wants_default_output_directory = cps.Binary( "Store batch files in default output folder?", True, doc=""" Check this box to store batch files in the Default Output folder. Uncheck the box to enter the path to the folder that will be used to store these files.""") self.custom_output_directory = cps.Text( "Output folder path", cpprefs.get_default_output_directory(), doc=""" Enter the path to the output folder.""") # Worded this way not because I am windows-centric but because it's # easier than listing every other OS in the universe except for VMS self.remote_host_is_windows = cps.Binary( "Are the cluster computers running Windows?", False, doc=""" Check this box if the cluster computers are running one of the Microsoft Windows operating systems. If you check this box, <b>CreateBatchFiles</b> will modify all paths to use the Windows file separator (backslash \). If you leave the box unchecked, <b>CreateBatchFiles</b> will modify all paths to use the Unix or Macintosh file separator (slash /).""") self.batch_mode = cps.Binary("Hidden: in batch mode", False) self.distributed_mode = cps.Binary("Hidden: in distributed mode", False) self.default_image_directory = cps.Setting( "Hidden: default input folder at time of save", cpprefs.get_default_image_directory()) self.revision = cps.Integer("Hidden: revision number", 0) self.from_old_matlab = cps.Binary("Hidden: from old matlab", False) self.acknowledge_old_matlab = cps.DoSomething( "Could not update CP1.0 pipeline to be compatible with CP2.0. See module notes.", "OK", self.clear_old_matlab) self.mappings = [] self.add_mapping() self.add_mapping_button = cps.DoSomething("", "Add another path mapping", self.add_mapping, doc=""" Use this option if another path must be mapped because there is a difference between how the local computer sees a folder location vs. how the cluster computer sees the folder location.""") self.check_path_button = cps.DoSomething( "Press this button to check pathnames on the remote server", "Check paths", self.check_paths, doc=""" his button will start a routine that will ask the webserver to check whether the default input and default output folders exist. It will also check whether all remote path mappings exist.""")
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.site_count = cps.Integer("Number of image sites per well", 1, minval=1, doc=""" This setting controls the number of image sets for each well""") self.column_count = cps.Integer("Number of columns per plate", 12, minval=1, doc=""" Enter the number of columns per plate""") self.row_count = cps.Integer("Number of rows per plate", 8, minval=1, doc=""" The number of rows per plate""") self.order = cps.Choice("Order of image data", [O_ROW, O_COLUMN], doc=""" This setting specifies how the input data is ordered (assuming that sites within a well are ordered consecutively): <ul> <li><i>%(O_ROW)s:</i>: The data appears by row and then by column. That is, all columns for a given row (e.g. A01, A02, A03...) appear consecutively, for each row in consecutive order.</li> <li><i>%(O_COLUMN)s:</i> The data appears by column and then by row. That is, all rows for a given column (e.g. A01, B01, C01...) appear consecutively, for each column in consecutive order.</li> </ul> <p>For instance, the SBS Bioimage example (available <a href="http://www.cellprofiler.org/examples.shtml#SBS_Bioimage_CNT">here</a>) has files that are named:<br> Channel1-01-A01.tif<br> Channel1-02-A02.tif<br> ...<br> Channel1-12-A12.tif<br> Channel1-13-B01.tif<br> ...<br> You would use "%(O_ROW)s" to label these because the ordering is by row and then by column.</p>""" % globals())
def create_settings(self): self.omero_host = cps.Text( "Host address", DEFAULT_OMERO_HOST, doc= """Host address of an omero server. Can be an ip-address or a hostname.""" ) self.omero_port = cps.Integer("Port", DEFAULT_OMERO_PORT, doc="""Port of an omero server.""") self.omero_username = cps.Text( "Username", DEFAULT_OMERO_USERNAME, doc="""Username is required for login into an omero server.""") self.omero_password = cps.Text( "Password", DEFAULT_OMERO_PASSWORD, doc="""Password is required for login into an omero server.""") self.omero_object = cps.Choice("Object to load", [MS_IMAGE, MS_DATASET, MS_PLATE], DEFAULT_OMERO_OBJECT) self.omero_object_id = cps.Integer( "Object id", DEFAULT_OMERO_OBJECT_ID, doc= """This is a number that omero uses to uniquely identify an object, be it a dataset, plate, or image.""" ) self.load_channels = cps.DoSomething("", "Load channels from OMERO", self.load_channels) # All the omero images that are loaded are assumed to have # as many or more channels than the highest channel number # the user specifies. self.channels = [] self.channel_count = cps.HiddenCount(self.channels, "Channel count") # Add the first channel self.add_channelfn(False) # Button for adding other channels self.add_channel = cps.DoSomething("", "Add another channel", self.add_channelfn)
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)
def test_01_04_display_integer_setting(self): v = cps.Integer("text",1) app,text_control,edit_control = self.set_setting(v) self.assertTrue(edit_control.Value,'1') self.assertTrue(isinstance(edit_control, wx.TextCtrl)) edit_control.SetValue("2") app.ProcessPendingEvents() edit_control = self.get_edit_control(app,v) self.assertEqual(edit_control.Value,'2') self.assertTrue(v==2) app.frame.Destroy() app.ProcessPendingEvents() app.ProcessIdle()
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 <i>Add another image</i> button below to add additional images which will be measured. You can add the same image multiple times if you want to measure the intensity within several different objects.''')) group.append( "nchannels", cps.Integer("How many channels does the image have?", 1, doc=""" Indicate how many planes this image have. This is needed as the cellprofiler pipeline needs to be independent of the actuall image data. """)) group.append( "wants_objects", cps.Binary( "Measure the intensity only from areas enclosed by objects?", False, doc=""" Select <i>%(YES)s</i> to measure only those pixels within an object of choice.""" % globals())) group.append( "object_name", cps.ObjectNameSubscriber("Select the input objects", cps.NONE, doc=''' <i>(Used only when measuring intensity from area enclosed by objects)</i><br> 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 create_settings(self): self.image_name = cps.ImageNameSubscriber("Select the input image", "None") # The following settings are used for the combine option self.output_image = cps.ImageNameProvider( "Name the output probability map", "ProbabilityMap") self.class_sel = cps.Integer( "Select the class", 0, 0, 42, doc='''Select the class you want to use. The class number corresponds to the label-class in ilastik''') self.h5_directory = cps.DirectoryPath( "Classifier file location", dir_choices=[ DEFAULT_OUTPUT_FOLDER_NAME, DEFAULT_INPUT_FOLDER_NAME, ABSOLUTE_FOLDER_NAME, DEFAULT_INPUT_SUBFOLDER_NAME, DEFAULT_OUTPUT_SUBFOLDER_NAME ], allow_metadata=False, doc= """Select the folder containing the classifier file to be loaded. %(IO_FOLDER_CHOICE_HELP_TEXT)s""" % globals()) def get_directory_fn(): '''Get the directory for the CSV file name''' return self.h5_directory.get_absolute_path() def set_directory_fn(path): dir_choice, custom_path = self.h5_directory.get_parts_from_path( path) self.h5_directory.join_parts(dir_choice, custom_path) self.classifier_file_name = cps.FilenameText( "Classfier file name", "None", doc="""This is the name of the Classfier file.""", get_directory_fn=get_directory_fn, set_directory_fn=set_directory_fn, browse_msg="Choose Classifier file", exts=[("Classfier file (*.h5)", "*.h5"), ("All files (*.*)", "*.*")])
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("bin_count", cps.Integer( "Number of bins",4, 2, doc="""How many bins do 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.""")) if can_remove: group.append("remover", cps.RemoveSettingButton("", "Remove this set of bins", self.bin_counts, group)) self.bin_counts.append(group)
def create_settings(self): # # The ImageNameSubscriber "subscribes" to all ImageNameProviders in # prior modules. Modules before yours will put images into CellProfiler. # The ImageSubscriber gives your user a list of these images # which can then be used as inputs in your module. # self.input_image_name = cps.ImageNameSubscriber( # The text to the left of the edit box "Input image name:", # HTML help that gets displayed when the user presses the # help button to the right of the edit box doc="""This is the image that the module operates on. You can choose any image that is made available by a prior module. <br> <b>ImageTemplate</b> will do something to this image. """) # # The ObjectNameSubscriber is similar - it will ask the user # which object to pick from the list of objects provided by # upstream modules. # self.input_object_name = cps.ObjectNameSubscriber( "Input object name", doc="""These are the objects that the module operates on.""") # # The radial degree is the "N" parameter in the Zernike - how many # inflection points there are, radiating out from the center. Higher # N means more features and a more detailed description # # The setting is an integer setting, bounded between 1 and 50. # N = 50 generates 1200 features! # self.radial_degree = cps.Integer( "Radial degree", 10, minval=1, maxval=50, doc="""Calculate all Zernike features up to the given radial degree. The Zernike function is parameterized by a radial and azimuthal degree. The module will calculate all Zernike features for all azimuthal degrees up to and including the radial degree you enter here.""")
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.""")
def create_settings(self): # "self" refers to the module's class attributes self.text_setting = cps.Text( "Text setting", "suggested value", ## doc = "This is the help for the text setting" ) self.choice_setting = cps.Choice( "Choice setting", ["Choice 1", "Choice 2", "Choice 3"], ## doc = "This is the help for the choice setting" ) self.binary_setting = cps.Binary( "Binary setting", False, ## doc = "This is the help for the binary setting" ) self.integer_setting = cps.Integer( "Integer setting", 15, ## doc = "This is the help for the integer setting" ) self.float_setting = cps.Float( "Float setting", 1.5, doc = "This is the help for the float setting")
def add_bins_cb(self, can_remove=True): '''Add an histogram to the bin_groups collection can_delete - set this to False to keep from showing the "remove" button for histograms that must be present. ''' group = cps.SettingsGroup() if can_remove: group.append("divider", cps.Divider(line=False)) group.append( 'bins', cps.Integer( "Number of bins", len(self.bins_groups) + 3, doc= """How much bins do you want in your histogram? You can calculate several histograms with different number of bins using the "Add another histogram" button.""" )) if can_remove: group.append( "remover", cps.RemoveSettingButton("", "Remove this histogram", self.bins_groups, group)) self.bins_groups.append(group)
def create_settings(self): """Create the settings for the module Create the settings for the module during initialization. """ self.image_name = cps.ImageNameSubscriber("Select the input image", cps.NONE, doc=""" The name of a binary image from a previous module. <b>IdentifyDeadWorms</b> will use this image to establish the foreground and background for the fitting operation. You can use <b>ApplyThreshold</b> to threshold a grayscale image and create the binary mask. You can also use a module such as <b>IdentifyPrimaryObjects</b> to label each worm and then use <b>ConvertObjectsToImage</b> to make the result a mask.""") self.object_name = cps.ObjectNameProvider( "Name the dead worm objects to be identified", "DeadWorms", doc=""" This is the name for the dead worm objects. You can refer to this name in subsequent modules such as <b>IdentifySecondaryObjects</b>""") self.worm_width = cps.Integer("Worm width", 10, minval=1, doc=""" This is the width (the short axis), measured in pixels, of the diamond used as a template when matching against the worm. It should be less than the width of a worm.""") self.worm_length = cps.Integer("Worm length", 100, minval=1, doc=""" This is the length (the long axis), measured in pixels, of the diamond used as a template when matching against the worm. It should be less than the length of a worm""") self.angle_count = cps.Integer("Number of angles", 32, minval=1, doc=""" This is the number of different angles at which the template will be tried. For instance, if there are 12 angles, the template will be rotated by 0°, 15°, 30°, 45° ... 165°. The shape is bilaterally symmetric; that is, you will get the same shape after rotating it by 180°.""") self.wants_automatic_distance = cps.Binary( "Automatically calculate distance parameters?", True, doc=""" This setting determines whether or not <b>IdentifyDeadWorms</b> automatically calculates the parameters used to determine whether two found-worm centers belong to the same worm. <p>Select <i>%(YES)s</i> to have <b>IdentifyDeadWorms</b> automatically calculate the distance from the worm length and width. Select <i>%(NO)s</i> to set the distances manually.</p>""" % globals()) self.space_distance = cps.Float("Spatial distance", 5, minval=1, doc=""" <i>(Used only if not automatically calculating distance parameters)</i><br> Enter the distance for calculating the worm centers, in units of pixels. The worm centers must be at least many pixels apart for the centers to be considered two separate worms.""") self.angular_distance = cps.Float("Angular distance", 30, minval=1, doc=""" <i>(Used only if automatically calculating distance parameters)</i><br> <b>IdentifyDeadWorms</b> calculates the worm centers at different angles. Two worm centers are considered to represent different worms if their angular distance is larger than this number. The number is measured in degrees.""")
def create_settings(self): self.x_object = cps.ObjectNameSubscriber( 'Select the object to display on the X-axis', 'None', doc=''' Choose the name of objects identified by some previous module (such as <b>IdentifyPrimaryObjects</b> or <b>IdentifySecondaryObjects</b>) whose measurements are to be displayed on the X-axis.''' ) self.x_axis = cps.Measurement( 'Select the object measurement to plot on the X-axis', self.get_x_object, 'None', doc=''' Choose the object measurement made by a previous module to display on the X-axis.''') self.y_object = cps.ObjectNameSubscriber( 'Select the object to display on the Y-axis', 'None', doc=''' Choose the name of objects identified by some previous module (such as <b>IdentifyPrimaryObjects</b> or <b>IdentifySecondaryObjects</b>) whose measurements are to be displayed on the Y-axis.''' ) self.y_axis = cps.Measurement( 'Select the object measurement to plot on the Y-axis', self.get_y_object, 'None', doc=''' Choose the object measurement made by a previous module to display on the Y-axis.''') self.gridsize = cps.Integer('Select the grid size', 100, 1, 1000, doc=''' Enter the number of grid regions you want used on each axis. Increasing the number of grid regions increases the resolution of the plot.''') self.xscale = cps.Choice('How should the X-axis be scaled?', ['linear', 'log'], None, doc=''' The X-axis can be scaled either with a <i>linear</i> scale or with a <i>log</i> (base 10) scaling. <p>Using a log scaling is useful when one of the measurements being plotted covers a large range of values; a log scale can bring out features in the measurements that would not easily be seen if the measurement is plotted linearly.</p>''') self.yscale = cps.Choice('How should the Y-axis be scaled?', ['linear', 'log'], None, doc=''' The Y-axis can be scaled either with a <i>linear</i> scale or with a <i>log</i> (base 10) scaling. <p>Using a log scaling is useful when one of the measurements being plotted covers a large range of values; a log scale can bring out features in the measurements that would not easily be seen if the measurement is plotted linearly.</p>''') self.bins = cps.Choice('How should the colorbar be scaled?', ['linear', 'log'], None, doc=''' The colorbar can be scaled either with a <i>linear</i> scale or with a <i>log</i> (base 10) scaling. <p>Using a log scaling is useful when one of the measurements being plotted covers a large range of values; a log scale can bring out features in the measurements that would not easily be seen if the measurement is plotted linearly.''') maps = [m for m in matplotlib.cm.datad.keys() if not m.endswith('_r')] maps.sort() self.colormap = cps.Choice('Select the color map', maps, 'jet', doc=''' Select the color map for the density plot. See this <a href="http://www.astro.princeton.edu/~msshin/science/code/matplotlib_cm/"> page</a> for pictures of the available colormaps.''' ) self.title = cps.Text('Enter a title for the plot, if desired', '', doc=''' Enter a title for the plot. If you leave this blank, the title will default to <i>(cycle N)</i> where <i>N</i> is the current image cycle being executed.''')
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, F_OPEN, 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. <ul> <li><i>%(R_ONCE)s:</i> Perform the operation once on the image.</li> <li><i>%(R_FOREVER)s:</i> Perform the operation on the image until successive iterations yield the same image.</li> <li><i>%(R_CUSTOM)s:</i> Perform the operation a custom number of times.</li> </ul>""" % globals())) group.append( "custom_repeats", cps.Integer(self.CUSTOM_REPEATS_TEXT, 2, 1, doc=self.CUSTOM_REPEATS_DOC)) group.append( "structuring_element", cps.Choice("Structuring element", SE_ALL, SE_DISK, doc=""" <i>(Used only for %(SE_F_TEXT)s)</i><br> The structuring element controls which neighboring pixels participate in the operation. For instance, for the %(F_ERODE)s operation, all pixels in the neighborhood of the pixel must be in the foreground for the pixel to be in the foreground in the output image. If a circular structuring element is used, then a pixel will be in the foreground only if all neighborhood pixels within a circle surrounding the pixel are in the foreground in the input image. <p>The structuring elements are:<br> <ul> <li><i>%(SE_DISK)s</i>: A disk centered on the pixel. The diameter setting determines the circle's diameter and all pixels that are at or closer than that diameter will be in the neighborhood.</li> <li><i>%(SE_ARBITRARY)s</i>: A structuring element which lets the user choose the exact neighborhood pixels to use.</li> <li><i>%(SE_DIAMOND)s</i>: A diamond centered on the pixel. The diameter setting determines the distance between the top and bottom and left and right corners of the diamond.</li> <li><i>%(SE_LINE)s</i>: A line centered on the pixel. The line has two settings. The angle setting gives the rotation of the line in the counter-clockwise direction in degrees, with a horizontal line having an angle of zero. The length of the line is determined by the diameter setting - only pixels at or closer than 1/2 of the diameter are included in the neighborhood. The line is drawn using the <a href="http://dx.doi.org/10.1147%%2Fsj.41.0025"> Bresenham algorithm</a>.</li> <li><i>%(SE_OCTAGON)s</i>: An octagon centered on the pixel. The octagon is inscribed inside a square. The diameter setting controls the length of the square's side. The diameter is rounded to the nearest integer in the series, n * 6 + 1 so a perfect octagon can be drawn.</li> <li><i>%(SE_PAIR)s</i>: The neighborhood of the pixel is composed of the pixel itself and the pixel at the x and y offsets given by the settings.</li> <li><i>%(SE_PERIODIC_LINE)s</i>: The points along a line described by an offset, centered on the pixel. The periodic line has three settings. The neighborhood pixels are all within a circle whose diameter is the diameter setting. Within the circle, pixels are chosen at N times the x and y offset from the center for positive and negative values of N.</li> <li><i>%(SE_RECTANGLE)s</i>: A rectangle centered on the pixel. The rectangle's height and width are given by two settings.</li> <li><i>%(SE_SQUARE)s</i>: a square centered on the pixel. The diameter setting determines the length of the square's side.</li> </ul></p>""" % globals())) group.append( "scale", cps.Float("Diameter", 3, minval=3, doc=""" Morphological open, close, erode and dialate are performed with structuring elements which determine the diameter of the circle enclosing the pixels to consider when applying the operation. This setting controls the diameter of the structuring element.""")) group.append( "x_offset", cps.Float("X offset", 1, doc=""" <i>(Used only for the %(SE_PAIR)s and %(SE_PERIODIC_LINE)s settings)</i>. The X offset to the first neighborhood pixel in the structuring element. """ % globals())) group.append( "y_offset", cps.Float("Y offset", 1, doc=""" <i>(Used only for the %(SE_PAIR)s and %(SE_PERIODIC_LINE)s structuring elements)</i>. The Y offset to the first neighborhood pixel in the structuring element. """ % globals())) group.append( "angle", cps.Float("Angle", 0, minval=-180, maxval=180, doc=""" <i>(Used only for the %(SE_LINE)s structuring element).</i> The angle, in degrees counter-clockwise from the horizontal, of the line. """ % globals())) group.append( "width", cps.Float("Width", 3, minval=1, doc=""" <i>(Used only for the %(SE_RECTANGLE)s structuring element).</i> The width of the rectangle in pixels. """ % globals())) group.append( "height", cps.Float("Height", 3, minval=1, doc=""" <i>(Used only for the %(SE_RECTANGLE)s structuring element).</i> The height of the rectangle in pixels. """ % globals())) group.append( "strel", cps.BinaryMatrix("Custom", doc=""" <i>(Used only for the %(SE_ARBITRARY)s structuring element).</i> This control lets you specify a custom structuring element. """ % globals())) group.append( "rescale_values", cps.Binary("Rescale values from 0 to 1?", True, doc=""" <i>(Used only for the %(F_DISTANCE)s operation).</i> <p>Select <i>%(YES)s</i> 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 <b>Identify</b> module or the like, which assumes a 0-1 scaling.</p> <p>Select <i>%(NO)s</i> 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.</p> """ % globals())) if can_remove: group.append( "remove", cps.RemoveSettingButton("", "Remove this operation", self.functions, group)) self.functions.append(group)
def create_settings(self): self.obj_or_img = cps.Choice( "Compare segmented objects, or foreground/background?", O_ALL) self.ground_truth = cps.ImageNameSubscriber( "Select the image to be used as the ground truth basis for calculating the amount of overlap", cps.NONE, doc = """ <i>(Used only when comparing foreground/background)</i> <br> This binary (black and white) image is known as the "ground truth" image. It can be the product of segmentation performed by hand, or the result of another segmentation algorithm whose results you would like to compare.""") self.test_img = cps.ImageNameSubscriber( "Select the image to be used to test for overlap", cps.NONE, doc = """ <i>(Used only when comparing foreground/background)</i> <br> This binary (black and white) image is what you will compare with the ground truth image. It is known as the "test image".""") self.object_name_GT = cps.ObjectNameSubscriber( "Select the objects to be used as the ground truth basis for calculating the amount of overlap", cps.NONE, doc =""" <i>(Used only when comparing segmented objects)</i> <br> Choose which set of objects will used as the "ground truth" objects. It can be the product of segmentation performed by hand, or the result of another segmentation algorithm whose results you would like to compare. See the <b>Load</b> modules for more details on loading objects.""") self.object_name_ID = cps.ObjectNameSubscriber( "Select the objects to be tested for overlap against the ground truth", cps.NONE, doc =""" <i>(Used only when comparing segmented objects)</i> <br> This set of objects is what you will compare with the ground truth objects. It is known as the "test object." """) self.wants_emd = cps.Binary( "Calculate earth mover's distance?", False, doc="""The earth mover's distance computes the shortest distance that would have to be travelled to move each foreground pixel in the test image to some foreground pixel in the reference image. "Earth mover's" refers to an analogy: the pixels are "earth" that has to be moved by some machine at the smallest possible cost. <br> It would take too much memory and processing time to compute the exact earth mover's distance, so <b>CalculateImageOverlap</b> chooses representative foreground pixels in each image and assigns each foreground pixel to its closest representative. The earth mover's distance is then computed for moving the foreground pixels associated with each representative in the test image to those in the reference image. """) self.max_points = cps.Integer( "Maximum # of points", value=250, minval = 100, doc = """ <i>(Used only when computing the earth mover's distance)</i> <br> This is the number of representative points that will be taken from the foreground of the test image and from the foreground of the reference image using the point selection method (see below). """) self.decimation_method = cps.Choice( "Point selection method", choices = [DM_KMEANS, DM_SKEL], doc = """ <i>(Used only when computing the earth mover's distance)</i> <br> The point selection setting determines how the representative points are chosen. <ul> <li><i>%(DM_KMEANS)s:</i> Select to pick representative points using a K-Means clustering technique. The foregrounds of both images are combined and representatives are picked that minimize the distance to the nearest representative. The same representatives are then used for the test and reference images.</li> <li><i>%(DM_SKEL)s:</i> Select to skeletonize the image and pick points eqidistant along the skeleton. </li> </ul> <dl> <dd><img src="memory:%(PROTIP_RECOMEND_ICON)s"> <i>%(DM_KMEANS)s</i> is a choice that's generally applicable to all images. <i>%(DM_SKEL)s</i> is best suited to long, skinny objects such as worms or neurites.</dd> </dl> """ % globals()) self.max_distance = cps.Integer( "Maximum distance", value=250, minval=1, doc = """ <i>(Used only when computing the earth mover's distance)</i> <br> This setting sets an upper bound to the distance penalty assessed during the movement calculation. As an example, the score for moving 10 pixels from one location to a location that is 100 pixels away is 10*100, but if the maximum distance were set to 50, the score would be 10*50 instead. <br> The maximum distance should be set to the largest reasonable distance that pixels could be expected to move from one image to the next. """) self.penalize_missing = cps.Binary( "Penalize missing pixels", value=False, doc = """ <i>(Used only when computing the earth mover's distance)</i> <br> If one image has more foreground pixels than the other, the earth mover's distance is not well-defined because there is no destination for the extra source pixels or vice-versa. It's reasonable to assess a penalty for the discrepancy when comparing the accuracy of a segmentation because the discrepancy represents an error. It's also reasonable to assess no penalty if the goal is to compute the cost of movement, for example between two frames in a time-lapse movie, because the discrepancy is likely caused by noise or artifacts in segmentation. Set this setting to "Yes" to assess a penalty equal to the maximum distance times the absolute difference in number of foreground pixels in the two images. Set this setting to "No" to assess no penalty. """)
def create_settings(self): """Create the module settings create_settings is called at the end of initialization. """ self.object = cps.ObjectNameSubscriber( 'Select the object whose measurements will be displayed', cps.NONE, doc=''' Choose the name of objects identified by some previous module (such as <b>IdentifyPrimaryObjects</b> or <b>IdentifySecondaryObjects</b>) whose measurements are to be displayed.''' ) self.x_axis = cps.Measurement('Select the object measurement to plot', self.get_object, cps.NONE, doc=''' Choose the object measurement made by a previous module to plot.''') self.bins = cps.Integer('Number of bins', 100, 1, 1000, doc=''' Enter the number of equally-spaced bins that you want used on the X-axis.''') self.xscale = cps.Choice( 'Transform the data prior to plotting along the X-axis?', ['no', 'log'], None, doc=''' The measurement data can be scaled with either a linear scale (<i>No</i>) or a <i>log</i> (base 10) scaling. <p>Log scaling is useful when one of the measurements being plotted covers a large range of values; a log scale can bring out features in the measurements that would not easily be seen if the measurement is plotted linearly.<p>''') self.yscale = cps.Choice('How should the Y-axis be scaled?', ['linear', 'log'], None, doc=''' The Y-axis can be scaled either with either a <i>linear</i> scale or a <i>log</i> (base 10) scaling. <p>Log scaling is useful when one of the measurements being plotted covers a large range of values; a log scale can bring out features in the measurements that would not easily be seen if the measurement is plotted linearly.</p>''') self.title = cps.Text('Enter a title for the plot, if desired', '', doc=''' Enter a title for the plot. If you leave this blank, the title will default to <i>(cycle N)</i> where <i>N</i> is the current image cycle being executed.''') self.wants_xbounds = cps.Binary( 'Specify min/max bounds for the X-axis?', False, doc=''' Select <i>%(YES)s</i> to specify minimum and maximum values for the plot on the X-axis. This is helpful if an outlier bin skews the plot such that the bins of interest are no longer visible.''' % globals()) self.xbounds = cps.FloatRange('Minimum/maximum values for the X-axis')