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.""")
Exemple #2
0
    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)
Exemple #3
0
    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)
Exemple #6
0
 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)
Exemple #7
0
 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)
Exemple #11
0
    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 &#92;). If you
            leave the box unchecked, <b>CreateBatchFiles</b> will modify all paths to use
            the Unix or Macintosh file separator (slash &#47;).""")

        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())
Exemple #14
0
    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())
Exemple #15
0
    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)
Exemple #17
0
    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)
Exemple #18
0
 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()
Exemple #19
0
    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)
Exemple #22
0
    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.""")
Exemple #23
0
    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.""")
Exemple #24
0
 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&deg;, 15&deg;, 30&deg;, 45&deg; ... 165&deg;.
            The shape is bilaterally symmetric; that is, you will get the same shape
            after rotating it by 180&deg;.""")

        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.""")
Exemple #27
0
    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.''')
Exemple #28
0
    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">&nbsp;
         <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')