Esempio n. 1
0
    def create_settings(self):
        """Create your settings by subclassing this function

        create_settings is called at the end of initialization.
        """
        self.grid_image = cps.GridNameProvider("Name the grid",
                                               doc="""\
This is the name of the grid. You can use this name to
retrieve the grid in subsequent modules.""")

        self.grid_rows = cps.Integer(
            "Number of rows",
            8,
            1,
            doc="""Along the height of the grid, define the number of rows.""")

        self.grid_columns = cps.Integer(
            "Number of columns",
            12,
            1,
            doc="""Along the width of the grid, define the number of columns."""
        )

        self.origin = cps.Choice(
            "Location of the first spot",
            [NUM_TOP_LEFT, NUM_BOTTOM_LEFT, NUM_TOP_RIGHT, NUM_BOTTOM_RIGHT],
            doc="""\
Grid cells are numbered consecutively; this option identifies the
origin for the numbering system and the direction for numbering.
For instance, if you choose "*%(NUM_TOP_LEFT)s*", the top left cell is
cell #1 and cells to the right and bottom are indexed with
larger numbers.""" % globals())

        self.ordering = cps.Choice("Order of the spots",
                                   [NUM_BY_ROWS, NUM_BY_COLUMNS],
                                   doc="""\
Grid cells can either be numbered by rows, then columns or by columns,
then rows. For instance, if you asked to start numbering a 96-well
plate at the top left (by specifying the location of the first spot), then:

-  *%(NUM_BY_ROWS)s:* this option will give well A01 the index 1, B01
   the index 2, and so on up to H01 which receives the index 8. Well A02
   will be assigned the index 9.
-  *%(NUM_BY_COLUMNS)s:* with this option, the well A02 will be
   assigned 2, well A12 will be assigned 12 and well B01 will be
   assigned 13.
""" % globals())

        self.each_or_once = cps.Choice("Define a grid for which cycle?",
                                       [EO_EACH, EO_ONCE],
                                       doc="""\
The setting allows you choose when you want to define a new grid:

-  *%(EO_ONCE)s:* If all of your images are perfectly aligned with each
   other (due to very consistent image acquisition, consistent grid
   location within the plate, and/or automatic cropping precisely within
   each plate), you can define the location of the marker spots once for
   all of the image cycles.
-  *%(EO_EACH)s:* If the location of the grid will vary from one image
   cycle to the next then you should define the location of the marker
   spots for each cycle independently.
""" % globals())

        self.auto_or_manual = cps.Choice(
            "Select the method to define the grid", [AM_AUTOMATIC, AM_MANUAL],
            doc="""\
Select whether you would like to define the grid automatically (based on
objects you have identified in a previous module) or manually. This
setting controls how the grid is defined:

-  *%(AM_MANUAL)s:* In manual mode, you manually indicate known
   locations of marker spots in the grid and have the rest of the
   positions calculated from those marks, no matter what the image
   itself looks like. You can define the grid either by clicking on the
   image with a mouse or by entering coordinates.
-  *%(AM_AUTOMATIC)s:* If you would like the grid to be defined
   automatically, an **IdentifyPrimaryObjects** module must be run prior
   to this module to identify the objects that will be used to define
   the grid. The left-most, right-most, top-most, and bottom-most object
   will be used to define the edges of the grid, and the rows and
   columns will be evenly spaced between these edges. Note that
   Automatic mode requires that the incoming objects are nicely defined:
   for example, if there is an object at the edge of the images that is
   not really an object that ought to be in the grid, a skewed grid will
   result. You might wish to use a **FilterObjects** module to clean up
   badly identified objects prior to defining the grid. If the spots are
   slightly out of alignment with each other from one image cycle to the
   next, this allows the identification to be a bit flexible and adapt
   to the real location of the spots.
""" % globals())

        self.object_name = cps.ObjectNameSubscriber(
            "Select the previously identified objects",
            cps.NONE,
            doc="""\
*(Used only if you selected "%(AM_AUTOMATIC)s" to define the grid)*

Select the previously identified objects you want to use to define the
grid. Use this setting to specify the name of the objects that will be
used to define the grid.
""" % globals())

        self.manual_choice = cps.Choice(
            "Select the method to define the grid manually",
            [MAN_MOUSE, MAN_COORDINATES],
            doc="""\
*(Used only if you selected "%(AM_MANUAL)s" to define the grid)*

Specify whether you want to define the grid using the mouse or by
entering the coordinates of the cells.

-  *%(MAN_MOUSE)s:* The user interface displays the image you specify.
   You will be asked to click in the center of two of the grid cells and
   specify the row and column for each. The grid coordinates will be
   computed from this information.
-  *%(MAN_COORDINATES)s:* Enter the X and Y coordinates of the grid
   cells directly. You can display an image of your grid to find the
   locations of the centers of the cells, then enter the X and Y
   position and cell coordinates for each of two cells.
""" % globals())

        self.manual_image = cps.ImageNameSubscriber(
            "Select the image to display",
            cps.NONE,
            doc="""\
*(Used only if you selected "%(AM_MANUAL)s" and "%(MAN_MOUSE)s" to define
the grid)*

Specify the image you want to display when defining the grid. This
setting lets you choose the image to display in the grid definition user
interface.
""" % globals())

        self.first_spot_coordinates = cps.Coordinates(
            "Coordinates of the first cell", (0, 0),
            doc="""\
*(Used only if you selected "%(AM_MANUAL)s" and "%(MAN_COORDINATES)s" to
define the grid)*

Enter the coordinates of the first cell on your grid. This setting
defines the location of the first of two cells in your grid. You should
enter the coordinates of the center of the cell. You can display an
image of your grid and use the pixel coordinate display to determine the
coordinates of the center of your cell.
""" % globals())

        self.first_spot_row = cps.Integer("Row number of the first cell",
                                          1,
                                          minval=1,
                                          doc="""\
*(Used only if you selected "%(AM_MANUAL)s" and "%(MAN_COORDINATES)s" to
define the grid)*

Enter the row index for the first cell here. Rows are numbered starting
at the origin. For instance, if you chose "*%(NUM_TOP_LEFT)s*" as your
origin, well A01 will be row number 1 and H01 will be row number 8. If
you chose "*%(NUM_BOTTOM_LEFT)s*", A01 will be row number 8 and H01 will
be row number 12.
""" % globals())

        self.first_spot_col = cps.Integer("Column number of the first cell",
                                          1,
                                          minval=1,
                                          doc="""\
*(Used only if you selected "%(AM_MANUAL)s" and "%(MAN_COORDINATES)s" to
define the grid)*

Enter the column index for the first cell here. Columns are numbered
starting at the origin. For instance, if you chose "*%(NUM_TOP_LEFT)s*"
as your origin, well A01 will be column number *1* and A12 will be
column number *12*. If you chose "*%(NUM_TOP_RIGHT)s*", A01 and A12 will
be *12* and *1*, respectively.
""" % globals())

        self.second_spot_coordinates = cps.Coordinates(
            "Coordinates of the second cell", (0, 0),
            doc="""\
*(Used only if you selected "%(AM_MANUAL)s" and "%(MAN_COORDINATES)s" to
define the grid)*

This setting defines the location of the second of two cells in your
grid. You should enter the coordinates of the center of the cell. You
can display an image of your grid and use the pixel coordinate
display to determine the coordinates (X,Y) of the center of your cell.
""" % globals())

        self.second_spot_row = cps.Integer("Row number of the second cell",
                                           1,
                                           minval=1,
                                           doc="""\
*(Used only if you selected "%(AM_MANUAL)s" and "%(MAN_COORDINATES)s" to
define the grid)*

Enter the row index for the second cell here. Rows are numbered starting
at the origin. For instance, if you chose "*%(NUM_TOP_LEFT)s*" as your
origin, well A01 will be row number 1 and H01 will be row number 8. If
you chose "*%(NUM_BOTTOM_LEFT)s*", A01 will be row number 8 and H01 will
be row number 12.
""" % globals())

        self.second_spot_col = cps.Integer("Column number of the second cell",
                                           1,
                                           minval=1,
                                           doc="""\
*(Used only if you selected "%(AM_MANUAL)s" and "%(MAN_COORDINATES)s" to
define the grid)*

Enter the column index for the second cell here. Columns are numbered
starting at the origin. For instance, if you chose "*%(NUM_TOP_LEFT)s*"
as your origin, well A01 will be column number 1 and A12 will be column
number 12. If you chose "*%(NUM_TOP_RIGHT)s*", A01 and A12 will be 12
and 1, respectively.
""" % globals())

        self.wants_image = cps.Binary("Retain an image of the grid?",
                                      False,
                                      doc="""\
Select "*%(YES)s*" to retain an image of the grid for use later in the
pipeline. This module can create an annotated image of the grid that can
be saved using the **SaveImages** module.
""" % globals())

        self.display_image_name = cps.ImageNameSubscriber(
            "Select the image on which to display the grid",
            cps.LEAVE_BLANK,
            can_be_blank=True,
            doc="""\
*(Used only if saving an image of the grid)*

Enter the name of the image that should be used as the background for
annotations (grid lines and grid indexes). This image will be used for
the figure and for the saved image.
""")

        self.save_image_name = cps.ImageNameProvider("Name the output image",
                                                     "Grid",
                                                     doc="""\
*(Used only if retaining an image of the grid for use later in the
pipeline)*

Enter the name you want to use for the output image. You can save this
image using the **SaveImages** module.
""")

        self.failed_grid_choice = cps.Choice(
            "Use a previous grid if gridding fails?",
            [FAIL_NO, FAIL_ANY_PREVIOUS, FAIL_FIRST],
            doc="""\
If the gridding fails, this setting allows you to control how the module
responds to the error:

-  *%(FAIL_NO)s:* The module will stop the pipeline if gridding fails.
-  *%(FAIL_ANY_PREVIOUS)s:* The module will use the the most recent
   successful gridding.
-  *%(FAIL_FIRST)s:* The module will use the first gridding.

Note that the pipeline will stop in all cases if gridding fails on the
first image.
""" % globals())
Esempio n. 2
0
    def add_measurement(self, flag_settings, can_delete=True):
        measurement_settings = flag_settings.measurement_settings

        group = cps.SettingsGroup()
        group.append("divider1", cps.Divider(line=False))
        group.append(
            "source_choice",
            cps.Choice(
                "Flag is based on",
                S_ALL,
                doc="""\
-  *%(S_IMAGE)s:* A per-image measurement, such as intensity or
   granularity.
-  *%(S_AVERAGE_OBJECT)s:* The average of all object measurements in
   the image.
-  *%(S_ALL_OBJECTS)s:* All the object measurements in an image,
   without averaging. In other words, if *any* of the objects meet the
   criteria, the image will be flagged.
-  *%(S_RULES)s:* Use a text file of rules produced by CellProfiler
   Analyst. With this option, you will have to ensure that this pipeline
   produces every measurement in the rules file upstream of this module.
-  *%(S_CLASSIFIER)s:* Use a classifier built by CellProfiler Analyst.
""" % globals(),
            ),
        )

        group.append(
            "object_name",
            cps.ObjectNameSubscriber(
                "Select the object to be used for flagging",
                cps.NONE,
                doc="""\
*(Used only when flag is based on an object measurement)*

Select the objects whose measurements you want to use for flagging.
""",
            ),
        )

        def object_fn():
            if group.source_choice == S_IMAGE:
                return cpmeas.IMAGE
            return group.object_name.value

        group.append(
            "rules_directory",
            cps.DirectoryPath(
                "Rules file location",
                doc="""\
*(Used only when flagging using "%(S_RULES)s")*

Select the location of the rules file that will be used for flagging images.
%(IO_FOLDER_CHOICE_HELP_TEXT)s
""" % globals(),
            ),
        )

        def get_directory_fn():
            """Get the directory for the rules file name"""
            return group.rules_directory.get_absolute_path()

        def set_directory_fn(path):
            dir_choice, custom_path = group.rules_directory.get_parts_from_path(
                path)
            group.rules_directory.join_parts(dir_choice, custom_path)

        group.append(
            "rules_file_name",
            cps.FilenameText(
                "Rules file name",
                "rules.txt",
                get_directory_fn=get_directory_fn,
                set_directory_fn=set_directory_fn,
                doc="""\
*(Used only when flagging using "%(S_RULES)s")*

The name of the rules file, most commonly from CellProfiler Analyst's
Classifier. This file should be a plain text file
containing the complete set of rules.

Each line of this file should be a rule naming a measurement to be made
on an image, for instance:

    IF (Image_ImageQuality_PowerLogLogSlope_DNA < -2.5, [0.79, -0.79], [-0.94, 0.94])

The above rule will score +0.79 for the positive category and -0.94
for the negative category for images whose power log slope is less
than -2.5 pixels and will score the opposite for images whose slope is
larger. The filter adds positive and negative and flags the images
whose positive score is higher than the negative score.
""" % globals(),
            ),
        )

        def get_rules_class_choices(group=group):
            """Get the available choices from the rules file"""
            try:
                if group.source_choice == S_CLASSIFIER:
                    return self.get_bin_labels(group)
                elif group.source_choice == S_RULES:
                    rules = self.get_rules(group)
                    nclasses = len(rules.rules[0].weights[0])
                    return [str(i) for i in range(1, nclasses + 1)]
                else:
                    return ["None"]
                rules = self.get_rules(group)
                nclasses = len(rules.rules[0].weights[0])
                return [str(i) for i in range(1, nclasses + 1)]
            except:
                return [str(i) for i in range(1, 3)]

        group.append(
            "rules_class",
            cps.MultiChoice(
                "Class number",
                choices=["1", "2"],
                doc="""\
*(Used only when flagging using "%(S_RULES)s")*

Select which classes to flag when filtering. The CellProfiler Analyst
Classifier user interface lists the names of the classes in order. By
default, these are the positive (class 1) and negative (class 2)
classes. **FlagImage** uses the first class from CellProfiler Analyst
if you choose “1”, etc.

Please note the following:

-  The flag is set if the image falls into the selected class.
-  You can make multiple class selections. If you do so, the module will
   set the flag if the image falls into any of the selected classes.
""" % globals(),
            ),
        )

        group.rules_class.get_choices = get_rules_class_choices

        group.append(
            "measurement",
            cps.Measurement(
                "Which measurement?",
                object_fn,
                doc="""Choose the measurement to be used as criteria.""",
            ),
        )

        group.append(
            "wants_minimum",
            cps.Binary(
                "Flag images based on low values?",
                True,
                doc="""\
Select *Yes* to flag images with measurements below the specified
cutoff. If the measurement evaluates to Not-A-Number (NaN), then the
image is not flagged.
""" % globals(),
            ),
        )

        group.append(
            "minimum_value",
            cps.Float("Minimum value",
                      0,
                      doc="""Set a value as a lower limit."""),
        )

        group.append(
            "wants_maximum",
            cps.Binary(
                "Flag images based on high values?",
                True,
                doc="""\
Select *Yes* to flag images with measurements above the specified
cutoff. If the measurement evaluates to Not-A-Number (NaN), then the
image is not flagged.
""" % globals(),
            ),
        )

        group.append(
            "maximum_value",
            cps.Float("Maximum value",
                      1,
                      doc="""Set a value as an upper limit."""),
        )

        if can_delete:
            group.append(
                "remover",
                cps.RemoveSettingButton("", "Remove this measurement",
                                        measurement_settings, group),
            )

        group.append("divider2", cps.Divider(line=True))
        measurement_settings.append(group)
Esempio n. 3
0
    def create_settings(self):
        self.image_name = cps.ImageNameSubscriber(
            "Select the input image",
            cps.NONE,
            doc=
            """Select the multichannel image you want to convert to grayscale."""
        )

        self.combine_or_split = cps.Choice("Conversion method",
                                           [COMBINE, SPLIT],
                                           doc='''\
How do you want to convert the color image?

-  *%(SPLIT)s:* Splits the channels of a color
   image (e.g., red, green, blue) into separate grayscale images.
-  *%(COMBINE)s:* Converts a color image to a grayscale image by
   combining channels together (e.g., red, green, blue).''' % globals())

        self.rgb_or_channels = cps.Choice("Image type",
                                          [CH_RGB, CH_HSV, CH_CHANNELS],
                                          doc="""\
This setting provides three options to choose from:

-  *%(CH_RGB)s:* The RGB (red, green, blue) color space is the typical
   model in which color images are stored. Choosing this option will
   split the image into red, green, and blue component images.
-  *%(CH_HSV)s:* The HSV (hue, saturation, value) color space is based
   on color characteristics such as tint, shade, and tone.
   Choosing this option will split the image into the hue,
   saturation, and value component images.
-  *%(CH_CHANNELS)s:* Many images contain color channels other than RGB
   or HSV. For instance, GIF and PNG formats can have an alpha
   channel that encodes transparency. TIF formats can have an arbitrary
   number of channels which represent pixel measurements made by
   different detectors, filters or lighting conditions. This setting
   allows you to handle a more complex model for images that
   have more than three channels.""" % globals())

        # The following settings are used for the combine option
        self.grayscale_name = cps.ImageNameProvider("Name the output image",
                                                    "OrigGray",
                                                    doc="""\
*(Used only when combining channels)*

Enter a name for the resulting grayscale image.""")

        self.red_contribution = cps.Float("Relative weight of the red channel",
                                          1,
                                          0,
                                          doc='''\
*(Used only when combining channels)*

Relative weights: If all relative weights are equal, all three colors
contribute equally in the final image. To weight colors relative to each
other, increase or decrease the relative weights.''')

        self.green_contribution = cps.Float(
            "Relative weight of the green channel",
            1,
            0,
            doc='''\
*(Used only when combining channels)*

Relative weights: If all relative weights are equal, all three colors
contribute equally in the final image. To weight colors relative to each
other, increase or decrease the relative weights.''')

        self.blue_contribution = cps.Float(
            "Relative weight of the blue channel",
            1,
            0,
            doc='''\
*(Used only when combining channels)*

Relative weights: If all relative weights are equal, all three colors
contribute equally in the final image. To weight colors relative to each
other, increase or decrease the relative weights.''')

        # The following settings are used for the split RGB option
        self.use_red = cps.Binary('Convert red to gray?',
                                  True,
                                  doc="""\
*(Used only when splitting RGB images)*

Select *"%(YES)s"* to extract the red channel to grayscale. Otherwise, the
red channel will be ignored.
""" % globals())

        self.red_name = cps.ImageNameProvider('Name the output image',
                                              "OrigRed",
                                              doc="""\
*(Used only when splitting RGB images)*

Enter a name for the resulting grayscale image coming from the red channel.""")

        self.use_green = cps.Binary('Convert green to gray?',
                                    True,
                                    doc="""\
*(Used only when splitting RGB images)*

Select *"%(YES)s"* to extract the green channel to grayscale. Otherwise, the
green channel will be ignored.
""" % globals())

        self.green_name = cps.ImageNameProvider('Name the output image',
                                                "OrigGreen",
                                                doc="""\
*(Used only when splitting RGB images)*

Enter a name for the resulting grayscale image coming from the green channel."""
                                                )

        self.use_blue = cps.Binary('Convert blue to gray?',
                                   True,
                                   doc="""\
*(Used only when splitting RGB images)*

Select *"%(YES)s"* to extract the blue channel to grayscale. Otherwise, the
blue channel will be ignored.
""" % globals())

        self.blue_name = cps.ImageNameProvider('Name the output image',
                                               "OrigBlue",
                                               doc="""\
*(Used only when splitting RGB images)*

Enter a name for the resulting grayscale image coming from the blue channel."""
                                               )

        # The following settings are used for the split HSV ption
        self.use_hue = cps.Binary('Convert hue to gray?',
                                  True,
                                  doc="""\
*(Used only when splitting HSV images)*

Select *"%(YES)s"* to extract the hue to grayscale. Otherwise, the hue
will be ignored.
""" % globals())

        self.hue_name = cps.ImageNameProvider('Name the output image',
                                              "OrigHue",
                                              doc="""\
*(Used only when splitting HSV images)*

Enter a name for the resulting grayscale image coming from the hue.""")

        self.use_saturation = cps.Binary('Convert saturation to gray?',
                                         True,
                                         doc="""\
*(Used only when splitting HSV images)*

Select *"%(YES)s"* to extract the saturation to grayscale. Otherwise, the
saturation will be ignored.
""" % globals())

        self.saturation_name = cps.ImageNameProvider('Name the output image',
                                                     "OrigSaturation",
                                                     doc="""\
*(Used only when splitting HSV images)*

Enter a name for the resulting grayscale image coming from the saturation.""")

        self.use_value = cps.Binary('Convert value to gray?',
                                    True,
                                    doc="""\
*(Used only when splitting HSV images)*

Select *"%(YES)s"* to extract the value to grayscale. Otherwise, the
value will be ignored.
""" % globals())

        self.value_name = cps.ImageNameProvider('Name the output image',
                                                "OrigValue",
                                                doc="""\
*(Used only when splitting HSV images)*

Enter a name for the resulting grayscale image coming from the value.""")

        # The alternative model:
        self.channels = []
        self.add_channel(False)
        self.channel_button = cps.DoSomething("", "Add another channel",
                                              self.add_channel)

        self.channel_count = cps.HiddenCount(self.channels, "Channel count")
Esempio n. 4
0
    def add_single_measurement(self, can_delete=True):
        '''Add a single measurement to the group of single measurements

        can_delete - True to include a "remove" button, False if you're not
                     allowed to remove it.
        '''
        group = cps.SettingsGroup()
        if can_delete:
            group.append("divider", cps.Divider(line=True))

        group.append("object_name", cps.ObjectNameSubscriber(
                "Select the object to be classified", cps.NONE,
                doc="""\
The name of the objects to be classified. You can choose from objects
created by any previous module. See **IdentifyPrimaryObjects**,
**IdentifySecondaryObjects**, **IdentifyTertiaryObjects**, or **Watershed**
"""))

        def object_fn():
            return group.object_name.value

        group.append("measurement", cps.Measurement(
                "Select the measurement to classify by", object_fn, doc="""\
*(Used only if using a single measurement)*

Select a measurement made by a previous module. The objects will be
classified according to their values for this measurement.
"""))

        group.append("bin_choice", cps.Choice(
                "Select bin spacing",
                [BC_EVEN, BC_CUSTOM], doc="""\
*(Used only if using a single measurement)*

Select how you want to define the spacing of the bins. You have the
following options:

-  *%(BC_EVEN)s:* Choose this if you want to specify bins of equal
   size, bounded by upper and lower limits. If you want two bins, choose
   this option and then provide a single threshold when asked.
-  *%(BC_CUSTOM)s:* Choose this option to create the indicated number
   of bins at evenly spaced intervals between the low and high
   threshold. You also have the option to create bins for objects that
   fall below or above the low and high threshold.
""" % globals()))

        group.append("bin_count", cps.Integer(
                "Number of bins", 3, minval=1, doc="""\
*(Used only if using a single measurement)*

This is the number of bins that will be created between
the low and high threshold"""
        ))

        group.append("low_threshold", cps.Float(
                "Lower threshold", 0, doc="""\
*(Used only if using a single measurement and "%(BC_EVEN)s" selected)*

This is the threshold that separates the lowest bin from the others. The
lower threshold, upper threshold, and number of bins define the
thresholds of bins between the lowest and highest.
""" % globals()))

        group.append("wants_low_bin", cps.Binary(
                "Use a bin for objects below the threshold?", False, doc="""\
*(Used only if using a single measurement)*

Select "*%(YES)s*" if you want to create a bin for objects whose values
fall below the low threshold. Select "*%(NO)s*" if you do not want a bin
for these objects.
""" % globals()))

        def min_upper_threshold():
            return group.low_threshold.value + np.finfo(float).eps

        group.append("high_threshold", cps.Float(
                "Upper threshold", 1,
                minval=cps.NumberConnector(min_upper_threshold), doc="""\
*(Used only if using a single measurement and "%(BC_EVEN)s" selected)*

This is the threshold that separates the last bin from the others. Note
that if you would like two bins, you should select "*%(BC_CUSTOM)s*".
""" % globals()))

        group.append("wants_high_bin", cps.Binary(
                "Use a bin for objects above the threshold?", False, doc="""\
*(Used only if using a single measurement)*

Select "*%(YES)s*" if you want to create a bin for objects whose values
are above the high threshold.

Select "*%(NO)s*" if you do not want a bin for these objects.
""" % globals()))

        group.append("custom_thresholds", cps.Text(
                "Enter the custom thresholds separating the values between bins",
                "0,1", doc="""\
*(Used only if using a single measurement and "%(BC_CUSTOM)s" selected)*

This setting establishes the threshold values for the bins. You should
enter one threshold between each bin, separating thresholds with commas
(for example, *0.3, 1.5, 2.1* for four bins). The module will create one
more bin than there are thresholds.
""" % globals()))

        group.append("wants_custom_names", cps.Binary(
                "Give each bin a name?", False, doc="""\
*(Used only if using a single measurement)*

Select "*%(YES)s*" to assign custom names to bins you have specified.

Select "*%(NO)s*" for the module to automatically assign names based on
the measurements and the bin number.
""" % globals()))

        group.append("bin_names", cps.Text(
                "Enter the bin names separated by commas", cps.NONE, doc="""\
*(Used only if "Give each bin a name?" is checked)*

Enter names for each of the bins, separated by commas.
An example including three bins might be *First,Second,Third*."""))

        group.append("wants_images", cps.Binary(
                "Retain an image of the classified objects?", False, doc="""\
Select "*%(YES)s*" to keep an image of the objects which is color-coded
according to their classification, for use later in the pipeline (for
example, to be saved by a **SaveImages** module).
""" % globals()))

        group.append("image_name", cps.ImageNameProvider(
                "Name the output image", "ClassifiedNuclei", doc="""Enter the name to be given to the classified object image."""))

        group.can_delete = can_delete

        def number_of_bins():
            '''Return the # of bins in this classification'''
            if group.bin_choice == BC_EVEN:
                value = group.bin_count.value
            else:
                value = len(group.custom_thresholds.value.split(",")) - 1
            if group.wants_low_bin:
                value += 1
            if group.wants_high_bin:
                value += 1
            return value

        group.number_of_bins = number_of_bins

        def measurement_name():
            '''Get the measurement name to use inside the bin name

            Account for conflicts with previous measurements
            '''
            measurement_name = group.measurement.value
            other_same = 0
            for other in self.single_measurements:
                if id(other) == id(group):
                    break
                if other.measurement.value == measurement_name:
                    other_same += 1
            if other_same > 0:
                measurement_name += str(other_same)
            return measurement_name

        def bin_feature_names():
            '''Return the feature names for each bin'''
            if group.wants_custom_names:
                return [name.strip()
                        for name in group.bin_names.value.split(",")]
            return ['_'.join((measurement_name(),
                              'Bin_%d' % (i + 1)))
                    for i in range(number_of_bins())]

        group.bin_feature_names = bin_feature_names

        def validate_group():
            bin_name_count = len(bin_feature_names())
            bin_count = number_of_bins()
            if bin_count < 1:
                bad_setting = (group.bin_count if group.bin_choice == BC_EVEN
                               else group.custom_thresholds)
                raise cps.ValidationError(
                        "You must have at least one bin in order to take measurements. "
                        "Either add more bins or ask for bins for objects above or below threshold",
                        bad_setting)
            if bin_name_count != number_of_bins():
                raise cps.ValidationError(
                        "The number of bin names (%d) does not match the number of bins (%d)." %
                        (bin_name_count, bin_count), group.bin_names)
            for bin_feature_name in bin_feature_names():
                cps.AlphanumericText.validate_alphanumeric_text(
                        bin_feature_name, group.bin_names, True)
            if group.bin_choice == BC_CUSTOM:
                try:
                    [float(x.strip())
                     for x in group.custom_thresholds.value.split(",")]
                except ValueError:
                    raise cps.ValidationError(
                            'Custom thresholds must be a comma-separated list '
                            'of numbers (example: "1.0, 2.3, 4.5")',
                            group.custom_thresholds)

        group.validate_group = validate_group

        if can_delete:
            group.remove_settings_button = cps.RemoveSettingButton(
                    "", "Remove this classification",
                    self.single_measurements, group)
        self.single_measurements.append(group)
Esempio n. 5
0
    def create_settings(self):
        """Create your settings by subclassing this function

        create_settings is called at the end of initialization.

        You should create the setting variables for your module here:
            # Ask the user for the input image
            self.image_name = cellprofiler.settings.ImageNameSubscriber(...)
            # Ask the user for the name of the output image
            self.output_image = cellprofiler.settings.ImageNameProvider(...)
            # Ask the user for a parameter
            self.smoothing_size = cellprofiler.settings.Float(...)
        """
        self.object_name = cps.ObjectNameSubscriber(
            "Select the objects to be edited",
            cps.NONE,
            doc="""\
Choose a set of previously identified objects
for editing, such as those produced by one of the
**Identify** modules (e.g., "*IdentifyPrimaryObjects*", "*IdentifySecondaryObjects*" etc.)."""
        )

        self.filtered_objects = cps.ObjectNameProvider(
            "Name the edited objects",
            "EditedObjects",
            doc="""\
Enter the name for the objects that remain
after editing. These objects will be available for use by
subsequent modules.""")

        self.allow_overlap = cps.Binary("Allow overlapping objects?",
                                        False,
                                        doc="""\
**EditObjectsManually** can allow you to edit an object so that it
overlaps another or it can prevent you from overlapping one object with
another. Objects such as worms or the neurites of neurons may cross each
other and might need to be edited with overlapping allowed, whereas a
monolayer of cells might be best edited with overlapping off.
Select "*%(YES)s*" to allow overlaps or select "*%(NO)s*" to prevent them.
""" % globals())

        self.renumber_choice = cps.Choice("Numbering of the edited objects",
                                          [R_RENUMBER, R_RETAIN],
                                          doc="""\
Choose how to number the objects that remain after editing, which
controls how edited objects are associated with their predecessors:

-  *%(R_RENUMBER)s:* The module will number the objects that remain
   using consecutive numbers. This is a good choice if you do not plan
   to use measurements from the original objects and you only want to
   use the edited objects in downstream modules; the objects that remain
   after editing will not have gaps in numbering where removed objects
   are missing.
-  *%(R_RETAIN)s:* This option will retain each object’s original
   number so that the edited object’s number matches its original
   number. This allows any measurements you make from the edited objects
   to be directly aligned with measurements you might have made of the
   original, unedited objects (or objects directly associated with
   them).
""" % globals())

        self.wants_image_display = cps.Binary("Display a guiding image?",
                                              True,
                                              doc="""\
Select "*%(YES)s*" to display an image and outlines of the objects.

Select "*%(NO)s*" if you do not want a guide image while editing.
""" % globals())

        self.image_name = cps.ImageNameSubscriber("Select the guiding image",
                                                  cps.NONE,
                                                  doc="""\
*(Used only if a guiding image is desired)*

This is the image that will appear when editing objects. Choose an image
supplied by a previous module.
""")
Esempio n. 6
0
    def create_settings(self):
        self.objects_name = cps.ObjectNameSubscriber(
            "Select the input objects",
            cps.NONE,
            doc="""
            Select the objects whose object numbers you want to reassign.
            You can use any objects that were created in previous modules, such as
            <b>IdentifyPrimaryObjects</b> or <b>IdentifySecondaryObjects</b>."""
        )

        self.output_objects_name = cps.ObjectNameProvider(
            "Name the new objects",
            "RelabeledNuclei",
            doc="""
            Enter a name for the objects whose numbers have been reassigned.
            You can use this name in subsequent modules that take objects as inputs."""
        )

        self.relabel_option = cps.Choice("Operation",
                                         [OPTION_UNIFY, OPTION_SPLIT],
                                         doc="""
            You can choose one of the following options:
            <ul>
            <li><i>%(OPTION_UNIFY)s:</i> Assign adjacent or nearby objects the same
            label based on certain criteria. It can be useful, for example,
            to merge together touching objects that were incorrectly split into two pieces
            by an <b>Identify</b> module.</li>
            <li><i>%(OPTION_SPLIT)s:</i> Assign a unique number to separate objects
            that currently share the same label. This can occur if you applied certain
            operations with the <b>Morph</b> module to objects.</li>
            </ul>""" % globals())

        self.unify_option = cps.Choice("Unification method",
                                       [UNIFY_DISTANCE, UNIFY_PARENT],
                                       doc="""
            <i>(Used only with the %(OPTION_UNIFY)s option)</i><br>
            You can unify objects in one of two ways:
            <ul>
            <li><i>%(UNIFY_DISTANCE)s: </i> All objects within a certain pixel radius
            from each other will be unified</li>
            <li><i>%(UNIFY_PARENT)s: </i>All objects which share the same parent
            relationship to another object will be unified. This is not be confused
            with using the <b>RelateObjects</b> module, in which the related objects
            remain as individual objects. See <b>RelateObjects</b> for more details.</li>
            </ul>
            """ % globals())

        self.unification_method = cps.Choice("Output object type",
                                             [UM_DISCONNECTED, UM_CONVEX_HULL],
                                             doc="""
            <i>(Used only with the %(UNIFY_PARENT)s unification method)</i>
            <br>
            <b>ReassignObjectNumbers</b> can either unify the child objects
            and keep them disconnected or it can find the smallest convex
            polygon (the convex hull) that encloses all of a parent's child
            objects. The convex hull will be truncated to include only those
            pixels in the parent - in that case it may not truly be convex.
            Choose %(UM_DISCONNECTED)s to leave the children as
            disconnected pieces. Choose %(UM_CONVEX_HULL)s to create an
            output object that is the convex hull around them all.
            """ % globals())

        self.parent_object = cps.Choice("Select the parent object", [cps.NONE],
                                        choices_fn=self.get_parent_choices,
                                        doc="""
            Select the parent object that will be used to
            unify the child objects. Please note the following:
            <ul>
            <li>You must have established a parent-child relationship
            between the objects using a prior <b>RelateObjects</b> module.</li>
            <li>Primary objects and their associated secondary objects are
            already in a one-to-one parent-child relationship, so it makes no
            sense to unify them here.</li>
            </ul>""")

        self.distance_threshold = cps.Integer(
            "Maximum distance within which to unify objects",
            0,
            minval=0,
            doc="""
            <i>(Used only with the %(OPTION_UNIFY)s option and the %(UNIFY_DISTANCE)s method)</i><br>
            Objects that are less than or equal to the distance
            you enter here, in pixels, will be unified. If you choose zero
            (the default), only objects that are touching will be unified.
            Note that <i>%(OPTION_UNIFY)s </i> will not actually connect or bridge
            the two objects by adding any new pixels; it simply assigns the same object number
            to the portions of the object. The new, unified object
            may therefore consist of two or more unconnected components.""" %
            globals())

        self.wants_image = cps.Binary("Unify using a grayscale image?",
                                      False,
                                      doc="""
            <i>(Used only with the %(OPTION_UNIFY)s option)</i><br>
            Select <i>%(YES)s</i> to use the objects' intensity features to determine whether two
            objects should be unified. If you choose to use a grayscale image,
            <i>%(OPTION_UNIFY)s</i> will unify two objects only if they
            are within the distance you have specified <i>and</i> certain criteria about the objects
            within the grayscale image are met.""" % globals())

        self.image_name = cps.ImageNameSubscriber(
            "Select the grayscale image to guide unification",
            cps.NONE,
            doc="""
            <i>(Used only if a grayscale image is to be used as a guide for unification)</i><br>
            Select the name of an image loaded or created by a previous module."""
        )

        self.minimum_intensity_fraction = cps.Float(
            "Minimum intensity fraction",
            .9,
            minval=0,
            maxval=1,
            doc="""
            <i>(Used only if a grayscale image is to be used as a guide for unification)</i><br>
            Select the minimum acceptable intensity fraction. This will be used
            as described for the method you choose in the next setting.""")

        self.where_algorithm = cps.Choice("Method to find object intensity",
                                          [CA_CLOSEST_POINT, CA_CENTROIDS],
                                          doc="""
            <i>(Used only if a grayscale image is to be used as a guide for unification)</i><br>
            You can use one of two methods to determine whether two
            objects should unified, assuming they meet the distance criteria (as specified above):
            <ul>
            <li><i>%(CA_CENTROIDS)s:</i> When the module considers merging two objects,
            this method identifies the centroid of each object,
            records the intensity value of the dimmer of the two centroids,
            multiplies this value by the <i>minimum intensity fraction</i> to generate a threshold,
            and draws a line between the centroids. The method will unify the
            two objects only if the intensity of every point along the line is above
            the threshold. For instance, if the intensity
            of one centroid is 0.75 and the other is 0.50 and the <i>minimum intensity fraction</i>
            has been chosen to be 0.9, all points along the line would need to have an intensity
            of min(0.75, 0.50) * 0.9 = 0.50 * 0.9 = 0.45.<br>
            This method works well for round cells whose maximum intensity
            is in the center of the cell: a single cell that was incorrectly segmented
            into two objects will typically not have a dim line between the centroids
            of the two halves and will be correctly unified.</li>

            <li><i>%(CA_CLOSEST_POINT)s:</i> This method is useful for unifying irregularly shaped cells
            which are connected. It starts by assigning background pixels in the vicinity of the objects to the nearest
            object. Objects are then unified if each object has background pixels that are:
            <ul>
            <li>Within a distance threshold from each object;</li>
            <li>Above the minimum intensity fraction of the nearest object pixel;</li>
            <li>Adjacent to background pixels assigned to a neighboring object.</li>
            </ul>
            An example of a feature that satisfies the above constraints is a line of
            pixels that connect two neighboring objects and is roughly the same intensity
            as the boundary pixels of both (such as an axon connecting two neurons).</li>
            </ul>""" % globals())

        self.wants_outlines = cps.Binary(
            "Retain outlines of the relabeled objects?",
            False,
            doc="""
            %(RETAINING_OUTLINES_HELP)s""" % globals())

        self.outlines_name = cps.OutlineNameProvider('Name the outlines',
                                                     'RelabeledNucleiOutlines',
                                                     doc="""
            %(NAMING_OUTLINES_HELP)s""" % globals())
    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>IdentifyLinearObjects</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 linear object and then use
            <b>ConvertObjectsToImage</b> to make the result a mask.""")

        self.object_name = cps.ObjectNameProvider(
            "Name the linear objects to be identified",
            "LinearObjects",
            doc="""
            This is the name for the linear objects. You can refer
            to this name in subsequent modules such as
            <b>IdentifySecondaryObjects</b>""")

        self.object_width = cps.Integer("Linear object 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 linear object. It should be less than the width
            of a linear object.""")

        self.object_length = cps.Integer("Linear object 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
            linear object. It should be less than the length of a linear object"""
                                         )

        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>IdentifyLinearObjects</b> automatically calculates the parameters
            used to determine whether two found-linear object centers belong to the
            same linear object.
            <p>Select <i>"Yes"</i> to have <b>IdentifyLinearObjects</b>
            automatically calculate the distance from the linear object length
            and width. Select <i>"No"</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 linear object centers, in units of pixels.
            The linear object centers must be at least many pixels apart for the centers to
            be considered two separate linear objects.""")

        self.angular_distance = cps.Float("Angular distance",
                                          30,
                                          minval=1,
                                          doc="""
            <i>(Used only if automatically calculating distance parameters)</i><br>
            <b>IdentifyLinearObjects</b> calculates the linear object centers at different
            angles. Two linear object centers are considered to represent different
            linear objects if their angular distance is larger than this number. The
            number is measured in degrees.""")

        self.overlap_within_angle = cps.Binary(
            "Combine if overlapping and within angular distance?",
            False,
            doc="""
            This setting determines whether or not
            <b>IdentifyLinearObjects</b> merges putative linear objects that are within the
            angular distance specified AND in which pixels from the two 
            linear objects overlap.
            <p>Select <i>"Yes"</i> to have <b>IdentifyLinearObjects</b>
            merge these linear objects. Select <i>"No"</i> use only the spatial
            distance and angular distance parameters above.</p>""" % globals())
    def create_settings(self):
        '''Create the settings for the module's UI'''
        self.warning = cps.Divider(
            "This module allows you to rename (overwrite) your files. Please "
            "see the help for this module for warnings.")

        self.image_name = cps.FileImageNameSubscriber('Select the input image',
                                                      cps.NONE,
                                                      doc="""
            Select the images associated with the files
            you want to rename. This should be an image loaded by the
            <b>Input</b> modules.
            Be very careful because you will be renaming these files!""")

        self.number_characters_prefix = cps.Integer(
            "Number of characters to retain at start of file name",
            6,
            minval=0,
            doc="""
            Number of characters at the start of the old
            file name that will be copied over verbatim to the new file name. For
            instance, if this setting is "6" and the file name is
            "Image-734.tif", the output file name will also start with
            "Image-".""")

        self.number_characters_suffix = cps.Integer(
            "Number of characters to retain at the end of file name",
            4,
            minval=0,
            doc="""
            Number of characters at the end of the old
            file name that will be copied over verbatim to the new file name. For
            instance, if this setting is "4" and the file name is
            "Image-734.tif", the output file name will also end with ".tif"."""
        )

        self.action = cps.Choice("Handling of remaining characters",
                                 [A_RENUMBER, A_DELETE],
                                 doc="""
            You can either treat the characters between the start and
            end as numbers or you can delete them. If you treat them as numbers,
            you will be given the opportunity to pad the numbers with zeros
            so that all of your file names will have a uniform length. For
            instance, if you were to renumber the highlighted portion of the
            file "Image-<u>734</u>.tif" using four digits, the result would
            be "Image-0734.tif".""")

        self.number_digits = cps.Integer("Number of digits for numbers",
                                         4,
                                         minval=0,
                                         doc="""
            <i>(Used only if %(A_RENUMBER)s is selected)</i><br>
            Use this setting to pad numbers with zeros so that they
            all have a uniform number of characters. For instance, padding
            with four digits has the following result:<br>
            <code><table>
            <tr><th>Original</th><th>Padded</th></tr>
            <tr><td>1</td><td>0001</td></tr>
            <tr><td>10</td><td>0010</td></tr>
            <tr><td>100</td><td>0100</td></tr>
            <tr><td>1000</td><td>1000</td></tr>
            </table></code>""" % globals())

        self.wants_text = cps.Binary("Add text to the file name?",
                                     False,
                                     doc="""
            Select <i>%(YES)s</i> if you want to add text
            to the file name. If you had chosen <i>%(A_RENUMBER)s</i> above,
            the module will add the text after your number.
            If you had chosen <i>%(A_DELETE)s</i>, the module will replace
            the deleted text with the text you enter here.""" % globals())

        self.text_to_add = cps.Text("Replacement text",
                                    "",
                                    doc="""
            <i>(Used only if you chose to add text to the file name)</i><br>
            Enter the text that you want to add to each file name.""")

        self.wants_to_replace_spaces = cps.Binary("Replace spaces?",
                                                  False,
                                                  doc="""
            Select <i>%(YES)s</i> to replace spaces in the final
            version of the file name with some other text.
            <p>Select <i>%(NO)s</i> if the file name can have spaces
            or if none of the file names have spaces.</p>""" % globals())

        self.space_replacement = cps.Text("Space replacement",
                                          "_",
                                          doc="""
            This is the text that will be substituted for spaces
            in your file name.""")
    def create_settings(self):
        """Create your settings by subclassing this function

        create_settings is called at the end of initialization.

        You should create the setting variables for your module here:
            # Ask the user for the input image
            self.image_name = cellprofiler.settings.ImageNameSubscriber(...)
            # Ask the user for the name of the output image
            self.output_image = cellprofiler.settings.ImageNameProvider(...)
            # Ask the user for a parameter
            self.smoothing_size = cellprofiler.settings.Float(...)
        """
        self.objects_or_image = cps.Choice(
                "Display object or image measurements?",
                [OI_OBJECTS, OI_IMAGE], doc="""\
-  *%(OI_OBJECTS)s* displays measurements made on objects.
-  *%(OI_IMAGE)s* displays a single measurement made on an image.
""" % globals())

        self.objects_name = cps.ObjectNameSubscriber(
                "Select the input objects", cps.NONE, doc="""\
*(Used only when displaying object measurements)*

Choose the name of objects identified by some previous module (such as
**IdentifyPrimaryObjects** or **IdentifySecondaryObjects**).
""")

        def object_fn():
            if self.objects_or_image == OI_OBJECTS:
                return self.objects_name.value
            else:
                return cpmeas.IMAGE

        self.measurement = cps.Measurement(
                "Measurement to display", object_fn, doc="""\
Choose the measurement to display. This will be a measurement made by
some previous module on either the whole image (if displaying a single
image measurement) or on the objects you selected.
""")

        self.wants_image = cps.Binary(
                "Display background image?", True,
                doc="""\
Choose whether or not to display the measurements on
a background image. Usually, you will want to see the image
context for the measurements, but it may be useful to save
just the overlay of the text measurements and composite the
overlay image and the original image later. Choose "Yes" to
display the measurements on top of a background image or "No"
to display the measurements on a black background.""")

        self.image_name = cps.ImageNameSubscriber(
                "Select the image on which to display the measurements", cps.NONE, doc="""\
Choose the image to be displayed behind the measurements.
This can be any image created or loaded by a previous module.
If you have chosen not to display the background image, the image
will only be used to determine the dimensions of the displayed image.""")

        self.color_or_text = cps.Choice(
                "Display mode", [CT_TEXT, CT_COLOR],
                doc="""\
*(Used only when displaying object measurements)*

Choose how to display the measurement information. If you choose
%(CT_TEXT)s, **DisplayDataOnImage** will display the numeric value on
top of each object. If you choose %(CT_COLOR)s, **DisplayDataOnImage**
will convert the image to grayscale, if necessary, and display the
portion of the image within each object using a hue that indicates the
measurement value relative to the other objects in the set using the
default color map.
""" % globals())

        self.colormap = cps.Colormap(
                "Color map",
                doc="""\
*(Used only when displaying object measurements)*

This is the color map used as the color gradient for coloring the
objects by their measurement values. See `this page`_ for pictures
of the available colormaps.

.. _this page: http://matplotlib.org/users/colormaps.html
            """)
        self.text_color = cps.Color(
                "Text color", "red", doc="""This is the color that will be used when displaying the text.""")

        self.display_image = cps.ImageNameProvider(
                "Name the output image that has the measurements displayed", "DisplayImage", doc="""\
The name that will be given to the image with the measurements
superimposed. You can use this name to refer to the image in subsequent
modules (such as **SaveImages**).
""")

        self.font_size = cps.Integer(
                "Font size (points)", 10, minval=1, doc="""Set the font size of the letters to be displayed.""")

        self.decimals = cps.Integer(
                "Number of decimals", 2, minval=0, doc="""Set how many decimals to be displayed, for example 2 decimals for 0.01; 3 decimals for 0.001.""")

        self.saved_image_contents = cps.Choice(
                "Image elements to save",
                [E_IMAGE, E_FIGURE, E_AXES], doc="""\
This setting controls the level of annotation on the image:

-  *%(E_IMAGE)s:* Saves the image with the overlaid measurement
   annotations.
-  *%(E_AXES)s:* Adds axes with tick marks and image coordinates.
-  *%(E_FIGURE)s:* Adds a title and other decorations.
""" % globals())

        self.offset = cps.Integer(
                "Annotation offset (in pixels)", 0, doc="""\
Add a pixel offset to the measurement. Normally, the text is
placed at the object (or image) center, which can obscure relevant features of
the object. This setting adds a specified offset to the text, in a random
direction.""")

        self.color_map_scale_choice = cps.Choice(
                "Color map scale",
                [CMS_USE_MEASUREMENT_RANGE, CMS_MANUAL],
                doc="""\
*(Used only when displaying object measurements as a colormap)*

**DisplayDataOnImage** assigns a color to each object’s measurement
value from a colormap when in colormap-mode, mapping the value to a
color along the colormap’s continuum. This mapping has implicit upper
and lower bounds to its range which are the extremes of the colormap.
This setting determines whether the extremes are the minimum and
maximum values of the measurement from among the objects in the
current image or manually-entered extremes.

-  *%(CMS_USE_MEASUREMENT_RANGE)s:* Use the full range of colors to
   get the maximum contrast within the image.
-  *%(CMS_MANUAL)s:* Manually set the upper and lower bounds so that
   images with different maxima and minima can be compared by a uniform
   color mapping.
""" % globals())
        self.color_map_scale = cps.FloatRange(
                "Color map range",
                value=(0.0, 1.0),
                doc="""\
*(Used only when setting a manual colormap range)*

This setting determines the lower and upper bounds of the values for the
color map.
""")
Esempio n. 10
0
    def create_settings(self):
        # Input settings
        self.input_color_choice = cps.Choice(
            "Input image type",
            CC_ALL,
            doc=
            "Specify whether you are combining several grayscale images or loading a single color image.",
        )

        self.wants_red_input = cps.Binary(
            "Use a red image?",
            True,
            doc="""\
*(Used only if input image type is "{CC_GRAYSCALE}")*

Select "*{YES}*" to specify an image to use for the red channel.
""".format(**{
                "CC_GRAYSCALE": CC_GRAYSCALE,
                "YES": YES
            }),
        )

        self.red_input_image = cps.ImageNameSubscriber(
            "Select the red image",
            cps.NONE,
            doc="""\
*(Used only if input image type is "{CC_GRAYSCALE}" and a red image is used)*

Provide an image for the red channel.
""".format(**{"CC_GRAYSCALE": CC_GRAYSCALE}),
        )

        self.wants_green_input = cps.Binary(
            "Use a green image?",
            True,
            doc="""\
*(Used only if input image type is "{CC_GRAYSCALE}")*

Select "*{YES}*" to specify an image to use for the green channel.
""".format(**{
                "CC_GRAYSCALE": CC_GRAYSCALE,
                "YES": YES
            }),
        )

        self.green_input_image = cps.ImageNameSubscriber(
            "Select the green image",
            cps.NONE,
            doc="""\
*(Used only if input image type is "{CC_GRAYSCALE}" and a green image is used)*

Provide an image for the green channel.
""".format(**{"CC_GRAYSCALE": CC_GRAYSCALE}),
        )

        self.wants_blue_input = cps.Binary(
            "Use a blue image?",
            True,
            doc="""\
*(Used only if input image type is "{CC_GRAYSCALE}")*

Select "*{YES}*" to specify an image to use for the blue channel.
""".format(**{
                "CC_GRAYSCALE": CC_GRAYSCALE,
                "YES": YES
            }),
        )

        self.blue_input_image = cps.ImageNameSubscriber(
            "Select the blue image",
            cps.NONE,
            doc="""\
*(Used only if input image type is "{CC_GRAYSCALE}" and a blue image is used)*

Provide an image for the blue channel.
""".format(**{"CC_GRAYSCALE": CC_GRAYSCALE}),
        )

        self.color_input_image = cps.ImageNameSubscriber(
            "Select the color image",
            cps.NONE,
            doc="""
*(Used only if input image type is "{CC_COLOR}")*

Select the color image to use.
""".format(**{"CC_COLOR": CC_COLOR}),
        )

        # Output settings
        self.output_color_choice = cps.Choice(
            "Output image type",
            CC_ALL,
            doc=
            "Specify whether you want to produce several grayscale images or one color image.",
        )

        self.wants_red_output = cps.Binary(
            'Select "*{YES}*" to produce a red image.'.format(**{"YES": YES}),
            True,
            doc="""\
*(Used only if output image type is "{CC_GRAYSCALE}")*

Select "*{YES}*" to produce a grayscale image corresponding to the inverted red channel.
""".format(**{
                "CC_GRAYSCALE": CC_GRAYSCALE,
                "YES": YES
            }),
        )

        self.red_output_image = cps.ImageNameProvider(
            "Name the red image",
            "InvertedRed",
            doc="""\
*(Used only if output image type is "{CC_GRAYSCALE}" and a red image is output)*

Provide a name for the inverted red channel image.
""".format(**{"CC_GRAYSCALE": CC_GRAYSCALE}),
        )

        self.wants_green_output = cps.Binary(
            'Select "*{YES}*" to produce a green image.'.format(
                **{"YES": YES}),
            True,
            doc="""\
*(Used only if output image type is "{CC_GRAYSCALE}")*

Select "*{YES}*" to produce a grayscale image corresponding to the inverted green channel.
""".format(**{
                "CC_GRAYSCALE": CC_GRAYSCALE,
                "YES": YES
            }),
        )

        self.green_output_image = cps.ImageNameProvider(
            "Name the green image",
            "InvertedGreen",
            doc="""\
*(Used only if output image type is "{CC_GRAYSCALE}" and a green image is output)*

Provide a name for the inverted green channel image.
""".format(**{"CC_GRAYSCALE": CC_GRAYSCALE}),
        )

        self.wants_blue_output = cps.Binary(
            'Select "*{YES}*" to produce a blue image.'.format(**{"YES": YES}),
            True,
            doc="""\
*(Used only if output image type is "{CC_GRAYSCALE}")*

Select "*{YES}*" to produce a grayscale image corresponding to the inverted blue channel.
""".format(**{
                "CC_GRAYSCALE": CC_GRAYSCALE,
                "YES": YES
            }),
        )

        self.blue_output_image = cps.ImageNameProvider(
            "Name the blue image",
            "InvertedBlue",
            doc="""\
*(Used only if output image type is "{CC_GRAYSCALE}" and a blue image is output)*

Provide a name for the inverted blue channel image.
""".format(**{"CC_GRAYSCALE": CC_GRAYSCALE}),
        )

        self.color_output_image = cps.ImageNameProvider(
            "Name the inverted color image",
            "InvertedColor",
            doc="""\
*(Used only when producing a color output image)*

Enter a name for the inverted color image.
""",
        )
Esempio n. 11
0
    def create_settings(self):
        self.image_name = cps.ImageNameSubscriber(
            'Select the input image',
            cps.NONE,
            doc="""Select the image to be smoothed""")

        self.filtered_image_name = cps.ImageNameProvider(
            'Name the output image',
            'FilteredImage',
            doc="""Enter a name for the resulting image""")

        self.smoothing_method = cps.Choice('Select smoothing method', [
            FIT_POLYNOMIAL, GAUSSIAN_FILTER, MEDIAN_FILTER,
            SMOOTH_KEEPING_EDGES, CIRCULAR_AVERAGE_FILTER, SM_TO_AVERAGE
        ],
                                           doc="""\
This module smooths images using one of several filters. Fitting a
polynomial is fastest but does not allow a very tight fit compared to
the other methods:

-  *%(FIT_POLYNOMIAL)s:* This method treats the intensity of the image
   pixels as a polynomial function of the x and y position of each
   pixel. It fits the intensity to the polynomial, *A x* :sup:`2` *+ B
   y* :sup:`2` *+ C xy + D x + E y + F*. This will produce a smoothed
   image with a single peak or trough of intensity that tapers off
   elsewhere in the image. For many microscopy images (where the
   illumination of the lamp is brightest in the center of field of
   view), this method will produce an image with a bright central region
   and dimmer edges. But, in some cases the peak/trough of the
   polynomial may actually occur outside of the image itself.
-  *%(GAUSSIAN_FILTER)s:* This method convolves the image with a
   Gaussian whose full width at half maximum is the artifact diameter
   entered. Its effect is to blur and obscure features smaller than the
   artifact diameter and spread bright or dim features larger than the
   artifact diameter.
-  *%(MEDIAN_FILTER)s:* This method finds the median pixel value within
   the artifact diameter you specify. It removes bright or dim features
   that are much smaller than the artifact diameter.
-  *%(SMOOTH_KEEPING_EDGES)s:* This method uses a bilateral filter
   which limits Gaussian smoothing across an edge while applying
   smoothing perpendicular to an edge. The effect is to respect edges in
   an image while smoothing other features. *%(SMOOTH_KEEPING_EDGES)s*
   will filter an image with reasonable speed for artifact diameters
   greater than 10 and for intensity differences greater than 0.1. The
   algorithm will consume more memory and operate more slowly as you
   lower these numbers.
-  *%(CIRCULAR_AVERAGE_FILTER)s:* This method convolves the image with
   a uniform circular averaging filter whose size is the artifact
   diameter entered. This filter is useful for re-creating an
   out-of-focus blur to an image.
-  *%(SM_TO_AVERAGE)s:* Creates a flat, smooth image where every pixel
   of the image equals the average value of the original image.
""" % globals())

        self.wants_automatic_object_size = cps.Binary(
            'Calculate artifact diameter automatically?',
            True,
            doc="""\
*(Used only if “%(GAUSSIAN_FILTER)s”, “%(MEDIAN_FILTER)s”, “%(SMOOTH_KEEPING_EDGES)s” or “%(CIRCULAR_AVERAGE_FILTER)s” is selected)*

Select *%(YES)s* to choose an artifact diameter based on the size of
the image. The minimum size it will choose is 30 pixels, otherwise the
size is 1/40 of the size of the image.

Select *%(NO)s* to manually enter an artifact diameter.
""" % globals())

        self.object_size = cps.Float('Typical artifact diameter',
                                     16.0,
                                     doc="""\
*(Used only if choosing the artifact diameter automatically is set to
“%(NO)s”)*

Enter the approximate diameter (in pixels) of the features to be blurred
by the smoothing algorithm. This value is used to calculate the size of
the spatial filter. %(HELP_ON_MEASURING_DISTANCES)s For most
smoothing methods, selecting a diameter over ~50 will take substantial
amounts of time to process.
""" % globals())

        self.sigma_range = cps.Float('Edge intensity difference',
                                     0.1,
                                     doc="""\
*(Used only if “%(SMOOTH_KEEPING_EDGES)s” is selected)*

Enter the intensity step (which indicates an edge in an image) that you
want to preserve. Edges are locations where the intensity changes
precipitously, so this setting is used to adjust the rough magnitude of
these changes. A lower number will preserve weaker edges. A higher
number will preserve only stronger edges. Values should be between zero
and one. %(HELP_ON_PIXEL_INTENSITIES)s
""" % globals())

        self.clip = cps.Binary('Clip intensities to 0 and 1?',
                               True,
                               doc="""\
*(Used only if "%(FIT_POLYNOMIAL)s" is selected)*

The *%(FIT_POLYNOMIAL)s* method is the only smoothing option that can
yield an output image whose values are outside of the values of the
input image. This setting controls whether to limit the image
intensity to the 0 - 1 range used by CellProfiler.

Select *%(YES)s* to set all output image pixels less than zero to zero
and all pixels greater than one to one.

Select *%(NO)s* to allow values less than zero and greater than one in
the output image.
""" % globals())
Esempio n. 12
0
    def create_settings(self):
        """Create your settings by subclassing this function

        create_settings is called at the end of initialization.
        """
        self.grid_name = cps.GridNameSubscriber("Select the defined grid",
                                                cps.NONE,
                                                doc="""
            Select the name of a grid created by a previous <b>DefineGrid</b>
            module.""")

        self.output_objects_name = cps.ObjectNameProvider(
            "Name the objects to be identified",
            "Wells",
            doc="""
            Enter the name of the grid objects identified by this module. These objects
            will be available for further measurement and processing in subsequent modules."""
        )

        self.shape_choice = cps.Choice("Select object shapes and locations", [
            SHAPE_RECTANGLE, SHAPE_CIRCLE_FORCED, SHAPE_CIRCLE_NATURAL,
            SHAPE_NATURAL
        ],
                                       doc="""
            Use this setting to choose the method to be used to determine the
            grid objects' shapes and locations:
            <ul>
            <li><i>%(SHAPE_RECTANGLE)s:</i> Each object will be created as a rectangle,
            completely occupying the entire grid compartment (rectangle). This option creates
            the rectangular objects based solely on the grid's specifications,
            not on any previously identified guiding objects.</li>
            <li><i>%(SHAPE_CIRCLE_FORCED)s:</i> Each object will be created as a circle, centered
            in the middle of each grid compartment. This option places
            the circular objects' locations based solely on the grid's specifications,
            not on any previously identified guiding objects. The radius of all circles in a grid
            will be constant for the entire grid in each image cycle, and can
            be determined automatically for each image cycle based on the average radius of previously
            identified guiding objects for that image cycle, or instead it can be specified
            as a single radius for all circles in all grids in the entire analysis run.</li>
            <li><i>%(SHAPE_CIRCLE_NATURAL)s:</i> Each object will be created as a circle,
            and each circle's location within its grid compartment will be determined
            based on the location of any previously identified guiding objects within
            that grid compartment. Thus, if a guiding object lies within a particular grid compartment,
            that object's center will be the center of the created circular object.
            If no guiding objects lie within a particular grid compartment, the circular object
            is placed within the center of that grid compartment.  If more than one
            guiding object lies within the grid compartment, they will be combined and the centroid of
            this combined object will be the location of the created circular object.
            Note that guiding objects whose centers are close to the grid edge are ignored.</li>
            <li><i>%(SHAPE_NATURAL)s:</i> Within each grid compartment, the object
            will be identified based on combining all of the parts of guiding objects, if any,
            that fall within the grid compartment.
            Note that guiding objects whose centers are close to the grid edge are ignored.
            If a guiding object does not exist within a grid compartment, an object consisting
            of one single pixel in the middle of the grid compartment will be created.</li>
            </ul>""" % globals())

        self.diameter_choice = cps.Choice(
            "Specify the circle diameter automatically?",
            [AM_AUTOMATIC, AM_MANUAL],
            doc="""
            <i>(Used only if Circle is selected as object shape)</i><br>
            There are two methods for selecting the circle diameter:
            <ul>
            <li><i>%(AM_AUTOMATIC)s:</i> Uses the average diameter of previously identified guiding
            objects as the diameter.</li>
            <li><i>%(AM_MANUAL)s:</i> Lets you specify the diameter directly, as a number.</li>
            </ul>""" % globals())

        self.diameter = cps.Integer("Circle diameter",
                                    20,
                                    minval=2,
                                    doc="""
            <i>(Used only if Circle is selected as object shape and diameter is
            specified manually)</i><br>
            Enter the diameter to be used for each grid circle, in pixels.
            %(HELP_ON_MEASURING_DISTANCES)s""" % globals())

        self.guiding_object_name = cps.ObjectNameSubscriber(
            "Select the guiding objects",
            cps.NONE,
            doc="""
            <i>(Used only if Circle is selected as object shape and diameter is specified
            automatically, or if Natural Location is selected as the object shape)</i><br>
            Select the names of previously identified objects that
            will be used to guide the shape and/or location of the objects created by this
            module, depending on the method chosen.""")

        self.wants_outlines = cps.Binary(
            "Retain outlines of the identified objects?",
            False,
            doc="""
            %(RETAINING_OUTLINES_HELP)s""" % globals())

        self.outlines_name = cps.OutlineNameProvider("Name the outline image",
                                                     "GridOutlines",
                                                     doc="""
            %(NAMING_OUTLINES_HELP)s""" % globals())
Esempio n. 13
0
    def create_settings(self):
        self.input_type = cps.Choice("Select the type of input", [IF_IMAGE],
                                     IF_IMAGE)

        self.image_name = cps.ImageNameSubscriber("Select the image to save",
                                                  cps.NONE,
                                                  doc="""
            <i>(Used only if "%(IF_IMAGE)s", "%(IF_MASK)s" or "%(IF_CROPPING)s" are selected to save)</i><br>
            Select the image you want to save.""" % globals())

        self.input_object_name = cps.ObjectNameSubscriber(
            "Select the objects to save", cps.NONE)

        self.objects_name = cps.ObjectNameSubscriber(
            "Select the objects to crop and save",
            cps.NONE,
            doc="""
            Select the objects that you want to save.""" % globals())

        self.file_name_method = cps.Choice(
            "Select method for constructing file names", [
                FN_FROM_IMAGE,
            ],
            doc="""
            Several choices are available for constructing the image file name:
            <ul>
            <li><i>%(FN_FROM_IMAGE)s:</i> The filename will be constructed based
            on the original filename of an input image specified in <b>NamesAndTypes</b>.
            You will have the opportunity to prefix or append
            additional text.
            <p>If you have metadata associated with your images, you can append an text
            to the image filename using a metadata tag. This is especially useful if you
            want your output given a unique label according to the metadata corresponding
            to an image group. The name of the metadata to substitute can be provided for
            each image for each cycle using the <b>Metadata</b> module.
            %(USING_METADATA_TAGS_REF)s%(USING_METADATA_HELP_REF)s.</p></li>
            </ul>""" % globals())

        self.file_image_name = cps.FileImageNameSubscriber(
            "Select image name for file prefix",
            cps.NONE,
            doc="""
            <i>(Used only when "%(FN_FROM_IMAGE)s" is selected for contructing the filename)</i><br>
            Select an image loaded using <b>NamesAndTypes</b>. The original filename will be
            used as the prefix for the output filename.""" % globals())

        self.wants_file_name_suffix = cps.Binary(
            "Append a suffix to the image file name?",
            False,
            doc="""
            Select <i>%(YES)s</i> to add a suffix to the image's file name.
            Select <i>%(NO)s</i> to use the image name as-is.""" % globals())

        self.file_name_suffix = cps.Text("Text to append to the image name",
                                         "",
                                         metadata=True,
                                         doc="""
            <i>(Used only when constructing the filename from the image filename)</i><br>
            Enter the text that should be appended to the filename specified above."""
                                         )

        self.file_format = cps.Choice("Saved file format", [FF_TIFF],
                                      value=FF_TIFF,
                                      doc="""
            <i>(Used only when saving non-movie files)</i><br>
            Select the image or movie format to save the image(s). Most common
            image formats are available; MAT-files are readable by MATLAB.""")

        self.pathname = SaveImagesDirectoryPath("Output file location",
                                                self.file_image_name,
                                                doc="""
            <i>(Used only when saving non-movie files)</i><br>
            This setting lets you choose the folder for the output
            files. %(IO_FOLDER_CHOICE_HELP_TEXT)s
            <p>An additional option is the following:
            <ul>
            <li><i>Same folder as image</i>: Place the output file in the same folder
            that the source image is located.</li>
            </ul></p>
            <p>%(IO_WITH_METADATA_HELP_TEXT)s %(USING_METADATA_TAGS_REF)s.
            For instance, if you have a metadata tag named
            "Plate", you can create a per-plate folder by selecting one the subfolder options
            and then specifying the subfolder name as "\g&lt;Plate&gt;". The module will
            substitute the metadata values for the current image set for any metadata tags in the
            folder name.%(USING_METADATA_HELP_REF)s.</p>
            <p>If the subfolder does not exist when the pipeline is run, CellProfiler will
            create it.</p>
            <p>If you are creating nested subfolders using the sub-folder options, you can
            specify the additional folders separated with slashes. For example, "Outlines/Plate1" will create
            a "Plate1" folder in the "Outlines" folder, which in turn is under the Default
            Input/Output Folder. The use of a forward slash ("/") as a folder separator will
            avoid ambiguity between the various operating systems.</p>""" %
                                                globals())

        self.bit_depth = cps.Choice(
            "Image bit depth", [BIT_DEPTH_8, BIT_DEPTH_16, BIT_DEPTH_FLOAT],
            doc="""
            <i>(Used only when saving files in a non-MAT format)</i><br>
            Select the bit-depth at which you want to save the images.
            <i>%(BIT_DEPTH_FLOAT)s</i> saves the image as floating-point decimals
            with 32-bit precision in its raw form, typically scaled between
            0 and 1.
            <b>%(BIT_DEPTH_16)s and %(BIT_DEPTH_FLOAT)s images are supported only
            for TIF formats. Currently, saving images in 12-bit is not supported.</b>"""
            % globals())

        self.object_extension = cps.Integer("Object extension",
                                            value=1,
                                            doc="""
            How many pixels should the bounding box of the objects be extended
                                            before cropping""")

        self.overwrite = cps.Binary(
            "Overwrite existing files without warning?",
            False,
            doc="""
            Select <i>%(YES)s</i> to automatically overwrite a file if it already exists.
            Select <i>%(NO)s</i> to be prompted for confirmation first.
            <p>If you are running the pipeline on a computing cluster,
            select <i>%(YES)s</i> since you will not be able to intervene and answer the confirmation prompt.</p>"""
            % globals())

        self.when_to_save = cps.Choice("When to save", [WS_FIRST_CYCLE],
                                       doc="""<a name='when_to_save'>
            <i>(Used only when saving non-movie files)</i><br>
            Specify at what point during pipeline execution to save file(s). </a>
            <ul>
            <li><i>%(WS_EVERY_CYCLE)s:</i> Useful for when the image of interest is created every cycle and is
            not dependent on results from a prior cycle.</li>
            </ul> """ % globals())

        self.update_file_names = cps.Binary(
            "Record the file and path information to the saved image?",
            False,
            doc="""
            Select <i>%(YES)s</i> to store filename and pathname data for each of the new files created
            via this module as a per-image measurement.
            <p>Instances in which this information may be useful include:
            <ul>
            <li>Exporting measurements to a database, allowing
            access to the saved image. If you are using the machine-learning tools or image
            viewer in CellProfiler Analyst, for example, you will want to enable this setting if you want
            the saved images to be displayed along with the original images.</li>
            <li>Allowing downstream modules (e.g., <b>CreateWebPage</b>) to access
            the newly saved files.</li>
            </ul></p>""" % globals())

        self.create_subdirectories = cps.Binary(
            "Create subfolders in the output folder?",
            False,
            doc="""
            Select <i>%(YES)s</i> to create subfolders to match the input image folder structure."""
            % globals())

        self.root_dir = cps.DirectoryPath("Base image folder",
                                          doc="""
            <i>Used only if creating subfolders in the output folder</i>
            In subfolder mode, <b>SaveImages</b> determines the folder for
            an image file by examining the path of the matching input file.
            The path that SaveImages uses is relative to the image folder
            chosen using this setting. As an example, input images might be stored
            in a folder structure of "images%(sep)s<i>experiment-name</i>%(sep)s
            <i>date</i>%(sep)s<i>plate-name</i>". If the image folder is
            "images", <b>SaveImages</b> will store images in the subfolder,
            "<i>experiment-name</i>%(sep)s<i>date</i>%(sep)s<i>plate-name</i>".
            If the image folder is "images%(sep)s<i>experiment-name</i>",
            <b>SaveImages</b> will store images in the subfolder,
            <i>date</i>%(sep)s<i>plate-name</i>".
            """ % dict(sep=os.path.sep))
    def create_settings(self):
        self.sub_object_name = cps.ObjectNameSubscriber(
            'Select the input child objects',
            cps.NONE,
            doc="""
            Child objects are defined as those objects contained within the
            parent object. For example, when relating speckles to the
            nuclei that contains them, the speckles are the children.""")

        self.parent_name = cps.ObjectNameSubscriber(
            'Select the input parent objects',
            cps.NONE,
            doc="""
            Parent objects are defined as those objects which encompass the
            child object. For example, when relating speckles to the
            nuclei that contains them, the nuclei are the parents.""")

        self.find_parent_child_distances = cps.Choice(
            "Calculate child-parent distances?",
            D_ALL,
            doc="""
            Choose the method to calculate distances of each child to its parent.
            <ul>
            <li><i>%(D_NONE)s:</i> Do not calculate any distances.</li>
            <li><i>%(D_MINIMUM)s:</i> The distance from the
            centroid of the child object to the closest perimeter point on
            the parent object.</li>
            <li><i>%(D_CENTROID)s:</i> The distance from the
            centroid of the child object to the centroid of the parent. </li>
            <li><i>%(D_BOTH)s:</i> Calculate both the <i>%(D_MINIMUM)s</i> and
            <i>%(D_CENTROID)s</i> distances.</li>
            </ul>""" % globals())

        self.wants_step_parent_distances = cps.Binary(
            "Calculate distances to other parents?",
            False,
            doc="""
            <i>(Used only if calculating distances)</i><br>
            Select <i>%(YES)s</i> to calculate the distances of the child objects to
            some other objects. These objects must be either parents or
            children of your parent object in order for this module to
            determine the distances. For instance, you might find "Nuclei" using
            <b>IdentifyPrimaryObjects</b>, find "Cells" using
            <b>IdentifySecondaryObjects</b> and find "Cytoplasm" using
            <b>IdentifyTertiaryObjects</b>. You can use <b>Relate</b> to relate
            speckles to cells and then measure distances to nuclei and
            cytoplasm. You could not use <b>RelateObjects</b> to relate speckles to
            cytoplasm and then measure distances to nuclei, because nuclei is
            neither a direct parent or child of cytoplasm.""" % globals())
        self.step_parent_names = []

        self.add_step_parent(can_delete=False)

        self.add_step_parent_button = cps.DoSomething("", "Add another parent",
                                                      self.add_step_parent)

        self.wants_per_parent_means = cps.Binary(
            'Calculate per-parent means for all child measurements?',
            False,
            doc="""
            Select <i>%(YES)s</i> to calculate the per-parent mean values of every upstream
            measurement made with the children objects and stores them as a
            measurement for the parent; the nomenclature of this new measurements is
            "Mean_&lt;child&gt;_&lt;category&gt;_&lt;feature&gt;".
            For this reason, this module should be placed <i>after</i> all <b>Measure</b>
            modules that make measurements of the children objects.""" %
            globals())
Esempio n. 15
0
    def create_settings(self):
        # XXX needs to use cps.SettingsGroup
        class Operand(object):
            '''Represents the collection of settings needed by each operand'''
            def __init__(self, index, operation):
                self.__index = index
                self.__operation = operation
                self.__operand_choice = cps.Choice(
                    self.operand_choice_text(),
                    MC_ALL,
                    doc=
                    """Indicate whether the operand is an image or object measurement."""
                )

                self.__operand_objects = cps.ObjectNameSubscriber(
                    self.operand_objects_text(),
                    cps.NONE,
                    doc=
                    """Choose the objects you want to measure for this operation."""
                )

                self.__operand_measurement = cps.Measurement(
                    self.operand_measurement_text(),
                    self.object_fn,
                    doc="""\
Enter the category that was used to create the measurement. You
will be prompted to add additional information depending on
the type of measurement that is requested.""")

                self.__multiplicand = cps.Float(
                    "Multiply the above operand by",
                    1,
                    doc=
                    """Enter the number by which you would like to multiply the above operand."""
                )

                self.__exponent = cps.Float(
                    "Raise the power of above operand by",
                    1,
                    doc=
                    """Enter the power by which you would like to raise the above operand."""
                )

            @property
            def operand_choice(self):
                '''Either MC_IMAGE for image measurements or MC_OBJECT for object'''
                return self.__operand_choice

            @property
            def operand_objects(self):
                '''Get measurements from these objects'''
                return self.__operand_objects

            @property
            def operand_measurement(self):
                '''The measurement providing the value of the operand'''
                return self.__operand_measurement

            @property
            def multiplicand(self):
                '''Premultiply the measurement by this value'''
                return self.__multiplicand

            @property
            def exponent(self):
                '''Raise the measurement to this power'''
                return self.__exponent

            @property
            def object(self):
                '''The name of the object for measurement or "Image"'''
                if self.operand_choice == MC_IMAGE:
                    return cpmeas.IMAGE
                else:
                    return self.operand_objects.value

            def object_fn(self):
                if self.__operand_choice == MC_IMAGE:
                    return cpmeas.IMAGE
                elif self.__operand_choice == MC_OBJECT:
                    return self.__operand_objects.value
                else:
                    raise NotImplementedError(
                        "Measurement type %s is not supported" %
                        self.__operand_choice.value)

            def operand_name(self):
                '''A fancy name based on what operation is being performed'''
                if self.__index == 0:
                    return ("first operand" if self.__operation
                            in (O_ADD, O_MULTIPLY) else "minuend"
                            if self.__operation == O_SUBTRACT else "numerator")
                elif self.__index == 1:
                    return ("second operand" if self.__operation
                            in (O_ADD, O_MULTIPLY) else "subtrahend" if
                            self.__operation == O_SUBTRACT else "denominator")

            def operand_choice_text(self):
                return self.operand_text("Select the %s measurement type")

            def operand_objects_text(self):
                return self.operand_text("Select the %s objects")

            def operand_text(self, format):
                return format % self.operand_name()

            def operand_measurement_text(self):
                return self.operand_text("Select the %s measurement")

            def settings(self):
                '''The operand settings to be saved in the output file'''
                return [
                    self.operand_choice, self.operand_objects,
                    self.operand_measurement, self.multiplicand, self.exponent
                ]

            def visible_settings(self):
                '''The operand settings to be displayed'''
                self.operand_choice.text = self.operand_choice_text()
                self.operand_objects.text = self.operand_objects_text()
                self.operand_measurement.text = self.operand_measurement_text()
                result = [self.operand_choice]
                result += ([self.operand_objects] if self.operand_choice == MC_OBJECT \
                               else [])
                result += [
                    self.operand_measurement, self.multiplicand, self.exponent
                ]
                return result

        self.output_feature_name = cps.AlphanumericText(
            "Name the output measurement",
            "Measurement",
            doc=
            """Enter a name for the measurement calculated by this module.""")

        self.operation = cps.Choice("Operation",
                                    O_ALL,
                                    doc="""\
Choose the arithmetic operation you would like to perform. *None* is
useful if you simply want to select some of the later options in the
module, such as multiplying or exponentiating your image by a constant.
""")

        self.operands = (Operand(0,
                                 self.operation), Operand(1, self.operation))

        self.spacer_1 = cps.Divider(line=True)

        self.spacer_2 = cps.Divider(line=True)

        self.spacer_3 = cps.Divider(line=True)

        self.wants_log = cps.Binary(
            "Take log10 of result?",
            False,
            doc=
            """Select *%(YES)s* if you want the log (base 10) of the result."""
            % globals())

        self.final_multiplicand = cps.Float("Multiply the result by",
                                            1,
                                            doc="""\
*(Used only for operations other than "None")*

Enter the number by which you would like to multiply the result.
""")

        self.final_exponent = cps.Float("Raise the power of result by",
                                        1,
                                        doc="""\
*(Used only for operations other than "None")*

Enter the power by which you would like to raise the result.
""")

        self.final_addend = cps.Float(
            "Add to the result",
            0,
            doc="""Enter the number you would like to add to the result.""")

        self.constrain_lower_bound = cps.Binary(
            "Constrain the result to a lower bound?",
            False,
            doc=
            """Select *%(YES)s* if you want the result to be constrained to a lower bound."""
            % globals())

        self.lower_bound = cps.Float(
            "Enter the lower bound",
            0,
            doc="""Enter the lower bound of the result here.""")

        self.constrain_upper_bound = cps.Binary(
            "Constrain the result to an upper bound?",
            False,
            doc=
            """Select *%(YES)s* if you want the result to be constrained to an upper bound."""
            % globals())

        self.upper_bound = cps.Float(
            "Enter the upper bound",
            1,
            doc="""Enter the upper bound of the result here.""")
Esempio n. 16
0
    def create_settings(self):
        self.image_name = cps.ImageNameSubscriber("Select the input image",
                                                  cps.NONE,
                                                  doc="""
            Choose the image to be cropped.""")

        self.cropped_image_name = cps.CroppingNameProvider(
            "Name the output image",
            "CropBlue",
            doc="""
            Enter the name to be given to cropped image.""")

        self.shape = cps.Choice(
            "Select the cropping shape",
            [SH_RECTANGLE, SH_ELLIPSE, SH_IMAGE, SH_OBJECTS, SH_CROPPING],
            SH_RECTANGLE,
            doc="""
            Select the shape into which you would like to crop:
            <ul>
            <li><i>%(SH_RECTANGLE)s:</i> Self-explanatory.</li>
            <li><i>%(SH_ELLIPSE)s:</i> Self-explanatory.</li>
            <li><i>%(SH_IMAGE)s:</i> Cropping will occur based on a binary image you specify. A choice box
            with available images will appear from which
            you can select an image. To crop into an arbitrary shape that you define, choose
            <i>%(SH_IMAGE)s</i> and use the <b>LoadSingleImage</b> module to load a black and white image
            that you have already prepared from a file. If you have created this image in a
            program such as Photoshop, this binary image should contain only the values 0 and 255,
            with zeros (black) for the parts you want to remove and 255 (white) for
            the parts you want to retain. Alternately, you may have previously generated a
            binary image using this module (e.g., using the <i>%(SH_ELLIPSE)s</i> option) and saved
            it using the <b>SaveImages</b> module.<br>
            In any case, the image must be exactly the same starting size as your image
            and should contain a contiguous block of white pixels, because
            the cropping module may remove rows and columns that are
            completely blank.</li>
            <li><i>%(SH_OBJECTS)s:</i> Crop based on labeled objects identified by a previous
            <b>Identify</b> module.</li>
            <li><i>%(SH_CROPPING)s:</i> The cropping generated by a previous cropping module.
            You will be able to select images that were generated by previous <b>Crop</b> modules.
            This <b>Crop</b> module will use the same cropping that was used to generate whichever image
            you choose.</li>
            </ul>""" % globals())

        self.crop_method = cps.Choice("Select the cropping method",
                                      [CM_COORDINATES, CM_MOUSE],
                                      CM_COORDINATES,
                                      doc="""
            Choose whether you would like to crop by typing in pixel coordinates or clicking with the mouse.
            <ul>
            <li><i>%(CM_COORDINATES)s:</i> For <i>%(SH_ELLIPSE)s</i>, you will be asked to enter the geometric
            parameters of the ellipse. For <i>%(SH_RECTANGLE)s</i>, you will be asked to specify
            the coordinates of the corners.</li>
            <li><i>%(CM_MOUSE)s:</i> For <i>%(SH_ELLIPSE)s</i>, you will be asked to click five or more
            points to define an ellipse around the part of the image you want to
            analyze.  Keep in mind that the more points you click, the longer it will
            take to calculate the ellipse shape. For <i>%(SH_RECTANGLE)s</i>, you can click as many
            points as you like that are in the interior of the region you wish to
            retain.</li>
            </ul>""" % globals())

        self.individual_or_once = cps.Choice(
            "Apply which cycle's cropping pattern?",
            [IO_INDIVIDUALLY, IO_FIRST],
            IO_INDIVIDUALLY,
            doc="""
            Specify how a given cropping pattern should be
            applied to other image cycles:
            <ul>
            <li><i>%(IO_FIRST)s:</i> The cropping pattern from the first image cycle is applied to all
            subsequent cyles. This is useful if the first image is intended to function as a template
            in some fashion.</li>
            <li><i>%(IO_INDIVIDUALLY)s:</i> Every image cycle is cropped individually.</li>
            </ul>""" % globals())

        self.horizontal_limits = cps.IntegerOrUnboundedRange(
            "Left and right rectangle positions",
            minval=0,
            doc="""
            <i>(Used only if %(SH_RECTANGLE)s selected as cropping shape, or if using Plate Fix)</i><br>
            Specify the left and right positions for the bounding rectangle by selecting one of the following:<br>
            <ul>
            <li><i>%(ABSOLUTE)s:</i> Specify these values as absolute pixel
            coordinates in the original image. For instance, you might enter
            "25", "225", and "Absolute" to create a 200&times;200 pixel image that is
            25 pixels from the top-left corner.</li>
            <li><i>%(FROM_EDGE)s:</i> Specify the position relative to the image
            edge. For instance, you might enter "25", "25", and "Edge" to
            crop 25 pixels from both the left and right edges of the image, irrespective
            of the image's original size.</li>
            </ul>""" % globals())

        self.vertical_limits = cps.IntegerOrUnboundedRange(
            "Top and bottom rectangle positions",
            minval=0,
            doc="""
            <i>(Used only if %(SH_RECTANGLE)s selected as cropping shape, or if using Plate Fix)</i><br>
            Specify the top and bottom positions for the bounding rectangle by selecting one of the following:<br>
            <ul>
            <li><i>%(ABSOLUTE)s:</i> Specify these values as absolute pixel coordinates.
            For instance, you might enter "25", "225", and "Absolute"
            to create a 200&times;200 pixel image that's 25 pixels
            from the top-left corner.</li>
            <li><i>%(FROM_EDGE)s:</i> Specify position relative to the image edge.
            For instance, you might enter "25", "25", and "Edge" to
            crop 25 pixels from the edges of your images irrespective
            of their size.</li>
            </ul>""" % globals())

        self.ellipse_center = cps.Coordinates("Coordinates of ellipse center",
                                              (500, 500),
                                              doc="""
            <i>(Used only if %(SH_ELLIPSE)s selected as cropping shape)</i><br>
            Specify the center pixel position of the ellipse.""" % globals())

        self.ellipse_x_radius = cps.Integer("Ellipse radius, X direction",
                                            400,
                                            doc="""
            <i>(Used only if %(SH_ELLIPSE)s selected as cropping shape)</i><br>
            Specify the radius of the ellipse in the X direction.""" %
                                            globals())

        self.ellipse_y_radius = cps.Integer("Ellipse radius, Y direction",
                                            200,
                                            doc="""
            <i>(Used only if %(SH_ELLIPSE)s selected as cropping shape)</i><br>
            Specify the radius of the ellipse in the Y direction.""" %
                                            globals())

        self.image_mask_source = cps.ImageNameSubscriber(
            "Select the masking image",
            cps.NONE,
            doc="""
            <i>(Used only if %(SH_IMAGE)s selected as cropping shape)</i><br>
            Select the image to be use as a cropping mask.""" % globals())

        self.cropping_mask_source = cps.CroppingNameSubscriber(
            "Select the image with a cropping mask",
            cps.NONE,
            doc="""
            <i>(Used only if %(SH_CROPPING)s selected as cropping shape)</i><br>
            Select the image associated with the cropping mask that you want to use."""
            % globals())

        self.objects_source = cps.ObjectNameSubscriber("Select the objects",
                                                       cps.NONE,
                                                       doc="""
            <i>(Used only if %(SH_OBJECTS)s selected as cropping shape)</i><br>
            Select the objects that are to be used as a cropping mask.""" %
                                                       globals())

        self.use_plate_fix = cps.Binary("Use Plate Fix?",
                                        False,
                                        doc="""
            <i>(Used only if %(SH_IMAGE)s selected as cropping shape)</i><br>
            Select <i>%(YES)s</i> to attempt to regularize the edges around a previously-identified
            plate object.
            <p>When attempting to crop based on a previously identified object
            such as a rectangular plate, the plate may not have
            precisely straight edges: there might be a tiny, almost unnoticeable
            "appendage" sticking out. Without Plate Fix, the <b>Crop</b>
            module would not crop the image tightly enough: it would retain the tiny appendage, leaving a lot
            of blank space around the plate and potentially causing problems with later
            modules (especially ones involving illumination correction). </p>
            <p>Plate Fix takes the
            identified object and crops to exclude any minor appendages (technically,
            any horizontal or vertical line where the object covers less than 50%% of
            the image). It also sets pixels around the edge of the object (for
            regions greater than 50%% but less than 100%%) that otherwise would be 0 to the
            background pixel value of your image, thus avoiding problems with
            other modules. </p>
            <p><i>Important note:</i> Plate Fix uses the coordinates
            entered in the boxes normally used for rectangle cropping (Top, Left and
            Bottom, Right) to tighten the edges around your identified plate. This
            is done because in the majority of plate identifications you do not want
            to include the sides of the plate. If you would like the entire plate to
            be shown, you should enter "1:end" for both coordinates. If, for example, you would like
            to crop 80 pixels from each edge of the plate, you could enter Top, Left and Bottom,
            Right values of 80 and select <i>%(FROM_EDGE)s</i>.</p>""" %
                                        globals())

        self.remove_rows_and_columns = cps.Choice(
            "Remove empty rows and columns?", [RM_NO, RM_EDGES, RM_ALL],
            RM_ALL,
            doc="""
            Use this option to choose whether to remove rows and columns that lack objects:
            <ul>
            <li><i>%(RM_NO)s:</i> Leave the image the same size. The cropped areas will be set
            to zeroes, and will appear as black.</li>
            <li><i>%(RM_EDGES)s:</i> Crop the image so that its top, bottom, left and right are at
            the first non-blank pixel for that edge.</li>
            <li><i>%(RM_ALL)s:</i> Remove any row or column of all-blank pixels, even from the
            internal portion of the image.</li>
            </ul>""" % globals())
Esempio n. 17
0
    def create_settings(self):
        self.input_image = cps.ImageNameSubscriber(
            "Select an input image",
            cps.NONE,
            doc=
            """Select the image to be tiled. Additional images within the cycle can be
added later by choosing the "*%(T_ACROSS_CYCLES)s*"option below.
""" % globals())

        self.output_image = cps.ImageNameProvider(
            "Name the output image",
            "TiledImage",
            doc="""Enter a name for the final tiled image.""")

        self.additional_images = []

        self.add_button = cps.DoSomething(
            "",
            "Add another image",
            self.add_image,
            doc="""Add images from other channels to perform similar tiling""")

        self.tile_method = cps.Choice("Tile assembly method",
                                      T_ALL,
                                      doc='''\
This setting controls the method by which the final tiled image is
asembled:

-  *%(T_WITHIN_CYCLES)s:* If you have loaded more than one image for
   each cycle using modules upstream in the pipeline, the images can be
   tiled. For example, you may tile three different channels (OrigRed,
   OrigBlue, and OrigGreen), and a new tiled image will be created for
   every image cycle.
-  *%(T_ACROSS_CYCLES)s:* If you want to tile images from multiple
   cycles together, select this option. For example, you may tile all
   the images of the same type (e.g., OrigBlue) across all fields of
   view in your experiment, which will result in one final tiled image
   when processing is complete.
''' % globals())

        self.rows = cps.Integer("Final number of rows",
                                8,
                                doc='''\
Specify the number of rows would you like to have in the tiled image.
For example, if you want to show your images in a 96-well format, enter
8.

*Special cases:* Let *M* be the total number of slots for images (i.e,
number of rows x number of columns) and *N* be the number of actual
images.

-  If *M* > *N*, blanks will be used for the empty slots.
-  If the *M* < *N*, an error will occur since there are not enough
   image slots. Check “Automatically calculate number of rows?” to avoid
   this error.
''')

        self.columns = cps.Integer("Final number of columns",
                                   12,
                                   doc='''\
Specify the number of columns you like to have in the tiled image. For
example, if you want to show your images in a 96-well format, enter 12.

*Special cases:* Let *M* be the total number of slots for images (i.e,
number of rows x number of columns) and *N* be the number of actual
images.

-  If *M* > *N*, blanks will be used for the empty slots.
-  If the *M* < *N*, an error will occur since there are not enough
   image slots. Check “Automatically calculate number of columns?” to
   avoid this error.
''')

        self.place_first = cps.Choice(
            "Image corner to begin tiling",
            P_ALL,
            doc=
            '''Where do you want the first image to be placed? Begin in the upper
left-hand corner for a typical multi-well plate format where the first image is A01.
''')

        self.tile_style = cps.Choice(
            "Direction to begin tiling",
            S_ALL,
            doc=
            '''This setting specifies the order that the images are to be arranged. If
your images are named A01, A02, etc, enter *%(S_ROW)s*".
''' % globals())

        self.meander = cps.Binary("Use meander mode?",
                                  False,
                                  doc='''\
Select "*%(YES)s*" to tile adjacent images in one direction, then the next
row/column is tiled in the opposite direction. Some microscopes capture
images in this fashion. The default mode is “comb”, or “typewriter”
mode; in this mode, when one row is completely tiled in one direction,
the next row starts near where the first row started and tiles again in
the same direction.
''' % globals())

        self.wants_automatic_rows = cps.Binary(
            "Automatically calculate number of rows?",
            False,
            doc="""\
**Tile** can automatically calculate the number of rows in the grid
based on the number of image cycles that will be processed. Select
"*%(YES)s*" to create a grid that has the number of columns that you
entered and enough rows to display all of your images. Select "*%(NO)s*"
to specify the number of rows.

If you check both automatic rows and automatic columns, **Tile** will
create a grid that has roughly the same number of rows and columns.
""" % globals())

        self.wants_automatic_columns = cps.Binary(
            "Automatically calculate number of columns?",
            False,
            doc="""\
**Tile** can automatically calculate the number of columns in the grid
from the number of image cycles that will be processed. Select "*%(YES)s*"
to create a grid that has the number of rows that you entered and enough
columns to display all of your images. Select "*%(NO)s*" to specify the
number of rows.

If you check both automatic rows and automatic columns, **Tile** will
create a grid that has roughly the same number of rows and columns.
""" % globals())
    def create_settings(self):
        '''Create the settings for the ExportToCellH5 module'''
        self.directory = cps.DirectoryPath("Output file location",
                                           doc="""
            This setting lets you choose the folder for the output files.
            %(IO_FOLDER_CHOICE_HELP_TEXT)s
            """ % globals())

        def get_directory_fn():
            '''Get the directory for the CellH5 file'''
            return self.directory.get_absolute_path()

        def set_directory_fn(path):
            dir_choice, custom_path = self.directory.get_parts_from_path(path)
            self.directory.join_parts(dir_choice, custom_path)

        self.file_name = cps.FilenameText("Output file name",
                                          "DefaultOut.ch5",
                                          get_directory_fn=get_directory_fn,
                                          set_directory_fn=set_directory_fn,
                                          metadata=True,
                                          browse_msg="Choose CellH5 file",
                                          mode=cps.FilenameText.MODE_APPEND,
                                          exts=[("CellH5 file (*.cellh5)",
                                                 "*.ch5"),
                                                ("HDF5 file (*.h5)", "*.h5"),
                                                ("All files (*.*", "*.*")],
                                          doc="""
            This setting lets you name your CellH5 file. If you choose an
            existing file, CellProfiler will add new data to the file
            or overwrite existing locations.
            <p>%(IO_WITH_METADATA_HELP_TEXT)s %(USING_METADATA_TAGS_REF)s.
            For instance, if you have a metadata tag named
            "Plate", you can create a per-plate folder by selecting one the subfolder options
            and then specifying the subfolder name as "\g&lt;Plate&gt;". The module will
            substitute the metadata values for the current image set for any metadata tags in the
            folder name.%(USING_METADATA_HELP_REF)s.</p>

            """ % globals())
        self.overwrite_ok = cps.Binary(
            "Overwrite existing data without warning?",
            False,
            doc="""
            Select <i>%(YES)s</i> to automatically overwrite any existing data
            for a site. Select <i>%(NO)s</i> to be prompted first.

            If you are running the pipeline on a computing cluster,
            select <i>%(YES)s</i> unless you want execution to stop because you
            will not be prompted to intervene. Also note that two instances
            of CellProfiler cannot write to the same file at the same time,
            so you must ensure that separate names are used on a cluster.
            """ % globals())
        self.repack = cps.Binary("Repack after analysis",
                                 True,
                                 doc="""
            This setting determines whether CellProfiler in multiprocessing mode
            repacks the data at the end of analysis. If you select <i>%(YES)s</i>,
            CellProfiler will combine all of the satellite files into a single
            file upon completion. This option requires some extra temporary disk
            space and takes some time at the end of analysis, but results in
            a single file which may occupy less disk space. If you select
            <i>%(NO)s</i>, CellProfiler will create a master file using the
            name that you give and this file will have links to individual
            data files that contain the actual data. Using the data generated by
            this option requires that you keep the master file and the linked
            files together when copying them to a new folder.
            """ % globals())
        self.plate_metadata = cps.Choice("Plate metadata", [],
                                         value="Plate",
                                         choices_fn=self.get_metadata_choices,
                                         doc="""
            This is the metadata tag that identifies the plate name of
            the images for the current cycle. Choose <i>None</i> if
            your assay does not have metadata for plate name. If your
            assay is slide-based, you can use a metadata item that identifies
            the slide as the choice for this setting and set the well
            and site metadata items to <i>None</i>.""")
        self.well_metadata = cps.Choice(
            "Well metadata", [],
            value="Well",
            choices_fn=self.get_metadata_choices,
            doc="""This is the metadata tag that identifies the well name
            for the images in the current cycle. Choose <i>None</i> if
            your assay does not have metadata for the well.""")
        self.site_metadata = cps.Choice(
            "Site metadata", [],
            value="Site",
            choices_fn=self.get_metadata_choices,
            doc="""This is the metadata tag that identifies the site name
                for the images in the current cycle. Choose <i>None</i> if
                your assay doesn't divide wells up into sites or if this
                tag is not required for other reasons.""")
        self.divider = cps.Divider()
        self.wants_to_choose_measurements = cps.Binary("Choose measurements?",
                                                       False,
                                                       doc="""
            This setting lets you choose between exporting all measurements or
            just the ones that you choose. Select <i>%(YES)s</i> to pick the
            measurements to be exported. Select <i>%(NO)s</i> to automatically
            export all measurements available at this stage of the pipeline.
            """ % globals())
        self.measurements = cps.MeasurementMultiChoice(
            "Measurements to export",
            doc="""
            <i>(Used only if choosing measurements.)</i>
            <br>
            This setting lets you choose individual measurements to be exported.
            Check the measurements you want to export.
            """)
        self.objects_to_export = []
        self.add_objects_button = cps.DoSomething("Add objects to export",
                                                  "Add objects",
                                                  self.add_objects)
        self.images_to_export = []
        self.add_image_button = cps.DoSomething("Add an image to export",
                                                "Add image", self.add_image)
        self.objects_count = cps.HiddenCount(self.objects_to_export)
        self.images_count = cps.HiddenCount(self.images_to_export)
    def create_settings(self):
        self.object_name = cps.ObjectNameSubscriber(
            "Select objects to measure",
            cps.NONE,
            doc="""\
Select the objects whose neighbors you want to measure.""",
        )

        self.neighbors_name = cps.ObjectNameSubscriber(
            "Select neighboring objects to measure",
            cps.NONE,
            doc="""\
This is the name of the objects that are potential
neighbors of the above objects. You can find the neighbors
within the same set of objects by selecting the same objects
as above.""",
        )

        self.distance_method = cps.Choice(
            "Method to determine neighbors",
            D_ALL,
            D_EXPAND,
            doc="""\
There are several methods by which to determine whether objects are
neighbors:

-  *%(D_ADJACENT)s:* In this mode, two objects must have adjacent
   boundary pixels to be neighbors.
-  *%(D_EXPAND)s:* The objects are expanded until all pixels on the
   object boundaries are touching another. Two objects are neighbors if
   any of their boundary pixels are adjacent after expansion.
-  *%(D_WITHIN)s:* Each object is expanded by the number of pixels you
   specify. Two objects are neighbors if they have adjacent pixels after
   expansion.

For *%(D_ADJACENT)s* and *%(D_EXPAND)s*, the
*%(M_PERCENT_TOUCHING)s* measurement is the percentage of pixels on
the boundary of an object that touch adjacent objects. For
*%(D_WITHIN)s*, two objects are touching if any of their boundary
pixels are adjacent after expansion and *%(M_PERCENT_TOUCHING)s*
measures the percentage of boundary pixels of an *expanded* object that
touch adjacent objects.
""" % globals(),
        )

        self.distance = cps.Integer(
            "Neighbor distance",
            5,
            1,
            doc="""\
*(Used only when “%(D_WITHIN)s” is selected)*

The Neighbor distance is the number of pixels that each object is
expanded for the neighbor calculation. Expanded objects that touch are
considered neighbors.
""" % globals(),
        )

        self.wants_count_image = cps.Binary(
            "Retain the image of objects colored by numbers of neighbors?",
            False,
            doc="""\
An output image showing the input objects colored by numbers of
neighbors may be retained. A colormap of your choice shows how many
neighbors each object has. The background is set to -1. Objects are
colored with an increasing color value corresponding to the number of
neighbors, such that objects with no neighbors are given a color
corresponding to 0. Use the **SaveImages** module to save this image to
a file.""",
        )

        self.count_image_name = cps.ImageNameProvider(
            "Name the output image",
            "ObjectNeighborCount",
            doc="""\
*(Used only if the image of objects colored by numbers of neighbors is
to be retained for later use in the pipeline)*

Specify a name that will allow the image of objects colored by numbers
of neighbors to be selected later in the pipeline.""",
        )

        self.count_colormap = cps.Colormap(
            "Select colormap",
            doc="""\
*(Used only if the image of objects colored by numbers of neighbors is
to be retained for later use in the pipeline)*

Select the colormap to use to color the neighbor number image. All
available colormaps can be seen `here`_.

.. _here: http://matplotlib.org/examples/color/colormaps_reference.html""",
        )

        self.wants_percent_touching_image = cps.Binary(
            "Retain the image of objects colored by percent of touching pixels?",
            False,
            doc="""\
Select *Yes* to keep an image of the input objects colored by the
percentage of the boundary touching their neighbors. A colormap of your
choice is used to show the touching percentage of each object. Use the
**SaveImages** module to save this image to a file.
""" % globals(),
        )

        self.touching_image_name = cps.ImageNameProvider(
            "Name the output image",
            "PercentTouching",
            doc="""\
*(Used only if the image of objects colored by percent touching is to be
retained for later use in the pipeline)*

Specify a name that will allow the image of objects colored by percent
of touching pixels to be selected later in the pipeline.""",
        )

        self.touching_colormap = cps.Colormap(
            "Select colormap",
            doc="""\
*(Used only if the image of objects colored by percent touching is to be
retained for later use in the pipeline)*

Select the colormap to use to color the percent touching image. All
available colormaps can be seen `here`_.

.. _here: http://matplotlib.org/examples/color/colormaps_reference.html""",
        )
Esempio n. 20
0
    def create_settings(self):
        """Create the settings that control this module"""
        self.object_name = cps.ObjectNameSubscriber(
            "Select objects to be masked",
            cps.NONE,
            doc="""\
Select the objects that will be masked (that is, excluded in whole or in
part based on the other settings in the module). You can choose from any
objects created by a previous object processing module, such as
**IdentifyPrimaryObjects**, **IdentifySecondaryObjects** or
**IdentifyTertiaryObjects**.
""",
        )

        self.remaining_objects = cps.ObjectNameProvider(
            "Name the masked objects",
            "MaskedNuclei",
            doc="""\
Enter a name for the objects that remain after
the masking operation. You can refer to the masked objects in
subsequent modules by this name.
""",
        )

        self.mask_choice = cps.Choice(
            "Mask using a region defined by other objects or by binary image?",
            [MC_OBJECTS, MC_IMAGE],
            doc="""\
You can mask your objects by defining a region using objects you
previously identified in your pipeline (*%(MC_OBJECTS)s*) or by
defining a region based on the white regions in a binary image
previously loaded or created in your pipeline (*%(MC_IMAGE)s*).
""" % globals(),
        )

        self.masking_objects = cps.ObjectNameSubscriber(
            "Select the masking object",
            cps.NONE,
            doc="""\
*(Used only if mask is to be made from objects)*

Select the objects that will be used to define the masking region. You
can choose from any objects created by a previous object processing
module, such as **IdentifyPrimaryObjects**,
**IdentifySecondaryObjects**, or **IdentifyTertiaryObjects**.
""",
        )

        self.masking_image = cps.ImageNameSubscriber(
            "Select the masking image",
            cps.NONE,
            doc="""\
*(Used only if mask is to be made from an image)*

Select an image that was either loaded or created by a previous module.
The image should be a binary image where the white portion of the image
is the region(s) you will use for masking. Binary images can be loaded
from disk using the **NamesAndTypes** module by selecting “Binary mask”
for the image type. You can also create a binary image from a grayscale
image using **ApplyThreshold**.
""",
        )

        self.wants_inverted_mask = cps.Binary(
            "Invert the mask?",
            False,
            doc="""\
This option reverses the foreground/background relationship of the mask.

-  Select "*No*" for the mask to be composed of the foreground (white
   portion) of the masking image or the area within the masking objects.
-  Select "*Yes*" for the mask to instead be composed of the
   *background* (black portions) of the masking image or the area
   *outside* the masking objects.
   """ % globals(),
        )

        self.overlap_choice = cps.Choice(
            "Handling of objects that are partially masked",
            [P_MASK, P_KEEP, P_REMOVE, P_REMOVE_PERCENTAGE],
            doc="""\
An object might partially overlap the mask region, with pixels both
inside and outside the region. **MaskObjects** can handle this in one
of three ways:

-  *%(P_MASK)s:* Choosing this option will reduce the size of partially
   overlapping objects. The part of the object that overlaps the masking
   region will be retained. The part of the object that is outside of the
   masking region will be removed.
-  *%(P_KEEP)s:* If you choose this option, **MaskObjects** will keep
   the whole object if any part of it overlaps the masking region.
-  *%(P_REMOVE)s:* Objects that are partially outside of the masking
   region will be completely removed if you choose this option.
-  *%(P_REMOVE_PERCENTAGE)s:* Determine whether to remove or keep an
   object depending on how much of the object overlaps the masking
   region. **MaskObjects** will keep an object if at least a certain
   fraction (which you enter below) of the object falls within the
   masking region. **MaskObjects** completely removes the object if too
   little of it overlaps the masking region.""" % globals(),
        )

        self.overlap_fraction = cps.Float(
            "Fraction of object that must overlap",
            0.5,
            minval=0,
            maxval=1,
            doc="""\
*(Used only if removing based on overlap)*

Specify the minimum fraction of an object that must overlap the masking
region for that object to be retained. For instance, if the fraction is
0.75, then 3/4 of an object must be within the masking region for that
object to be retained.
""",
        )

        self.retain_or_renumber = cps.Choice(
            "Numbering of resulting objects",
            [R_RENUMBER, R_RETAIN],
            doc="""\
Choose how to number the objects that remain after masking, which
controls how remaining objects are associated with their predecessors:

-  *%(R_RENUMBER)s:* The objects that remain will be renumbered using
   consecutive numbers. This is a good choice if you do not plan to use
   measurements from the original objects; your object measurements for
   the masked objects will not have gaps (where removed objects are
   missing).
-  *%(R_RETAIN)s:* The original labels for the objects will be
   retained. This allows any measurements you make from the masked
   objects to be directly aligned with measurements you might have made
   of the original, unmasked objects (or objects directly associated
   with them).
""" % globals(),
        )
Esempio n. 21
0
    def create_settings(self):
        # Input settings
        self.input_color_choice = cps.Choice("Input image type",
                                             CC_ALL,
                                             doc="""\
Specify whether you are combining several grayscale images or loading a single color image."""
                                             )

        self.wants_red_input = cps.Binary("Use a red image?",
                                          True,
                                          doc="""\
Select *%(YES)s* to specify an image to use for the red channel.""" %
                                          globals())

        self.red_input_image = cps.ImageNameSubscriber("Select the red image",
                                                       cps.NONE)

        self.wants_green_input = cps.Binary("Use a green image?",
                                            True,
                                            doc="""\
Select *%(YES)s* to specify an image to use for the green channel.""" %
                                            globals())

        self.green_input_image = cps.ImageNameSubscriber(
            "Select the green image", cps.NONE)

        self.wants_blue_input = cps.Binary("Use a blue image?",
                                           True,
                                           doc="""\
Select *%(YES)s* to specify an image to use for the blue channel.""" %
                                           globals())

        self.blue_input_image = cps.ImageNameSubscriber(
            "Select the blue image", cps.NONE)

        self.color_input_image = cps.ImageNameSubscriber(
            "Select the color image",
            cps.NONE,
            doc="""\
Select the color image to use.""")

        # Output settings
        self.output_color_choice = cps.Choice("Output image type",
                                              CC_ALL,
                                              doc="""\
Specify whether you want to produce several grayscale images or one color image."""
                                              )

        self.wants_red_output = cps.Binary(
            "Select *%(YES)s* to produce a red image." % globals(), True)

        self.red_output_image = cps.ImageNameProvider("Name the red image",
                                                      "InvertedRed")

        self.wants_green_output = cps.Binary(
            "Select *%(YES)s* to produce a green image." % globals(), True)

        self.green_output_image = cps.ImageNameProvider(
            "Name the green image", "InvertedGreen")

        self.wants_blue_output = cps.Binary(
            "Select *%(YES)s* to produce a blue image." % globals(), True)

        self.blue_output_image = cps.ImageNameProvider("Name the blue image",
                                                       "InvertedBlue")

        self.color_output_image = cps.ImageNameProvider(
            "Name the inverted color image",
            "InvertedColor",
            doc="""\
*(Used only when producing a color output image)*

Enter a name for the inverted color image.""")
Esempio n. 22
0
    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. **IdentifyDeadWorms**
will use this image to establish the foreground and background for the
fitting operation. You can use **ApplyThreshold** to threshold a
grayscale image and create the binary mask. You can also use a module
such as **IdentifyPrimaryObjects** to label each worm and then use
**ConvertObjectsToImage** 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
**IdentifySecondaryObjects**""")

        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 **IdentifyDeadWorms**
automatically calculates the parameters used to determine whether two
found-worm centers belong to the same worm.

Select "*%(YES)s*" to have **IdentifyDeadWorms** automatically calculate
the distance from the worm length and width. Select "*%(NO)s*" to set the
distances manually.
""" % globals())

        self.space_distance = cps.Float("Spatial distance",
                                        5,
                                        minval=1,
                                        doc="""\
*(Used only if not automatically calculating distance parameters)*

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="""\
*(Used only if automatically calculating distance parameters)*

**IdentifyDeadWorms** 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.
""")
Esempio n. 23
0
    def create_settings(self):
        """Create the settings for the module

        Create the settings for the module during initialization.
        """
        self.contrast_choice = cps.Choice(
                "Make each classification decision on how many measurements?",
                [BY_SINGLE_MEASUREMENT, BY_TWO_MEASUREMENTS], doc="""\
This setting controls how many measurements are used to make a
classifications decision for each object:

-  *%(BY_SINGLE_MEASUREMENT)s:* Classifies each object based on a
   single measurement.
-  *%(BY_TWO_MEASUREMENTS)s:* Classifies each object based on a pair
   of measurements taken together (that is, an object must meet two
   criteria to belong to a class).
""" % globals())

        ############### Single measurement settings ##################
        #
        # A list holding groupings for each of the single measurements
        # to be done
        #
        self.single_measurements = []
        #
        # A count of # of measurements
        #
        self.single_measurement_count = cps.HiddenCount(self.single_measurements)
        #
        # Add one single measurement to start off
        #
        self.add_single_measurement(False)
        #
        # A button to press to get another measurement
        #
        self.add_measurement_button = cps.DoSomething(
                "", "Add another classification", self.add_single_measurement)
        #
        ############### Two-measurement settings #####################
        #
        # The object for the contrasting method
        #
        self.object_name = cps.ObjectNameSubscriber(
                "Select the object name", cps.NONE, doc="""\
Choose the object that you want to measure from the list. This should be
an object created by a previous module such as
**IdentifyPrimaryObjects**, **IdentifySecondaryObjects**, **IdentifyTertiaryObjects**, or **Watershed**
""")

        #
        # The two measurements for the contrasting method
        #
        def object_fn():
            return self.object_name.value

        self.first_measurement = cps.Measurement(
                "Select the first measurement", object_fn, doc="""\
*(Used only if using a pair of measurements)*

Choose a measurement made on the above object. This is the first of two
measurements that will be contrasted together. The measurement should be
one made on the object in a prior module.
""")

        self.first_threshold_method = cps.Choice(
                "Method to select the cutoff",
                [TM_MEAN, TM_MEDIAN, TM_CUSTOM], doc="""\
*(Used only if using a pair of measurements)*

Objects are classified as being above or below a cutoff value for a
measurement. You can set this cutoff threshold in one of three ways:

-  *%(TM_MEAN)s*: At the mean of the measurement’s value for all
   objects in the image cycle.
-  *%(TM_MEDIAN)s*: At the median of the measurement’s value for all
   objects in the image set.
-  *%(TM_CUSTOM)s*: You specify a custom threshold value.
""" % globals())

        self.first_threshold = cps.Float(
                "Enter the cutoff value", 0.5, doc="""\
*(Used only if using a pair of measurements)*

This is the cutoff value separating objects in the two classes.""")

        self.second_measurement = cps.Measurement(
                "Select the second measurement", object_fn, doc="""\
*(Used only if using a pair of measurements)*

Select a measurement made on the above object. This is
the second of two measurements that will be contrasted together.
The measurement should be one made on the object in a prior
module.""")

        self.second_threshold_method = cps.Choice(
                "Method to select the cutoff",
                [TM_MEAN, TM_MEDIAN, TM_CUSTOM], doc="""\
*(Used only if using a pair of measurements)*

Objects are classified as being above or below a cutoff value for a
measurement. You can set this cutoff threshold in one of three ways:

-  *%(TM_MEAN)s:* At the mean of the measurement’s value for all
   objects in the image cycle.
-  *%(TM_MEDIAN)s:* At the median of the measurement’s value for all
   objects in the image set.
-  *%(TM_CUSTOM)s:* You specify a custom threshold value.
""" % globals())

        self.second_threshold = cps.Float(
                "Enter the cutoff value", 0.5, doc="""\
*(Used only if using a pair of measurements)*

This is the cutoff value separating objects in the two classes.""")

        self.wants_custom_names = cps.Binary(
                "Use custom names for the bins?", False, doc="""\
*(Used only if using a pair of measurements)*

Select "*%(YES)s*" if you want to specify the names of each bin
measurement.

Select "*%(NO)s*" to create names based on the measurements. For instance,
for “Intensity_MeanIntensity_Green” and
“Intensity_TotalIntensity_Blue”, the module generates measurements
such as
“Classify_Intensity_MeanIntensity_Green_High_Intensity_TotalIntensity_Low”.
""" % globals())

        self.low_low_custom_name = cps.AlphanumericText(
                "Enter the low-low bin name", "low_low", doc="""\
*(Used only if using a pair of measurements)*

Name of the measurement for objects that fall below the threshold for
both measurements.
""")

        self.low_high_custom_name = cps.AlphanumericText(
                "Enter the low-high bin name", "low_high", doc="""\
*(Used only if using a pair of measurements)*

Name of the measurement for objects whose
first measurement is below threshold and whose second measurement
is above threshold.
""")

        self.high_low_custom_name = cps.AlphanumericText(
                "Enter the high-low bin name", "high_low", doc="""\
*(Used only if using a pair of measurements)*

Name of the measurement for objects whose
first measurement is above threshold and whose second measurement
is below threshold.""")

        self.high_high_custom_name = cps.AlphanumericText(
                "Enter the high-high bin name", "high_high", doc="""\
*(Used only if using a pair of measurements)*

Name of the measurement for objects that
are above the threshold for both measurements.""")

        self.wants_image = cps.Binary(
                "Retain an image of the classified objects?", False, doc="""\
Select "*%(YES)s*" to retain the image of the objects color-coded
according to their classification, for use later in the pipeline (for
example, to be saved by a **SaveImages** module).
""" % globals())

        self.image_name = cps.ImageNameProvider(
                "Enter the image name", cps.NONE, doc="""\
*(Used only if the classified object image is to be retained for later use in the pipeline)*

Enter the name to be given to the classified object image.""")
    def create_settings(self):
        self.primary_objects = cps.ObjectNameSubscriber(
            "Select the input objects",
            "Nuclei",
            doc="""
            What did you call the objects you want to use as "seeds" to identify a secondary
            object around each one? By definition, each primary object must be associated with exactly one
            secondary object and completely contained within it.""")

        self.objects_name = cps.ObjectNameProvider(
            "Name the objects to be identified",
            "Cells",
            doc="""
            Enter the name that you want to call the objects identified by this module."""
        )

        self.method = cps.Choice(
            "Select the method to identify the secondary objects", [
                M_PROPAGATION, M_WATERSHED_G, M_WATERSHED_I, M_DISTANCE_N,
                M_DISTANCE_B
            ],
            M_PROPAGATION,
            doc="""
            <p>There are several methods available to find the dividing lines
            between secondary objects which touch each other:
            <ul>
            <li><i>%(M_PROPAGATION)s:</i> This method will find dividing lines
            between clumped objects where the image stained for secondary objects
            shows a change in staining (i.e., either a dimmer or a brighter line).
            Smoother lines work better, but unlike the Watershed method, small gaps
            are tolerated. This method is considered an improvement on the
            traditional <i>Watershed</i> method. The dividing lines between objects are
            determined by a combination of the distance to the nearest primary object
            and intensity gradients. This algorithm uses local image similarity to
            guide the location of boundaries between cells. Boundaries are
            preferentially placed where the image's local appearance changes
            perpendicularly to the boundary (<i>Jones et al, 2005</i>).</li>

            <li><i>%(M_WATERSHED_G)s:</i> This method uses the watershed algorithm
            (<i>Vincent and Soille, 1991</i>) to assign
            pixels to the primary objects which act as seeds for the watershed.
            In this variant, the watershed algorithm operates on the Sobel
            transformed image which computes an intensity gradient. This method
            works best when the image intensity drops off or increases rapidly
            near the boundary between cells.
            </li>
            <li><i>%(M_WATERSHED_I)s:</i> This method is similar to the above,
            but it uses the inverted intensity of the image for the watershed.
            The areas of lowest intensity will form the boundaries between
            cells. This method works best when there is a saddle of relatively
            low intensity at the cell-cell boundary.
            </li>
            <li><i>Distance:</i> In this method, the edges of the primary
            objects are expanded a specified distance to create the secondary
            objects. For example, if nuclei are labeled but there is no stain to help
            locate cell edges, the nuclei can simply be expanded in order to estimate
            the cell's location. This is often called the "doughnut" or "annulus" or
            "ring" approach for identifying the cytoplasm.
            There are two methods that can be used:
            <ul>
            <li><i>%(M_DISTANCE_N)s</i>: In this method, the image of the secondary
            staining is not used at all; the expanded objects are the
            final secondary objects.</li>
            <li><i>%(M_DISTANCE_B)s</i>: Thresholding of the secondary staining image is used to eliminate background
            regions from the secondary objects. This allows the extent of the
            secondary objects to be limited to a certain distance away from the edge
            of the primary objects without including regions of background.</li></ul></li>
            </ul>
            <b>References</b>
            <ul>
            <li>Jones TR, Carpenter AE, Golland P (2005) "Voronoi-Based Segmentation of Cells on Image Manifolds",
            <i>ICCV Workshop on Computer Vision for Biomedical Image Applications</i>, 535-543.
            (<a href="http://www.cellprofiler.org/linked_files/Papers/JonesCVBIA2005.pdf">link</a>)</li>
            <li>(Vincent L, Soille P (1991) "Watersheds in Digital Spaces: An Efficient Algorithm Based on Immersion
            Simulations", <i>IEEE Transactions of Pattern Analysis and Machine
            Intelligence</i>, 13(6): 583-598
            (<a href="http://dx.doi.org/10.1109/34.87344">link</a>)</li>
            </ul>""" % globals())

        self.image_name = cps.ImageNameSubscriber("Select the input image",
                                                  cps.NONE,
                                                  doc="""
            The selected image will be used to find the edges of the secondary objects.
            For <i>%(M_DISTANCE_N)s</i> this will not affect object identification,
            only the final display.""" % globals())

        self.create_threshold_settings()
        # default smoothing choice is different for idprimary and idsecondary
        self.threshold_smoothing_choice.value = cpmi.TSM_NONE

        self.distance_to_dilate = cps.Integer(
            "Number of pixels by which to expand the primary objects",
            10,
            minval=1)

        self.regularization_factor = cps.Float("Regularization factor",
                                               0.05,
                                               minval=0,
                                               doc="""
            <i>(Used only if %(M_PROPAGATION)s method is selected)</i> <br>
            The regularization factor &lambda; can be anywhere in the range 0 to infinity.
            This method takes two factors into account when deciding where to draw
            the dividing line between two touching secondary objects: the distance to
            the nearest primary object, and the intensity of the secondary object
            image. The regularization factor controls the balance between these two
            considerations:
            <ul>
            <li>A &lambda; value of 0 means that the distance to the nearest
            primary object is ignored and the decision is made entirely on the
            intensity gradient between the two competing primary objects. </li>
            <li>Larger values of &lambda; put more and more weight on the distance between the two objects.
            This relationship is such that small changes in &lambda; will have fairly different
            results (e.,g 0.01 vs 0.001). However, the intensity image is almost completely
            ignored at &lambda; much greater than 1.</li>
            <li>At infinity, the result will look like %(M_DISTANCE_B)s, masked to the
            secondary staining image.</li>
            </ul>""" % globals())

        self.use_outlines = cps.Binary(
            "Retain outlines of the identified secondary objects?",
            False,
            doc="""
            %(RETAINING_OUTLINES_HELP)s""" % globals())

        self.outlines_name = cps.OutlineNameProvider('Name the outline image',
                                                     "SecondaryOutlines",
                                                     doc="""
            %(NAMING_OUTLINES_HELP)s""" % globals())

        self.wants_discard_edge = cps.Binary(
            "Discard secondary objects touching the border of the image?",
            False,
            doc="""
            Select <i>%(YES)s</i> to discard secondary objects which touch
            the image border. Select <i>%(NO)s</i> to retain objects regardless
            of whether they touch the image edge or not.
            <p>The objects are discarded
            with respect to downstream measurement modules, but they are retained in memory
            as "unedited objects"; this allows them to be considered in downstream modules that modify the
            segmentation.</p>""" % globals())

        self.fill_holes = cps.Binary("Fill holes in identified objects?",
                                     True,
                                     doc="""
            Select <i>%(YES)s</i> to fill any holes inside objects.""" %
                                     globals())

        self.wants_discard_primary = cps.Binary(
            "Discard the associated primary objects?",
            False,
            doc="""
            <i>(Used only if discarding secondary objects touching the image border)</i> <br>
            It might be appropriate to discard the primary object
            for any secondary object that touches the edge of the image.
            <p>Select <i>%(YES)s</i> to create a new set of objects that are identical
            to the original primary objects set, minus the objects for which the associated
            secondary object touches the image edge.</p>""" % globals())

        self.new_primary_objects_name = cps.ObjectNameProvider(
            "Name the new primary objects",
            "FilteredNuclei",
            doc="""
            <i>(Used only if associated primary objects are discarded)</i> <br>
            You can name the primary objects that remain after the discarding step.
            These objects will all have secondary objects
            that do not touch the edge of the image. Note that any primary object
            whose secondary object touches the edge will be retained in memory as an
            "unedited object"; this allows them to be considered in downstream modules that modify the
            segmentation.""")

        self.wants_primary_outlines = cps.Binary(
            "Retain outlines of the new primary objects?",
            False,
            doc="""
            <i>(Used only if associated primary objects are discarded)</i><br>
            %(RETAINING_OUTLINES_HELP)s""" % globals())

        self.new_primary_outlines_name = cps.OutlineNameProvider(
            "Name the new primary object outlines",
            "FilteredNucleiOutlines",
            doc="""
            <i>(Used only if associated primary objects are discarded and saving outlines of new primary objects)</i><br>
            Enter a name for the outlines of the identified
            objects. The outlined image can be selected in downstream modules by selecting
            them from any drop-down image list.""")
    def add_dose_value(self, can_remove=True):
        '''Add a dose value measurement to the list

        can_delete - set this to False to keep from showing the "remove"
                     button for images that must be present.'''
        group = cps.SettingsGroup()
        group.append(
            "measurement",
            cps.Measurement(
                "Select the image measurement describing the treatment dose",
                lambda: cpmeas.IMAGE,
                doc="""\
The V and Z’ factors, metrics of assay quality, and the EC50,
indicating dose-response, are calculated by this module based on each
image being specified as a particular treatment dose. Choose a
measurement that gives the dose of some treatment for each of your
images. See the help for the previous setting for details."""))

        group.append(
            "log_transform",
            cps.Binary("Log-transform the dose values?",
                       False,
                       doc='''\
Select *%(YES)s* if you have dose-response data and you want to
log-transform the dose values before fitting a sigmoid curve.

Select *%(NO)s* if your data values indicate only positive vs. negative
controls.
''' % globals()))

        group.append(
            'wants_save_figure',
            cps.Binary(
                '''Create dose-response plots?''',
                False,
                doc=
                '''Select *%(YES)s* if you want to create and save dose-response plots.
You will be asked for information on how to save the plots.''' % globals()))

        group.append(
            'figure_name',
            cps.Text("Figure prefix",
                     "",
                     doc='''\
*(Used only when creating dose-response plots)*

CellProfiler will create a file name by appending the measurement name
to the prefix you enter here. For instance, if you specify a prefix
of “Dose\_”, when saving a file related to objects you have chosen (for
example, *Cells*) and a particular measurement (for example, *AreaShape_Area*),
CellProfiler will save the figure as *Dose_Cells_AreaShape_Area.m*.
Leave this setting blank if you do not want a prefix.
'''))
        group.append(
            'pathname',
            cps.DirectoryPath("Output file location",
                              dir_choices=[
                                  cps.DEFAULT_OUTPUT_FOLDER_NAME,
                                  cps.DEFAULT_INPUT_FOLDER_NAME,
                                  cps.ABSOLUTE_FOLDER_NAME,
                                  cps.DEFAULT_OUTPUT_SUBFOLDER_NAME,
                                  cps.DEFAULT_INPUT_SUBFOLDER_NAME
                              ],
                              doc="""\
*(Used only when creating dose-response plots)*

This setting lets you choose the folder for the output files. %(IO_FOLDER_CHOICE_HELP_TEXT)s

%(IO_WITH_METADATA_HELP_TEXT)s
""" % globals()))

        group.append("divider", cps.Divider())

        group.append(
            "remover",
            cps.RemoveSettingButton("", "Remove this dose measurement",
                                    self.dose_values, group))
        self.dose_values.append(group)
Esempio n. 26
0
    def add_flag(self, can_delete=True):
        group = cps.SettingsGroup()
        group.append("divider1", cps.Divider(line=False))
        group.append("measurement_settings", [])
        group.append("measurement_count",
                     cps.HiddenCount(group.measurement_settings))
        group.append(
            "category",
            cps.Text("Name the flag's category",
                     "Metadata",
                     doc='''
                        Name a measurement category by which to categorize the flag. The <i>Metadata</i>
                        category is the default used in CellProfiler to store information about
                        images (referred to as <i>metadata</i>).</p>
                        <p>The flag is stored as a per-image measurement whose name is a combination of the
                        flag's category and feature name, underscore delimited.
                        For instance, if the measurement category is
                        <i>Metadata</i> and the feature name is <i>QCFlag</i>, then the default
                        measurement name would be <i>Metadata_QCFlag</i>. %s</p>'''
                     % USING_METADATA_HELP_REF))

        group.append(
            "feature_name",
            cps.Text("Name the flag",
                     "QCFlag",
                     doc='''
                        The flag is stored as a per-image measurement whose name is a combination of the
                        flag's category and feature name, separated by underscores.
                        For instance, if the measurement category is
                        <i>Metadata</i> and the feature name is <i>QCFlag</i>, then the default
                        measurement name would be <i>Metadata_QCFlag</i>.'''))

        group.append(
            "combination_choice",
            cps.Choice("How should measurements be linked?", [C_ANY, C_ALL],
                       doc='''
                        For combinations of measurements, you can set the criteria under which an image set is flagged:
                        <ul>
                        <li><i>%(C_ANY)s:</i> An image set will be flagged if any of its measurements fail. This can be useful
                        for flagging images possessing multiple QC flaws; for example, you can flag all bright images
                        and all out of focus images with one flag.</li>
                        <li><i>%(C_ALL)s:</i> A flag will only be assigned if all measurements fail.  This can be useful
                        for flagging images that possess only a combination
                        of QC flaws; for example, you can flag only images that are both bright and out of focus.</li>
                        </ul>''' % globals()))

        group.append(
            "wants_skip",
            cps.Binary("Skip image set if flagged?",
                       False,
                       doc="""
                        <p>Select <i>%(YES)s</i> to skip the remainder of the pipeline for image sets
                        that are flagged. CellProfiler will not run subsequent modules in the
                        pipeline on the images in any image set that is flagged.
                        Select <i>%(NO)s</i> for CellProfiler to continue to process the pipeline regardless
                        of flagging.</p>
                        <p>You may want to skip processing in order to filter out
                        unwanted images. For instance, you may want
                        to exclude out of focus images when running
                        <b>CorrectIllumination_Calculate</b>. You can do this with a
                        pipeline that measures image quality and flags inappropriate
                        images before it runs <b>CorrectIllumination_Calculate</b>.</p>"""
                       % globals()))

        group.append(
            "add_measurement_button",
            cps.DoSomething("", "Add another measurement",
                            self.add_measurement, group))
        self.add_measurement(group, False if not can_delete else True)
        if can_delete:
            group.append(
                "remover",
                cps.RemoveSettingButton("", "Remove this flag", self.flags,
                                        group))
        group.append("divider2", cps.Divider(line=True))
        self.flags.append(group)
Esempio n. 27
0
    def add_flag(self, can_delete=True):
        group = cps.SettingsGroup()
        group.append("divider1", cps.Divider(line=False))
        group.append("measurement_settings", [])
        group.append("measurement_count",
                     cps.HiddenCount(group.measurement_settings))
        group.append(
            "category",
            cps.Text(
                "Name the flag's category",
                "Metadata",
                doc="""\
Name a measurement category by which to categorize the flag. The
*Metadata* category is the default used in CellProfiler to store
information about images (referred to as *metadata*).

The flag is stored as a per-image measurement whose name is a
combination of the flag’s category and the flag name that you choose, separated by
underscores. For instance, if the measurement category is *Metadata* and
the flag name is *QCFlag*, then the default measurement name would be
*Metadata_QCFlag*.
""",
            ),
        )

        group.append(
            "feature_name",
            cps.Text(
                "Name the flag",
                "QCFlag",
                doc="""\
The flag is stored as a per-image measurement whose name is a
combination of the flag’s category and the flag name that you choose, separated by
underscores. For instance, if the measurement category is *Metadata* and
the flag name is *QCFlag*, then the default measurement name would be
*Metadata_QCFlag*.
""",
            ),
        )

        group.append(
            "combination_choice",
            cps.Choice(
                "How should measurements be linked?",
                [C_ANY, C_ALL],
                doc="""\
For combinations of measurements, you can set the criteria under which
an image set is flagged:

-  *%(C_ANY)s:* An image set will be flagged if any of its measurements
   fail. This can be useful for flagging images possessing multiple QC
   flaws; for example, you can flag all bright images and all out of
   focus images with one flag.
-  *%(C_ALL)s:* A flag will only be assigned if all measurements fail.
   This can be useful for flagging images that possess only a
   combination of QC flaws; for example, you can flag only images that
   are both bright and out of focus.
""" % globals(),
            ),
        )

        group.append(
            "wants_skip",
            cps.Binary(
                "Skip image set if flagged?",
                False,
                doc="""\
Select *Yes* to skip the remainder of the pipeline for image sets
that are flagged. CellProfiler will not run subsequent modules in the
pipeline on the images for any image set that is flagged. Select *No*
for CellProfiler to continue to process the pipeline regardless of
flagging.

You may want to skip processing in order to filter out unwanted images.
For instance, you may want to exclude out of focus images when running
**CorrectIllumination_Calculate**. You can do this with a pipeline that
measures image quality and flags inappropriate images before it runs
**CorrectIllumination_Calculate**.
""" % globals(),
            ),
        )

        group.append(
            "add_measurement_button",
            cps.DoSomething(
                "",
                "Add another measurement",
                self.add_measurement,
                group,
                doc="""Add another measurement as a criteria.""",
            ),
        )
        self.add_measurement(group, False if not can_delete else True)
        if can_delete:
            group.append(
                "remover",
                cps.RemoveSettingButton("", "Remove this flag", self.flags,
                                        group),
            )
        group.append("divider2", cps.Divider(line=True))
        self.flags.append(group)
Esempio n. 28
0
    def create_settings(self):
        self.pipeline = None
        self.metadata_keys = {}

        module_explanation = [
            "The %s module optionally allows you to split your list of images into image subsets"
            % self.module_name,
            "(groups) which will be processed independently of each other. Examples of",
            "groupings include screening batches, microtiter plates, time-lapse movies, etc.",
        ]
        self.set_notes([" ".join(module_explanation)])

        self.wants_groups = cps.Binary(
            "Do you want to group your images?",
            False,
            doc="""\
Select "*{YES}*" if you need to split your images into image subsets (or
*groups*) such that each group is processed independently of each other.
See the main module help for more details.
""".format(**{"YES": YES}),
        )

        self.grouping_text = cps.HTMLText(
            "",
            content=
            "Each unique metadata value (or combination of values) will be defined as a group",
            size=(30, 2),
        )

        self.grouping_metadata = []

        self.grouping_metadata_count = cps.HiddenCount(
            self.grouping_metadata, "grouping metadata count")

        self.add_grouping_metadata(can_remove=False)

        self.add_grouping_metadata_button = cps.DoSomething(
            "", "Add another metadata item", self.add_grouping_metadata)

        self.grouping_list = cps.Table(
            "Grouping list",
            min_size=(300, 100),
            doc="""\
This list shows the unique values of the selected metadata under the
“Group” column; each of the unique values comprises a group. The “Count”
column shows the number of image sets that included in a given group;
this is useful as a “sanity check”, to make sure that the expected
number of images are present. For example, if you are grouping by
per-plate metadata from a 384-well assay with 2 sites per well
consisting of 3 plates, you would expect to see 3 groups (each from the
3 unique plate IDs), with 384 wells × 2 sites/well = 768 image sets in
each.
""",
        )

        self.image_set_list = cps.Table(
            "Image sets",
            doc="""\
This list displays the file name and location of each of the image sets
that comprise the group. For example, if you are grouping by per-plate
metadata from a 384-well assay with 2 sites per well consisting of 3
plates, you would expect to see a table consisting of 3 plates × 384
wells/plate ×2 sites/well = 2304 rows.
""",
        )
Esempio n. 29
0
    def create_settings(self):
        self.image_name = cps.ImageNameSubscriber(
            "Select the input image",
            cps.NONE,
            doc='''Select the image whose edges you want to enhance.''')

        self.output_image_name = cps.ImageNameProvider(
            "Name the output image",
            "EdgedImage",
            doc='''Enter a name for the resulting image with edges enhanced.'''
        )

        self.method = cps.Choice(
            "Select an edge-finding method",
            [M_SOBEL, M_PREWITT, M_ROBERTS, M_LOG, M_CANNY, M_KIRSCH],
            doc='''\
There are several methods that can be used to enhance edges. Often, it
is best to test them against each other empirically:

-  *%(M_SOBEL)s:* Finds edges using the %(M_SOBEL)s approximation to
   the derivative. The %(M_SOBEL)s method derives a horizontal and
   vertical gradient measure and returns the square-root of the sum of
   the two squared signals.
-  *%(M_PREWITT)s:* Finds edges using the %(M_PREWITT)s approximation
   to the derivative. It returns edges at those points where the
   gradient of the image is maximum.
-  *%(M_ROBERTS)s:* Finds edges using the Roberts approximation to the
   derivative. The %(M_ROBERTS)s method looks for gradients in the
   diagonal and anti-diagonal directions and returns the square-root of
   the sum of the two squared signals. This method is fast, but it
   creates diagonal artifacts that may need to be removed by smoothing.
-  *%(M_LOG)s:* Applies a Laplacian of Gaussian filter to the image and
   finds zero crossings.
-  *%(M_CANNY)s:* Finds edges by looking for local maxima of the
   gradient of the image. The gradient is calculated using the
   derivative of a Gaussian filter. The method uses two thresholds to
   detect strong and weak edges, and includes the weak edges in the
   output only if they are connected to strong edges. This method is
   therefore less likely than the others to be fooled by noise, and more
   likely to detect true weak edges.
-  *%(M_KIRSCH)s:* Finds edges by calculating the gradient among the 8
   compass points (North, North-east, etc.) and selecting the maximum as
   the pixel’s value.
''' % globals())

        self.wants_automatic_threshold = cps.Binary(
            "Automatically calculate the threshold?",
            True,
            doc='''\
*(Used only with the "%(M_CANNY)s" option and automatic thresholding)*

Select *%(YES)s* to automatically calculate the threshold using a
three-category Otsu algorithm performed on the Sobel transform of the
image.

Select *%(NO)s* to manually enter the threshold value.
''' % globals())

        self.manual_threshold = cps.Float("Absolute threshold",
                                          0.2,
                                          0,
                                          1,
                                          doc='''\
*(Used only with the "%(M_CANNY)s" option and manual thresholding)*

The upper cutoff for Canny edges. All Sobel-transformed pixels with this
value or higher will be marked as an edge. You can enter a threshold
between 0 and 1.
''' % globals())

        self.threshold_adjustment_factor = cps.Float(
            "Threshold adjustment factor",
            1,
            doc='''\
*(Used only with the "%(M_CANNY)s" option and automatic thresholding)*

This threshold adjustment factor is a multiplier that is applied to both
the lower and upper Canny thresholds if they are calculated
automatically. An adjustment factor of 1 indicates no adjustment. The
adjustment factor has no effect on any threshhold entered manually.
''' % globals())

        self.direction = cps.Choice("Select edge direction to enhance",
                                    [E_ALL, E_HORIZONTAL, E_VERTICAL],
                                    doc='''\
*(Used only with "%(M_PREWITT)s" and "%(M_SOBEL)s" methods)*

Select the direction of the edges you aim to identify in the image
(predominantly horizontal, predominantly vertical, or both).
''' % globals())

        self.wants_automatic_sigma = cps.Binary(
            "Calculate Gaussian's sigma automatically?",
            True,
            doc="""\
Select *%(YES)s* to automatically calculate the Gaussian's sigma.

Select *%(NO)s* to manually enter the value.
""" % globals())

        self.sigma = cps.Float("Gaussian's sigma value",
                               10,
                               doc="""Set a value for Gaussian's sigma.""")

        self.wants_automatic_low_threshold = cps.Binary(
            "Calculate value for low threshold automatically?",
            True,
            doc="""\
*(Used only with the "%(M_CANNY)s" option and automatic thresholding)*

Select *%(YES)s* to automatically calculate the low / soft threshold
cutoff for the %(M_CANNY)s method.

Select *%(NO)s* to manually enter the low threshold value.
""" % globals())

        self.low_threshold = cps.Float("Low threshold value",
                                       0.1,
                                       0,
                                       1,
                                       doc="""\
*(Used only with the "%(M_CANNY)s" option and manual thresholding)*

Enter the soft threshold cutoff for the %(M_CANNY)s method. The
%(M_CANNY)s method will mark all %(M_SOBEL)s-transformed pixels with
values below this threshold as not being edges.
""" % globals())
    def create_settings(self):
        self.mode = cps.Choice("Classify or train?",
                               [MODE_CLASSIFY, MODE_TRAIN])
        self.advanced_or_automatic = cps.Choice(
            "Configuration mode", [AA_AUTOMATIC, AA_ADVANCED],
            doc="""Do you want to automatically choose the training parameters
            or use the defaults?""")
        self.radius = cps.Integer("Radius", DEFAULT_RADIUS, 1)
        self.n_features = cps.Integer(
            "Number of features",
            DEFAULT_N_FEATURES,
            1,
            doc="""The classifier runs a feature reduction set. This creates
            <i>Eigentextures</i> which are representative texture patches
            found throughout the image. The module scores each patch around
            a pixel according to how much it has each of these textures and
            those scores are fed into the final classifier. Raise the number of
            features if some of the textures or edges of your classes are
            misclassified. Lower the number of features to improve processing
            time or to reduce overfitting if you have a smaller amount of
            ground truth.
            """)
        self.n_estimators = cps.Integer(
            "Number of estimators",
            DEFAULT_N_ESTIMATORS,
            1,
            doc="""The classifier uses a voting scheme where it trains this
            many estimators. It purposefully does a bad job training and makes
            up for this deficit by having many poor classification judges.
            This protects against overfitting by not relying on having a single
            classifier that is very good at classifying the ground truth, but
            mistakenly uses irrelevant information to do so. Raise the number
            of estimators if the classifier is making obvious mistakes with
            unwarranted certainty. Lower the number of estimators to improve
            processing speed.""")
        self.min_samples_per_leaf = cps.Integer(
            "Minimum samples per leaf",
            DEFAULT_MIN_SAMPLES_PER_LEAF,
            1,
            doc="""This setting determines the minimum number of ground truth
            pixels that the classifier will use to split a decision tree.
            There must be at least this number of example pixels in each branch
            for the classifier to have confidence that the split is real and
            not just an artifact of an irrelevant measurement.
            
            Lower this setting if the classifier does a good job on most of the
            pixels but does not draw sharp distinctions between one class and
            another at the border between the classes (e.g. at the edges of
            cells). Raise this setting if the classifier misclassifies pixels
            that are clearly not the right class - this is overtraining.
            """)
        self.path = cps.DirectoryPath("Classifier folder")

        def get_directory_fn():
            '''Get the directory for the file name'''
            return self.path.get_absolute_path()

        def set_directory_fn(path):
            dir_choice, custom_path = self.path.get_parts_from_path(path)
            self.path.join_parts(dir_choice, custom_path)

        self.filename = cps.FilenameText(
            "Classifier file",
            "Classifier.cpclassifier",
            get_directory_fn=get_directory_fn,
            set_directory_fn=set_directory_fn,
            exts=[("Pixel classifier (*.cpclassifier)", "*.cpclassifier"),
                  ("All files (*.*)", "*.*")])
        self.gt_source = cps.Choice("Ground truth source",
                                    [SRC_OBJECTS, SRC_ILASTIK],
                                    doc="""
        The ground truth data can either be taken from objects or can be
        the exported TIF "labels" output of Ilastik.
        """)
        self.labels_image = cps.ImageNameSubscriber("Ilastik labels image",
                                                    "labels.tif",
                                                    doc="""
            <i>Used only if the ground truth source is "Ilastik"</i>
            <br>
            This image should be the exported labels image from Ilastik.
            """)
        self.wants_background_class = cps.Binary(
            "Do you want a background class?", True)
        self.background_class_name = cps.Text("Background class name",
                                              "Background")
        self.object_classes = []
        self.object_class_count = cps.HiddenCount(self.object_classes,
                                                  "Object class count")
        self.add_objects(False)
        self.add_objects_button = cps.DoSomething("Add another class", "Add",
                                                  self.add_objects)
        self.label_classes = []
        self.label_class_count = cps.HiddenCount(self.label_classes,
                                                 "Label class count")
        self.add_labels(False)
        self.add_labels_button = cps.DoSomething("Add another class", "Add",
                                                 self.add_labels)

        self.images = []
        self.image_count = cps.HiddenCount(self.images, "Image count")
        self.add_image(False)
        self.add_image_button = cps.DoSomething("Add another image", "Add",
                                                self.add_image)
        self.outputs = []
        self.output_count = cps.HiddenCount(self.outputs, "Output count")
        self.add_output(False)
        self.add_output_button = cps.DoSomething("Add another output", "Add",
                                                 self.add_output)