Пример #1
0
        def measurement_visibles(m_g):
            if hasattr(m_g, "remover"):
                result = [cps.Divider(line=True)]
            else:
                result = []
            result += [m_g.source_choice]

            if (m_g.source_choice == S_ALL_OBJECTS
                    or m_g.source_choice == S_AVERAGE_OBJECT):
                result += [m_g.object_name]
            if m_g.source_choice == S_RULES or m_g.source_choice == S_CLASSIFIER:
                result += [
                    m_g.rules_directory, m_g.rules_file_name, m_g.rules_class
                ]
                whatami = "Rules" if m_g.source_choice == S_RULES else "Classifier"
                for setting, s in (
                    (m_g.rules_directory, "%s file location"),
                    (m_g.rules_file_name, "%s file name"),
                ):
                    setting.text = s % whatami
            else:
                result += [m_g.measurement, m_g.wants_minimum]
                if m_g.wants_minimum.value:
                    result += [m_g.minimum_value]
                result += [m_g.wants_maximum]
                if m_g.wants_maximum.value:
                    result += [m_g.maximum_value]
            if hasattr(m_g, "remover"):
                result += [m_g.remover, cps.Divider(line=True)]
            return result
    def create_settings(self):
        """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 = 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 = DoSomething("", "Add another object",
                                       self.add_object_cb)
        self.object_divider = cps.Divider()

        self.moms = 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())
Пример #3
0
 def create_settings(self):
     self.divider_top = cps.Divider(line=False)
     self.images = []
     self.image_count = cps.HiddenCount(self.images, "Image count")
     self.add_image(can_remove=False)
     self.add_button = cps.DoSomething("", "Add another image",
                                       self.add_image)
     self.divider_bottom = cps.Divider(line=False)
Пример #4
0
 def create_settings(self):
     """Create the settings & name the module"""
     self.divider_top = cps.Divider(line=False)
     self.images = []
     self.add_image_measurement(can_remove=False)
     self.add_button = cps.DoSomething("", "Add another image",
                                       self.add_image_measurement)
     self.divider_bottom = cps.Divider(line=False)
 def create_settings(self):
     """Create the settings for the module at startup.
     
     The module allows for an unlimited number of measured objects, each
     of which has an entry in self.object_groups.
     """ 
     self.image_groups = []
     self.object_groups = []
     self.scale_groups = []
     self.image_count = cps.HiddenCount(self.image_groups)
     self.object_count = cps.HiddenCount(self.object_groups)
     self.scale_count = cps.HiddenCount(self.scale_groups)
     self.add_image_cb(can_remove = False)
     self.add_images = DoSomething("", "Add another image",
                                       self.add_image_cb)
     self.image_divider = cps.Divider()
     self.add_object_cb(can_remove = True)
     self.add_objects = DoSomething("", "Add another object",
                                        self.add_object_cb)
     self.object_divider = cps.Divider()
     self.add_scale_cb(can_remove = False)
     self.add_scales = 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 = 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=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_object_cb(self, can_remove=True):
     '''Add an object to the object_groups collection
     
     can_delete - set this to False to keep from showing the "remove"
     button for objects that must be present.
     '''
     group = cps.SettingsGroup()
     if can_remove:
         group.append("divider", cps.Divider(line=False))
     group.append(
         'object_name',
         LabelSubscriber("Select objects to measure",
                         "None",
                         doc="""
                  What did you call the objects from which you want to calculate moments? 
                  If you only want to calculat moments of
                  the image overall, you can remove all objects using the "Remove this object" button. 
                  <p>Objects specified here will have moments computed against <i>all</i> images specfied above, which
                  may lead to image-object combinations that are unneccesary. If you
                  do not want this behavior, use multiple <b>CalculateMoments</b>
                  modules to specify the particular image-object measures that you want.</p>"""
                         ))
     if can_remove:
         group.append(
             "remover",
             cps.do_something.RemoveSettingButton("", "Remove this object",
                                                  self.object_groups,
                                                  group))
     self.object_groups.append(group)
Пример #7
0
    def add_bins_cb(self, can_remove=True):
        '''Add an histogram to the bin_groups collection
        
        can_delete - set this to False to keep from showing the "remove"
                     button for histograms that must be present.
        '''
        group = cps.SettingsGroup()
        if can_remove:
            group.append("divider", cps.Divider(line=False))
        group.append(
            'bins',
            Integer(
                "Number of bins",
                len(self.bins_groups) + 3,
                doc=
                """How much bins do you want in your histogram? You can calculate several histograms with different number of bins using the "Add another histogram" button."""
            ))

        if can_remove:
            group.append(
                "remover",
                cps.do_something.RemoveSettingButton("",
                                                     "Remove this histogram",
                                                     self.bins_groups, group))
        self.bins_groups.append(group)
Пример #8
0
    def add_image(self, can_delete=True):
        """Add an image and its settings to the list of images"""
        image_name = cps.subscriber.ImageSubscriber(
            "Select the input image",
            NONE,
            doc="""
            Select the image to be corrected.""",
        )

        corrected_image_name = cps.text.ImageName(
            "Name the output image",
            "SpillCorrected",
            doc="""
            Enter a name for the corrected image.""",
        )

        spill_correct_function_image_name = cps.subscriber.ImageSubscriber(
            "Select the spillover function image",
            NONE,
            doc="""
            Select the spillover correction image that will be used to
            carry out the correction. This image is usually produced by the R
            software CATALYST or loaded as a .tiff format image using the
            <b>Images</b> module or
            <b>LoadSingleImage</b>.""",
        )
        spill_correct_method = cps.choice.Choice(
            "Spillover correction method",
            [METHOD_NNLS, METHOD_LS],
            doc="""
            Select the spillover correction method.
            <ul>
            <li><i>%(METHOD_LS)s:</i> Gives the least square solution
            for overdetermined solutions or the exact solution for exactly 
            constraint problems. </li>
            <li><i>%(METHOD_NNLS)s:</i> Gives the non linear least squares
            solution: The most accurate solution, according to the least
            squares criterium, without any negative values.
            </li>
            </ul>
            """ % globals(),
        )

        image_settings = cps.SettingsGroup()
        image_settings.append("image_name", image_name)
        image_settings.append("corrected_image_name", corrected_image_name)
        image_settings.append("spill_correct_function_image_name",
                              spill_correct_function_image_name)
        image_settings.append("spill_correct_method", spill_correct_method)

        if can_delete:
            image_settings.append(
                "remover",
                cps.do_something.RemoveSettingButton("", "Remove this image",
                                                     self.images,
                                                     image_settings),
            )
        image_settings.append("divider", cps.Divider())
        self.images.append(image_settings)
Пример #9
0
 def flag_visibles(flag):
     if hasattr(flag, "remover"):
         result = [cps.Divider(line=True), cps.Divider(line=True)]
     else:
         result = []
     result += [flag.category, flag.feature_name, flag.wants_skip]
     if len(flag.measurement_settings) > 1:
         result += [flag.combination_choice]
     for measurement_settings in flag.measurement_settings:
         result += measurement_visibles(measurement_settings)
     result += [flag.add_measurement_button]
     if hasattr(flag, "remover"):
         result += [
             flag.remover,
             cps.Divider(line=True),
             cps.Divider(line=True)
         ]
     return result
Пример #10
0
    def add_image_measurement(self, can_remove=True):
        group = cps.SettingsGroup()
        if can_remove:
            group.append("divider", cps.Divider())

        group.append(
            "image_name",
            cps.ImageNameSubscriber(
                "Select the image to measure",
                "None",
                doc="""\
Choose an image name from the drop-down menu to calculate intensity for
that image. Use the *Add another image* button below to add additional
images to be measured. You can add the same image multiple times
if you want to measure the intensity within several different
objects.""",
            ),
        )

        group.append(
            "wants_objects",
            cps.Binary(
                "Measure the intensity only from areas enclosed by objects?",
                False,
                doc="""\
Select *Yes* to measure only those pixels within an object type you
choose, identified by a prior module. Note that this module will
aggregate intensities across all objects in the image: to measure each
object individually, see **MeasureObjectIntensity** instead.
""" % globals(),
            ),
        )

        group.append(
            "object_name",
            cps.ObjectNameSubscriber(
                "Select the input objects",
                "None",
                doc="""\
*(Used only when measuring intensity from area occupied by objects)*

Select the objects that the intensity will be aggregated within. The
intensity measurement will be restricted to the pixels within these
objects.""",
            ),
        )

        if can_remove:
            group.append(
                "remover",
                cps.RemoveSettingButton("", "Remove this image", self.images,
                                        group),
            )
        self.images.append(group)
Пример #11
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 = 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 = DoSomething("", "Add another object",
                                       self.add_object_cb)
        self.object_divider = cps.Divider()

        self.bins_groups = []
        self.bins_count = cps.HiddenCount(self.bins_groups)
        self.add_bins_cb(can_remove=False)
        self.add_bins = DoSomething("", "Add another histogram",
                                    self.add_bins_cb)
Пример #12
0
    def add_channelfn(self, can_remove=True):
        """Add another image channel

        can_remove - true if we are allowed to remove this channel
        """
        group = cps.SettingsGroup()
        self.channels.append(group)

        # Check which cellprofiler image we are in the group
        # (each channel translates to a single cellprofiler image)
        cpimg_index = 0
        for channel in self.channels:
            if id(channel) == id(group):
                break
            cpimg_index += 1

        group.append("divider", cps.Divider(line=True))
        group.append(
            "cpimage_name",
            cps.ImageNameProvider("Image name",
                                  default_cpimage_name(cpimg_index)),
        )
        channel_numbers = [
            str(x) for x in range(0, max(10,
                                         len(self.channels) + 2))
        ]
        group.append(
            "channel_number",
            cps.Choice(
                "Channel number:",
                channel_numbers,
                channel_numbers[len(self.channels) - 1],
                doc="""(Used only for multichannel images)
			The channels of a multichannel image are numbered starting from 0 (zero).

			Each channel is a greyscale image, acquired using different
			illumination sources and/or optics. Use this setting to pick
			the channel to associate with the image or images you load from
			OMERO.""",
            ),
        )
        group.can_remove = can_remove
        if can_remove:
            group.append(
                "remover",
                cps.RemoveSettingButton("Remove this channel",
                                        "Remove channel", self.channels,
                                        group),
            )
 def add_image_cb(self, can_remove = True):
     '''Add an image to the image_groups collection
     
     can_delete - set this to False to keep from showing the "remove"
                  button for images that must be present.
     '''
     group = cps.SettingsGroup()
     if can_remove:
         group.append("divider", cps.Divider(line=False))
     group.append('image_name', 
                  ImageSubscriber("Select an image to measure","None",
                                          doc="""
                                          What did you call the grayscale images whose texture you want to measure?"""))
     if can_remove:
         group.append("remover", cps.do_something.RemoveSettingButton("", "Remove this image", self.image_groups, group))
     self.image_groups.append(group)
Пример #14
0
    def create_settings(self):
        self.flags = []
        self.flag_count = cps.HiddenCount(self.flags)
        self.add_flag_button = cps.DoSomething("", "Add another flag",
                                               self.add_flag)
        self.spacer_1 = cps.Divider()
        self.add_flag(can_delete=False)
        self.ignore_flag_on_last = cps.Binary(
            "Ignore flag skips on last cycle?",
            False,
            doc="""\
When set to *{YES}*, this option allows you to bypass skipping on the last
cycle of an image group.  This behavior is usually not desired, but may be 
useful when using SaveImages 'Save on last cycle' option for an image made
by any other module than MakeProjection, CorrectIlluminationCalculate, and Tile.
""".format(**{"YES": "Yes"}),
        )
Пример #15
0
    def add_image(self, can_remove=True):
        """Add an image + associated questions and buttons"""
        group = cps.SettingsGroup()
        if can_remove:
            group.append("divider", cps.Divider(line=True))

        group.append(
            "input_image_name",
            cps.ImageNameSubscriber(
                "Select an additional image to tile",
                "None",
                doc="""Select an additional image to tile?""",
            ),
        )
        if can_remove:
            group.append(
                "remover",
                cps.RemoveSettingButton("", "Remove above image",
                                        self.additional_images, group),
            )
        self.additional_images.append(group)
 def add_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', 
                  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', 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.do_something.RemoveSettingButton("", "Remove this scale", self.scale_groups, group))
     self.scale_groups.append(group)
Пример #17
0
    def add_image(self, can_remove=True):
        group = cps.SettingsGroup()
        group.can_remove = can_remove
        if can_remove:
            group.append("divider", cps.Divider())
        idx = len(self.outputs)
        default_name = STAINS_BY_POPULARITY[idx % len(STAINS_BY_POPULARITY)]
        default_name = default_name.replace(" ", "")

        group.append(
            "image_name",
            cps.ImageNameProvider(
                "Name the output image",
                default_name,
                doc="""\
Use this setting to name one of the images produced by the
module for a particular stain. The image can be used in
subsequent modules in the pipeline.
""",
            ),
        )

        choices = list(sorted(STAIN_DICTIONARY.keys())) + [CHOICE_CUSTOM]

        group.append(
            "stain_choice",
            cps.Choice(
                "Stain",
                choices=choices,
                doc="""\
Use this setting to choose the absorbance values for a particular stain.

The stains are:

|Unmix_image0|

(Information taken from `here`_,
`here <http://en.wikipedia.org/wiki/Staining>`__, and
`here <http://stainsfile.info>`__.)
You can choose *{CHOICE_CUSTOM}* and enter your custom values for the
absorbance (or use the estimator to determine values from single-stain
images).

.. _here: http://en.wikipedia.org/wiki/Histology#Staining
.. |Unmix_image0| image:: {UNMIX_COLOR_CHART}

""".format(
                    **{
                        "UNMIX_COLOR_CHART":
                        cellprofiler.gui.help.content.image_resource(
                            "UnmixColors.png"),
                        "CHOICE_CUSTOM":
                        CHOICE_CUSTOM,
                    }),
            ),
        )

        group.append(
            "red_absorbance",
            cps.Float(
                "Red absorbance",
                0.5,
                0,
                1,
                doc="""\
*(Used only if "%(CHOICE_CUSTOM)s" is selected for the stain)*

The red absorbance setting estimates the dye’s absorbance of light in
the red channel.You should enter a value between 0 and 1 where 0 is no
absorbance and 1 is complete absorbance. You can use the estimator to
calculate this value automatically.
""" % globals(),
            ),
        )

        group.append(
            "green_absorbance",
            cps.Float(
                "Green absorbance",
                0.5,
                0,
                1,
                doc="""\
*(Used only if "%(CHOICE_CUSTOM)s" is selected for the stain)*

The green absorbance setting estimates the dye’s absorbance of light in
the green channel. You should enter a value between 0 and 1 where 0 is
no absorbance and 1 is complete absorbance. You can use the estimator to
calculate this value automatically.
""" % globals(),
            ),
        )

        group.append(
            "blue_absorbance",
            cps.Float(
                "Blue absorbance",
                0.5,
                0,
                1,
                doc="""\
*(Used only if "%(CHOICE_CUSTOM)s" is selected for the stain)*

The blue absorbance setting estimates the dye’s absorbance of light in
the blue channel. You should enter a value between 0 and 1 where 0 is no
absorbance and 1 is complete absorbance. You can use the estimator to
calculate this value automatically.
""" % globals(),
            ),
        )

        def on_estimate():
            result = self.estimate_absorbance()
            if result is not None:
                (
                    group.red_absorbance.value,
                    group.green_absorbance.value,
                    group.blue_absorbance.value,
                ) = result

        group.append(
            "estimator_button",
            cps.DoSomething(
                "Estimate absorbance from image",
                "Estimate",
                on_estimate,
                doc="""\
Press this button to load an image of a sample stained only with the dye
of interest. **UnmixColors** will estimate appropriate red, green and
blue absorbance values from the image.
            """,
            ),
        )

        if can_remove:
            group.append(
                "remover",
                cps.RemoveSettingButton("", "Remove this image", self.outputs,
                                        group),
            )
        self.outputs.append(group)
Пример #18
0
    def add_image(self, can_remove=True):
        group = GranularitySettingsGroup()
        group.can_remove = can_remove
        if can_remove:
            group.append("divider", cps.Divider(line=True))

        group.append(
            "image_name",
            cps.ImageNameSubscriber(
                "Select an image to measure",
                "None",
                doc=
                "Select the grayscale images whose granularity you want to measure.",
            ),
        )

        group.append(
            "subsample_size",
            cps.Float(
                "Subsampling factor for granularity measurements",
                0.25,
                minval=np.finfo(float).eps,
                maxval=1,
                doc="""\
If the textures of interest are larger than a few pixels, we recommend
you subsample the image with a factor <1 to speed up the processing.
Down sampling the image will let you detect larger structures with a
smaller sized structure element. A factor >1 might increase the accuracy
but also require more processing time. Images are typically of higher
resolution than is required for granularity measurements, so the default
value is 0.25. For low-resolution images, increase the subsampling
fraction; for high-resolution images, decrease the subsampling fraction.
Subsampling by 1/4 reduces computation time by (1/4) :sup:`3` because the
size of the image is (1/4) :sup:`2` of original and the range of granular
spectrum can be 1/4 of original. Moreover, the results are sometimes
actually a little better with subsampling, which is probably because
with subsampling the individual granular spectrum components can be used
as features, whereas without subsampling a feature should be a sum of
several adjacent granular spectrum components. The recommendation on the
numerical value cannot be determined in advance; an analysis as in this
reference may be required before running the whole set. See this `pdf`_,
slides 27-31, 49-50.

.. _pdf: http://www.ravkin.net/presentations/Statistical%20properties%20of%20algorithms%20for%20analysis%20of%20cell%20images.pdf""",
            ),
        )

        group.append(
            "image_sample_size",
            cps.Float(
                "Subsampling factor for background reduction",
                0.25,
                minval=np.finfo(float).eps,
                maxval=1,
                doc="""\
It is important to remove low frequency image background variations as
they will affect the final granularity measurement. Any method can be
used as a pre-processing step prior to this module; we have chosen to
simply subtract a highly open image. To do it quickly, we subsample the
image first. The subsampling factor for background reduction is usually
[0.125 – 0.25]. This is highly empirical, but a small factor should be
used if the structures of interest are large. The significance of
background removal in the context of granulometry is that image volume
at certain granular size is normalized by total image volume, which
depends on how the background was removed.""",
            ),
        )

        group.append(
            "element_size",
            cps.Integer(
                "Radius of structuring element",
                10,
                minval=1,
                doc="""\
This radius should correspond to the radius of the textures of interest
*after* subsampling; i.e., if textures in the original image scale have
a radius of 40 pixels, and a subsampling factor of 0.25 is used, the
structuring element size should be 10 or slightly smaller, and the range
of the spectrum defined below will cover more sizes.""",
            ),
        )

        group.append(
            "granular_spectrum_length",
            cps.Integer(
                "Range of the granular spectrum",
                16,
                minval=1,
                doc="""\
You may need a trial run to see which granular
spectrum range yields informative measurements. Start by using a wide spectrum and
narrow it down to the informative range to save time.""",
            ),
        )

        group.append(
            "add_objects_button",
            cps.DoSomething(
                "",
                "Add another object",
                group.add_objects,
                doc="""\
Press this button to add granularity measurements for objects, such as
those identified by a prior **IdentifyPrimaryObjects** module.
**MeasureGranularity** will measure the image’s granularity within each
object at the requested scales.""",
            ),
        )

        group.objects = []

        group.object_count = cps.HiddenCount(group.objects, "Object count")

        if can_remove:
            group.append(
                "remover",
                cps.RemoveSettingButton("", "Remove this image", self.images,
                                        group),
            )
        self.images.append(group)
        return group
    def add_compmeasurement(self, can_delete=True):
        """Add an compmeasurement and its settings to the list of compmeasurements"""
        group = cps.SettingsGroup()

        object_name = cps.subscriber.LabelSubscriber("Select Object")

        compmeasurement_name = PatchedMeasurementSetting(
            "Select the measurment to correct for spillover",
            object_name.get_value,
            "None",
            doc=""" Select compmeasurement
            to be spillover corrected""",
        )

        corrected_compmeasurement_suffix = cps.text.alphanumeric.Alphanumeric(
            "Name the output compmeasurement suffix",
            "Corrected",
            doc="""
            Enter a name for the corrected measurement.""",
        )

        spill_correct_function_image_name = cps.subscriber.ImageSubscriber(
            "Select the spillover function image",
            "None",
            doc="""
            Select the spillover correction image that will be used to
            carry out the correction. This image is usually produced by the R
            software CATALYST or loaded as a .tiff format image using the
            <b>Images</b> module or
            <b>LoadSingleImage</b>.""",
        )
        spill_correct_method = cps.choice.Choice(
            "Spillover correction method",
            [METHOD_NNLS, METHOD_LS],
            doc="""
            Select the spillover correction method.
            <ul>
            <li><i>%(METHOD_LS)s:</i> Gives the least square solution
            for overdetermined solutions or the exact solution for exactly
            constraint problems. </li>
            <li><i>%(METHOD_NNLS)s:</i> Gives the non linear least squares
            solution: The most accurate solution, according to the least
            squares criterium, without any negative values.
            </li>
            </ul>
            """ % globals(),
        )

        compmeasurement_settings = cps.SettingsGroup()
        compmeasurement_settings.append("object_name", object_name)
        compmeasurement_settings.append("compmeasurement_name",
                                        compmeasurement_name)
        compmeasurement_settings.append("corrected_compmeasurement_suffix",
                                        corrected_compmeasurement_suffix)
        compmeasurement_settings.append("spill_correct_function_image_name",
                                        spill_correct_function_image_name)
        compmeasurement_settings.append("spill_correct_method",
                                        spill_correct_method)

        if can_delete:
            compmeasurement_settings.append(
                "remover",
                cps.do_something.RemoveSettingButton(
                    "",
                    "Remove this measurement",
                    self.compmeasurements,
                    compmeasurement_settings,
                ),
            )
        compmeasurement_settings.append("divider", cps.Divider())
        self.compmeasurements.append(compmeasurement_settings)
Пример #20
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",
                "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)
Пример #21
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(),
                    "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* 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* 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* 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.""",
        )

        self.rounding = cps.Choice(
            "How should the output value be rounded?",
            ROUNDING,
            doc="""\
Choose how the values should be rounded- not at all, to a specified number of decimal places, 
to the next lowest integer ("floor rounding"), or to the next highest integer ("ceiling rounding").
Note that for rounding to an arbitrary number of decimal places, Python uses "round to even" rounding,
such that ties round to the nearest even number. Thus, 1.5 and 2.5 both round to to 2 at 0 decimal 
places, 2.45 rounds to 2.4, 2.451 rounds to 2.5, and 2.55 rounds to 2.6 at 1 decimal place. See the 
numpy documentation for more information.  
""",
        )

        self.rounding_digit = cps.Integer(
            "Enter how many decimal places the value should be rounded to",
            0,
            doc="""\
Enter how many decimal places the value should be rounded to. 0 will round to an integer (e.g. 1, 2), 1 to 
one decimal place (e.g. 0.1, 0.2), -1 to one value before the decimal place (e.g. 10, 20), etc.
""",
        )
Пример #22
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)
Пример #23
0
    def add_image(self, can_delete=True):
        """Add an image and its settings to the list of images"""
        image_name = cps.ImageNameSubscriber(
            "Select the input image", "None", doc="Select the image to be corrected."
        )

        corrected_image_name = cps.ImageNameProvider(
            "Name the output image",
            "CorrBlue",
            doc="Enter a name for the corrected image.",
        )

        illum_correct_function_image_name = cps.ImageNameSubscriber(
            "Select the illumination function",
            "None",
            doc="""\
Select the illumination correction function image that will be used to
carry out the correction. This image is usually produced by another
module or loaded as a .mat or .npy format image using the **Images** module
or a **Load** module, most commonly **LoadSingleImage**.

Note that loading .mat format images is deprecated and will be removed in
a future version of CellProfiler. You can export .mat format images as
.npy format images using **SaveImages** to ensure future compatibility.
""",
        )

        divide_or_subtract = cps.Choice(
            "Select how the illumination function is applied",
            [DOS_DIVIDE, DOS_SUBTRACT],
            doc="""\
This choice depends on how the illumination function was calculated and
on your physical model of the way illumination variation affects the
background of images relative to the objects in images; it is also
somewhat empirical.

-  *%(DOS_SUBTRACT)s:* Use this option if the background signal is
   significant relative to the real signal coming from the cells. If you
   created the illumination correction function using
   *Background*, then you will want to choose
   *%(DOS_SUBTRACT)s* here.
-  *%(DOS_DIVIDE)s:* Choose this option if the signal to background
   ratio is high (the cells are stained very strongly). If you created
   the illumination correction function using *Regular*, then
   you will want to choose *%(DOS_DIVIDE)s* here.
"""
            % globals(),
        )

        image_settings = cps.SettingsGroup()
        image_settings.append("image_name", image_name)
        image_settings.append("corrected_image_name", corrected_image_name)
        image_settings.append(
            "illum_correct_function_image_name", illum_correct_function_image_name
        )
        image_settings.append("divide_or_subtract", divide_or_subtract)
        image_settings.append("rescale_option", RE_NONE)

        if can_delete:
            image_settings.append(
                "remover",
                cps.RemoveSettingButton(
                    "", "Remove this image", self.images, image_settings
                ),
            )
        image_settings.append("divider", cps.Divider())
        self.images.append(image_settings)
Пример #24
0
    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* if you have dose-response data and you want to
log-transform the dose values before fitting a sigmoid curve.

Select *No* 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* 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=[
                    cpprefs.DEFAULT_OUTPUT_FOLDER_NAME,
                    cpprefs.DEFAULT_INPUT_FOLDER_NAME,
                    cpprefs.ABSOLUTE_FOLDER_NAME,
                    cpprefs.DEFAULT_OUTPUT_SUBFOLDER_NAME,
                    cpprefs.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)
Пример #25
0
    def add_mapping(self):
        group = cps.SettingsGroup()
        group.append(
            "local_directory",
            cps.Text(
                "Local root path",
                cpprefs.get_default_image_directory(),
                doc="""\
Enter the path to files on this computer. This is the root path on the
local machine (i.e., the computer setting up the batch files).

For instance, a Windows machine might access files images by mounting the file system using a drive
letter, like this:

``Z:\your_data\images``

and the cluster computers access the same file system like this:

``/server_name/your_name/your_data/images``

In this case, since the ``your_data\images`` portion of the path is
the same for both, the local root path is the portion prior, i.e.,
``Z:\`` and similarly for the cluster root path, i.e.,
``/server_name/your_name/``.

If **CreateBatchFiles** finds any pathname that matches the local root path
at the beginning, it will replace that matching portion with the cluster root path.

For example, if you have mapped the remote cluster machine like this:

``Z:\your_data\images``

(on a Windows machine, for instance) and the cluster machine sees the same folder like this:

``/server_name/your_name/your_data/images``

you would enter ``Z:\`` here for the local root path and ``/server_name/your_name/`` for the
cluster root path in the next setting.""",
            ),
        )

        group.append(
            "remote_directory",
            cps.Text(
                "Cluster root path",
                cpprefs.get_default_image_directory(),
                doc="""\
Enter the path to files on the cluster. This is the cluster root path,
i.e., how the cluster machine sees the top-most folder where your
input/output files are stored.

For instance, a Windows machine might access files images by mounting the file system using a drive
letter, like this:

``Z:\your_data\images``

and the cluster computers access the same file system like this:

``/server_name/your_name/your_data/images``

In this case, since the ``your_data\images`` portion of the path is
the same for both, the local root path is the portion prior, i.e.,
``Z:\`` and similarly for the cluster root path, i.e.,
``/server_name/your_name/``.

If **CreateBatchFiles** finds any pathname that matches the local root path
at the beginning, it will replace that matching portion with the cluster root path.

For example, if you have mapped the remote cluster machine like this:

``Z:\your_data\images``

(on a Windows machine, for instance) and the cluster machine sees the same folder like this:

``/server_name/your_name/your_data/images``

you would enter ``Z:\`` in the previous setting for the local root
path and ``/server_name/your_name/`` here for the cluster root path.""",
            ),
        )
        group.append(
            "remover",
            cps.RemoveSettingButton("", "Remove this path mapping",
                                    self.mappings, group),
        )
        group.append("divider", cps.Divider(line=False))
        self.mappings.append(group)
    def create_settings(self):
        '''Create the settings for the ExportToCellH5 module'''
        self.directory = Directory("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.text.Filename("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.text.Filename.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"</i> to automatically overwrite any existing data
            for a site. Select <i>"No"</i> to be prompted first.

            If you are running the pipeline on a computing cluster,
            select <i>"Yes"</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"</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"</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 = 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 = 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 = 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"</i> to pick the
            measurements to be exported. Select <i>"No"</i> to automatically
            export all measurements available at this stage of the pipeline.
            """ % globals())
        self.measurements = 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 = DoSomething("Add objects to export",
                                              "Add objects", self.add_objects)
        self.images_to_export = []
        self.add_image_button = 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)
Пример #27
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",
                "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*" if you want to create a bin for objects whose values
fall below the low threshold. Select "*No*" 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*" if you want to create a bin for objects whose values
are above the high threshold.

Select "*No*" 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*" to assign custom names to bins you have specified.

Select "*No*" 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",
                "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*" 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)
Пример #28
0
    def add_function(self, can_remove=True):
        group = MorphSettingsGroup()
        group.can_remove = can_remove
        if can_remove:
            group.append("divider", cps.Divider(line=False))
        group.append(
            "function",
            cps.Choice(
                "Select the operation to perform",
                F_ALL,
                doc=
                """Choose one of the operations described in this module's help.""",
            ),
        )

        group.append(
            "repeats_choice",
            cps.Choice(
                "Number of times to repeat operation",
                R_ALL,
                doc="""\
This setting controls the number of times that the same operation is
applied successively to the image.

-  *%(R_ONCE)s:* Perform the operation once on the image.
-  *%(R_FOREVER)s:* Perform the operation on the image until successive
   iterations yield the same image.
-  *%(R_CUSTOM)s:* Perform the operation a custom number of times.""" %
                globals(),
            ),
        )

        group.append(
            "custom_repeats",
            cps.Integer(self.CUSTOM_REPEATS_TEXT,
                        2,
                        1,
                        doc=self.CUSTOM_REPEATS_DOC),
        )

        group.append(
            "rescale_values",
            cps.Binary(
                "Rescale values from 0 to 1?",
                True,
                doc="""\
*(Used only for the "%(F_DISTANCE)s" operation).*

Select "*Yes*" to rescale the transformed values to lie between 0 and
1. This is the option to use if the distance transformed image is to be
used for thresholding by an **Identify** module or the like, which
assumes a 0-1 scaling.

Select "*No*" to leave the values in absolute pixel units. This useful
in cases where the actual pixel distances are to be used downstream as
input for a measurement module.""" % globals(),
            ),
        )

        if can_remove:
            group.append(
                "remove",
                cps.RemoveSettingButton("", "Remove this operation",
                                        self.functions, group),
            )
        self.functions.append(group)