Exemplo n.º 1
0
    def create_settings(self):
        """Create the settings for the module at startup.
        """
        self.image_groups = []
        self.image_count = cps.HiddenCount(self.image_groups)
        self.add_image_cb(can_remove=False)
        self.add_images = cps.DoSomething("", "Add another image",
                                          self.add_image_cb)
        self.image_divider = cps.Divider()

        self.object_groups = []
        self.object_count = cps.HiddenCount(self.object_groups)
        self.add_object_cb(can_remove=True)
        self.add_objects = cps.DoSomething("", "Add another object",
                                           self.add_object_cb)
        self.object_divider = cps.Divider()

        self.moms = cps.MultiChoice(
            "Moments to compute",
            MOM_ALL,
            MOM_ALL,
            doc=
            """Moments are statistics describing the distribution of values in the set of pixels of interest:
                <p><ul>
                <li><i>%(MOM_1)s</i> - the first image moment, which corresponds to the central value of the collection of pixels of interest.</li>
                <li><i>%(MOM_2)s</i> - the second image moment, which measures the amount of variation or dispersion of pixel values about its mean.</li>
                <li><i>%(MOM_3)s</i> - a scaled version of the third moment, which measures the asymmetry of the pixel values distribution about its mean.</li>
                <li><i>%(MOM_4)s</i> - a scaled version of the fourth moment, which measures the "peakedness" of the pixel values distribution.</li>
                </ul><p>
                Choose one or more moments to measure.""" % globals())
    def create_settings(self):
        """Create the settings for the module at startup.
        
        The module allows for an unlimited number of measured objects, each
        of which has an entry in self.object_groups.
        """
        self.image_groups = []
        self.object_groups = []
        self.scale_groups = []
        self.image_count = cps.HiddenCount(self.image_groups)
        self.object_count = cps.HiddenCount(self.object_groups)
        self.scale_count = cps.HiddenCount(self.scale_groups)
        self.add_image_cb(can_remove=False)
        self.add_images = cps.DoSomething("", "Add another image",
                                          self.add_image_cb)
        self.image_divider = cps.Divider()
        self.add_object_cb(can_remove=True)
        self.add_objects = cps.DoSomething("", "Add another object",
                                           self.add_object_cb)
        self.object_divider = cps.Divider()
        self.add_scale_cb(can_remove=False)
        self.add_scales = cps.DoSomething("", "Add another scale",
                                          self.add_scale_cb)
        self.scale_divider = cps.Divider()

        self.wants_gabor = cps.Binary(
            "Measure Gabor features?",
            True,
            doc="""The Gabor features measure striped texture in an object. They
            take a substantial time to calculate. Check this setting to
            measure the Gabor features. Uncheck this setting to skip
            the Gabor feature calculation if it is not informative for your
            images""")
        self.gabor_angles = cps.Integer(
            "Number of angles to compute for Gabor",
            4,
            2,
            doc="""
        <i>(Used only if Gabor features are measured)</i><br>
        How many angles do you want to use for each Gabor texture measurement?
            The default value is 4 which detects bands in the horizontal, vertical and diagonal
            orientations.""")
        self.gabor_divider = cps.Divider()

        self.wants_tamura = cps.Binary(
            "Measure Tamura features?",
            True,
            doc="""The Tamura features are very ugly.""")
        self.tamura_feats = cps.MultiChoice("Features to compute",
                                            F_ALL,
                                            F_ALL,
                                            doc="""Tamura Features:
                        <p><ul>
                        <li><i>%(F_1)s</i> - bla.</li>
                        <li><i>%(F_2)s</i> - bla.</li>
                        <li><i>%(F_3)s</i> - bla.</li>
                        </ul><p>
                        Choose one or more features to compute.""" % globals())
    def add_scale_cb(self, can_remove=True):
        '''Add a scale to the scale_groups collection
        
        can_delete - set this to False to keep from showing the "remove"
                     button for scales that must be present.
        '''
        group = cps.SettingsGroup()
        if can_remove:
            group.append("divider", cps.Divider(line=False))
        group.append(
            'scale',
            cps.Integer(
                "Texture scale to measure",
                len(self.scale_groups) + 3,
                doc=
                """You can specify the scale of texture to be measured, in pixel units; 
                                 the texture scale is the distance between correlated intensities in the image. A 
                                 higher number for the scale of texture measures larger patterns of 
                                 texture whereas smaller numbers measure more localized patterns of 
                                 texture. It is best to measure texture on a scale smaller than your 
                                 objects' sizes, so be sure that the value entered for scale of texture is 
                                 smaller than most of your objects. For very small objects (smaller than 
                                 the scale of texture you are measuring), the texture cannot be measured 
                                 and will result in a undefined value in the output file."""
            ))
        group.append(
            'angles',
            cps.MultiChoice(
                "Angles to measure",
                H_ALL,
                H_ALL,
                doc=
                """The Haralick texture measurements are based on the correlation
        between pixels offset by the scale in one of four directions:
        <p><ul>
        <li><i>%(H_HORIZONTAL)s</i> - the correlated pixel is "scale" pixels
        to the right of the pixel of interest.</li>
        <li><i>%(H_VERTICAL)s</i> - the correlated pixel is "scale" pixels
        below the pixel of interest.</li>
        <li><i>%(H_DIAGONAL)s</i> - the correlated pixel is "scale" pixels
        to the right and "scale" pixels below the pixel of interest.</li>
        <li><i>%(H_ANTIDIAGONAL)s</i> - the correlated pixel is "scale"
        pixels to the left and "scale" pixels below the pixel of interest.</li>
        </ul><p>
        Choose one or more directions to measure.""" % globals()))

        if can_remove:
            group.append(
                "remover",
                cps.RemoveSettingButton("", "Remove this scale",
                                        self.scale_groups, group))
        self.scale_groups.append(group)
Exemplo n.º 4
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)