class OpNanshePreprocessDataCached(Operator):
    """
    Given an input image and max/min bounds,
    masks out (i.e. sets to zero) all pixels that fall outside the bounds.
    """
    name = "OpNanshePreprocessDataCached"
    category = "Pointwise"

    Input = InputSlot()
    CacheInput = InputSlot(optional=True)

    ToRemoveZeroedLines = InputSlot(value=True)
    ErosionShape = InputSlot(value=[21, 1])
    DilationShape = InputSlot(value=[1, 3])

    ToExtractF0 = InputSlot(value=True)
    HalfWindowSize = InputSlot(value=400, stype='int')
    WhichQuantile = InputSlot(value=0.15, stype='float')
    TemporalSmoothingGaussianFilterStdev = InputSlot(value=5.0, stype='float')
    SpatialSmoothingGaussianFilterStdev = InputSlot(value=5.0, stype='float')
    TemporalSmoothingGaussianFilterWindowSize = InputSlot(value=5.0,
                                                          stype='float')
    SpatialSmoothingGaussianFilterWindowSize = InputSlot(value=5.0,
                                                         stype='float')
    BiasEnabled = InputSlot(value=False, stype='bool')
    Bias = InputSlot(value=0.0, stype='float')

    ToWaveletTransform = InputSlot(value=True)
    Scale = InputSlot(value=4)

    OpNansheRemoveZeroedLinesOutput = OutputSlot()
    OpNansheExtractF0_dF_F_Output = OutputSlot()
    OpNansheExtractF0_F0_Output = OutputSlot()
    OpNansheWaveletTransformOutput = OutputSlot()

    CleanBlocks = OutputSlot()
    CacheOutput = OutputSlot()
    Output = OutputSlot()

    def __init__(self, *args, **kwargs):
        super(OpNanshePreprocessDataCached, self).__init__(*args, **kwargs)

        self.opConvertType = OpConvertTypeCached(parent=self)
        self.opConvertType.Dtype.setValue(numpy.float32)

        self.opNansheRemoveZeroedLines = OpNansheRemoveZeroedLinesCached(
            parent=self)
        self.opNansheRemoveZeroedLines.ErosionShape.connect(self.ErosionShape)
        self.opNansheRemoveZeroedLines.DilationShape.connect(
            self.DilationShape)

        self.opNansheExtractF0 = OpNansheExtractF0Cached(parent=self)
        self.opNansheExtractF0.HalfWindowSize.connect(self.HalfWindowSize)
        self.opNansheExtractF0.WhichQuantile.connect(self.WhichQuantile)
        self.opNansheExtractF0.TemporalSmoothingGaussianFilterStdev.connect(
            self.TemporalSmoothingGaussianFilterStdev)
        self.opNansheExtractF0.SpatialSmoothingGaussianFilterStdev.connect(
            self.SpatialSmoothingGaussianFilterStdev)
        self.opNansheExtractF0.TemporalSmoothingGaussianFilterWindowSize.connect(
            self.TemporalSmoothingGaussianFilterWindowSize)
        self.opNansheExtractF0.SpatialSmoothingGaussianFilterWindowSize.connect(
            self.SpatialSmoothingGaussianFilterWindowSize)
        self.opNansheExtractF0.BiasEnabled.connect(self.BiasEnabled)
        self.opNansheExtractF0.Bias.connect(self.Bias)

        self.opNansheWaveletTransform = OpNansheWaveletTransformCached(
            parent=self)
        self.opNansheWaveletTransform.Scale.connect(self.Scale)

        self.OpNansheRemoveZeroedLinesOutput.connect(
            self.opNansheRemoveZeroedLines.Output)
        self.OpNansheExtractF0_dF_F_Output.connect(self.opNansheExtractF0.dF_F)
        self.OpNansheExtractF0_F0_Output.connect(self.opNansheExtractF0.F0)
        self.OpNansheWaveletTransformOutput.connect(
            self.opNansheWaveletTransform.Output)

        self.opCache = OpArrayCache(parent=self)
        self.opCache.fixAtCurrent.setValue(False)
        self.CleanBlocks.connect(self.opCache.CleanBlocks)

        self.CacheOutput.connect(self.opCache.Output)

    def setupOutputs(self):
        self.opNansheRemoveZeroedLines.Input.disconnect()
        self.opNansheExtractF0.Input.disconnect()
        self.opNansheWaveletTransform.Input.disconnect()
        self.opCache.Input.disconnect()

        next_output = self.Input

        self.opConvertType.Input.connect(next_output)
        next_output = self.opConvertType.Output

        if self.ToRemoveZeroedLines.value:
            self.opNansheRemoveZeroedLines.Input.connect(next_output)
            next_output = self.opNansheRemoveZeroedLines.Output

        if self.ToExtractF0.value:
            self.opNansheExtractF0.Input.connect(next_output)
            next_output = self.opNansheExtractF0.dF_F

        if self.ToWaveletTransform.value:
            self.opNansheWaveletTransform.Input.connect(next_output)
            next_output = self.opNansheWaveletTransform.Output

        self.Output.connect(next_output)
        self.opCache.Input.connect(next_output)

        self.opCache.blockShape.setValue(self.opCache.Output.meta.shape)

    # Don't need execute as the output will be drawn through the Output slot.

    def setInSlot(self, slot, subindex, key, value):
        assert slot == self.CacheInput

        self.opCache.setInSlot(self.opCache.Input, subindex, key, value)

    def propagateDirty(self, slot, subindex, roi):
        if slot.name == "ToRemoveZeroedLines":
            if slot.value:
                self.opNansheRemoveZeroedLines.Output.setDirty(slice(None))
            else:
                if self.ToExtractF0.value:
                    self.opNansheExtractF0.Input.setDirty(slice(None))
                elif self.ToWaveletTransform.value:
                    self.opNansheWaveletTransform.Input.setDirty(slice(None))
                else:
                    self.opCache.Input.setDirty(slice(None))
        elif slot.name == "ToExtractF0":
            if slot.value:
                self.opNansheExtractF0.dF_F.setDirty(slice(None))
                self.opNansheExtractF0.F0.setDirty(slice(None))
            else:
                if self.ToWaveletTransform.value:
                    self.opNansheWaveletTransform.Input.setDirty(slice(None))
                else:
                    self.opCache.Input.setDirty(slice(None))
        elif slot.name == "ToWaveletTransform":
            if slot.value:
                self.opNansheWaveletTransform.Output.setDirty(slice(None))
            else:
                self.opCache.Input.setDirty(slice(None))
class OpNanshePreprocessDataCached(Operator):
    """
    Given an input image and max/min bounds,
    masks out (i.e. sets to zero) all pixels that fall outside the bounds.
    """
    name = "OpNanshePreprocessDataCached"
    category = "Pointwise"


    Input = InputSlot()
    CacheInput = InputSlot(optional=True)


    ToRemoveZeroedLines = InputSlot(value=True)
    ErosionShape = InputSlot(value=[21, 1])
    DilationShape = InputSlot(value=[1, 3])

    ToExtractF0 = InputSlot(value=True)
    HalfWindowSize = InputSlot(value=400, stype='int')
    WhichQuantile = InputSlot(value=0.15, stype='float')
    TemporalSmoothingGaussianFilterStdev = InputSlot(value=5.0, stype='float')
    SpatialSmoothingGaussianFilterStdev = InputSlot(value=5.0, stype='float')
    TemporalSmoothingGaussianFilterWindowSize = InputSlot(value=5.0, stype='float')
    SpatialSmoothingGaussianFilterWindowSize = InputSlot(value=5.0, stype='float')
    BiasEnabled = InputSlot(value=False, stype='bool')
    Bias = InputSlot(value=0.0, stype='float')

    ToWaveletTransform = InputSlot(value=True)
    Scale = InputSlot(value=4)


    OpNansheRemoveZeroedLinesOutput = OutputSlot()
    OpNansheExtractF0_dF_F_Output = OutputSlot()
    OpNansheExtractF0_F0_Output = OutputSlot()
    OpNansheWaveletTransformOutput = OutputSlot()

    CleanBlocks = OutputSlot()
    CacheOutput = OutputSlot()
    Output = OutputSlot()

    def __init__(self, *args, **kwargs):
        super( OpNanshePreprocessDataCached, self ).__init__( *args, **kwargs )

        self.opConvertType = OpConvertTypeCached(parent=self)
        self.opConvertType.Dtype.setValue(numpy.float32)

        self.opNansheRemoveZeroedLines = OpNansheRemoveZeroedLinesCached(parent=self)
        self.opNansheRemoveZeroedLines.ErosionShape.connect(self.ErosionShape)
        self.opNansheRemoveZeroedLines.DilationShape.connect(self.DilationShape)

        self.opNansheExtractF0 = OpNansheExtractF0Cached(parent=self)
        self.opNansheExtractF0.HalfWindowSize.connect(self.HalfWindowSize)
        self.opNansheExtractF0.WhichQuantile.connect(self.WhichQuantile)
        self.opNansheExtractF0.TemporalSmoothingGaussianFilterStdev.connect(self.TemporalSmoothingGaussianFilterStdev)
        self.opNansheExtractF0.SpatialSmoothingGaussianFilterStdev.connect(self.SpatialSmoothingGaussianFilterStdev)
        self.opNansheExtractF0.TemporalSmoothingGaussianFilterWindowSize.connect(self.TemporalSmoothingGaussianFilterWindowSize)
        self.opNansheExtractF0.SpatialSmoothingGaussianFilterWindowSize.connect(self.SpatialSmoothingGaussianFilterWindowSize)
        self.opNansheExtractF0.BiasEnabled.connect(self.BiasEnabled)
        self.opNansheExtractF0.Bias.connect(self.Bias)

        self.opNansheWaveletTransform = OpNansheWaveletTransformCached(parent=self)
        self.opNansheWaveletTransform.Scale.connect(self.Scale)


        self.OpNansheRemoveZeroedLinesOutput.connect(self.opNansheRemoveZeroedLines.Output)
        self.OpNansheExtractF0_dF_F_Output.connect(self.opNansheExtractF0.dF_F)
        self.OpNansheExtractF0_F0_Output.connect(self.opNansheExtractF0.F0)
        self.OpNansheWaveletTransformOutput.connect(self.opNansheWaveletTransform.Output)

        self.opCache = OpArrayCache(parent=self)
        self.opCache.fixAtCurrent.setValue(False)
        self.CleanBlocks.connect(self.opCache.CleanBlocks)

        self.CacheOutput.connect(self.opCache.Output)

    def setupOutputs(self):
        self.opNansheRemoveZeroedLines.Input.disconnect()
        self.opNansheExtractF0.Input.disconnect()
        self.opNansheWaveletTransform.Input.disconnect()
        self.opCache.Input.disconnect()

        next_output = self.Input

        self.opConvertType.Input.connect(next_output)
        next_output = self.opConvertType.Output

        if self.ToRemoveZeroedLines.value:
            self.opNansheRemoveZeroedLines.Input.connect(next_output)
            next_output = self.opNansheRemoveZeroedLines.Output

        if self.ToExtractF0.value:
            self.opNansheExtractF0.Input.connect(next_output)
            next_output = self.opNansheExtractF0.dF_F

        if self.ToWaveletTransform.value:
            self.opNansheWaveletTransform.Input.connect(next_output)
            next_output = self.opNansheWaveletTransform.Output

        self.Output.connect(next_output)
        self.opCache.Input.connect(next_output)

        self.opCache.blockShape.setValue( self.opCache.Output.meta.shape )

    # Don't need execute as the output will be drawn through the Output slot.

    def setInSlot(self, slot, subindex, key, value):
        assert slot == self.CacheInput

        self.opCache.setInSlot(self.opCache.Input, subindex, key, value)

    def propagateDirty(self, slot, subindex, roi):
        if slot.name == "ToRemoveZeroedLines":
            if slot.value:
                self.opNansheRemoveZeroedLines.Output.setDirty( slice(None) )
            else:
                if self.ToExtractF0.value:
                    self.opNansheExtractF0.Input.setDirty( slice(None) )
                elif self.ToWaveletTransform.value:
                    self.opNansheWaveletTransform.Input.setDirty( slice(None) )
                else:
                    self.opCache.Input.setDirty( slice(None) )
        elif slot.name == "ToExtractF0":
            if slot.value:
                self.opNansheExtractF0.dF_F.setDirty( slice(None) )
                self.opNansheExtractF0.F0.setDirty( slice(None) )
            else:
                if self.ToWaveletTransform.value:
                    self.opNansheWaveletTransform.Input.setDirty( slice(None) )
                else:
                    self.opCache.Input.setDirty( slice(None) )
        elif slot.name == "ToWaveletTransform":
            if slot.value:
                self.opNansheWaveletTransform.Output.setDirty( slice(None) )
            else:
                self.opCache.Input.setDirty( slice(None) )
class OpNanshePostprocessDataCached(Operator):
    """
    Given an input image and max/min bounds,
    masks out (i.e. sets to zero) all pixels that fall outside the bounds.
    """
    name = "OpNanshePostprocessDataCached"
    category = "Pointwise"

    Input = InputSlot()
    CacheInput = InputSlot(optional=True)

    SignificanceThreshold = InputSlot(value=3.0, stype="float")
    WaveletTransformScale = InputSlot(value=4, stype="int")
    NoiseThreshold = InputSlot(value=4.0, stype="float")
    AcceptedRegionShapeConstraints_MajorAxisLength_Min = InputSlot(
        value=0.0, stype="float")
    AcceptedRegionShapeConstraints_MajorAxisLength_Min_Enabled = InputSlot(
        value=True, stype="bool")
    AcceptedRegionShapeConstraints_MajorAxisLength_Max = InputSlot(
        value=25.0, stype="float")
    AcceptedRegionShapeConstraints_MajorAxisLength_Max_Enabled = InputSlot(
        value=True, stype="bool")

    PercentagePixelsBelowMax = InputSlot(value=0.8, stype="float")
    MinLocalMaxDistance = InputSlot(value=20.0, stype="float")

    AcceptedNeuronShapeConstraints_Area_Min = InputSlot(value=45, stype="int")
    AcceptedNeuronShapeConstraints_Area_Min_Enabled = InputSlot(value=True,
                                                                stype="bool")
    AcceptedNeuronShapeConstraints_Area_Max = InputSlot(value=600, stype="int")
    AcceptedNeuronShapeConstraints_Area_Max_Enabled = InputSlot(value=True,
                                                                stype="bool")

    AcceptedNeuronShapeConstraints_Eccentricity_Min = InputSlot(value=0.0,
                                                                stype="float")
    AcceptedNeuronShapeConstraints_Eccentricity_Min_Enabled = InputSlot(
        value=True, stype="bool")
    AcceptedNeuronShapeConstraints_Eccentricity_Max = InputSlot(value=0.9,
                                                                stype="float")
    AcceptedNeuronShapeConstraints_Eccentricity_Max_Enabled = InputSlot(
        value=True, stype="bool")

    AlignmentMinThreshold = InputSlot(value=0.6, stype="float")
    OverlapMinThreshold = InputSlot(value=0.6, stype="float")

    Fuse_FractionMeanNeuronMaxThreshold = InputSlot(value=0.01, stype="float")

    CleanBlocks = OutputSlot()
    Output = OutputSlot()
    ColorizedOutput = OutputSlot()

    def __init__(self, *args, **kwargs):
        super(OpNanshePostprocessDataCached, self).__init__(*args, **kwargs)

        self.opPostprocessing = OpNanshePostprocessData(parent=self)

        self.opPostprocessing.SignificanceThreshold.connect(
            self.SignificanceThreshold)
        self.opPostprocessing.WaveletTransformScale.connect(
            self.WaveletTransformScale)
        self.opPostprocessing.NoiseThreshold.connect(self.NoiseThreshold)
        self.opPostprocessing.AcceptedRegionShapeConstraints_MajorAxisLength_Min.connect(
            self.AcceptedRegionShapeConstraints_MajorAxisLength_Min)
        self.opPostprocessing.AcceptedRegionShapeConstraints_MajorAxisLength_Min_Enabled.connect(
            self.AcceptedRegionShapeConstraints_MajorAxisLength_Min_Enabled)
        self.opPostprocessing.AcceptedRegionShapeConstraints_MajorAxisLength_Max.connect(
            self.AcceptedRegionShapeConstraints_MajorAxisLength_Max)
        self.opPostprocessing.AcceptedRegionShapeConstraints_MajorAxisLength_Max_Enabled.connect(
            self.AcceptedRegionShapeConstraints_MajorAxisLength_Max_Enabled)
        self.opPostprocessing.PercentagePixelsBelowMax.connect(
            self.PercentagePixelsBelowMax)
        self.opPostprocessing.MinLocalMaxDistance.connect(
            self.MinLocalMaxDistance)
        self.opPostprocessing.AcceptedNeuronShapeConstraints_Area_Min.connect(
            self.AcceptedNeuronShapeConstraints_Area_Min)
        self.opPostprocessing.AcceptedNeuronShapeConstraints_Area_Min_Enabled.connect(
            self.AcceptedNeuronShapeConstraints_Area_Min_Enabled)
        self.opPostprocessing.AcceptedNeuronShapeConstraints_Area_Max.connect(
            self.AcceptedNeuronShapeConstraints_Area_Max)
        self.opPostprocessing.AcceptedNeuronShapeConstraints_Area_Max_Enabled.connect(
            self.AcceptedNeuronShapeConstraints_Area_Max_Enabled)
        self.opPostprocessing.AcceptedNeuronShapeConstraints_Eccentricity_Min.connect(
            self.AcceptedNeuronShapeConstraints_Eccentricity_Min)
        self.opPostprocessing.AcceptedNeuronShapeConstraints_Eccentricity_Min_Enabled.connect(
            self.AcceptedNeuronShapeConstraints_Eccentricity_Min_Enabled)
        self.opPostprocessing.AcceptedNeuronShapeConstraints_Eccentricity_Max.connect(
            self.AcceptedNeuronShapeConstraints_Eccentricity_Max)
        self.opPostprocessing.AcceptedNeuronShapeConstraints_Eccentricity_Max_Enabled.connect(
            self.AcceptedNeuronShapeConstraints_Eccentricity_Max_Enabled)
        self.opPostprocessing.AlignmentMinThreshold.connect(
            self.AlignmentMinThreshold)
        self.opPostprocessing.OverlapMinThreshold.connect(
            self.OverlapMinThreshold)
        self.opPostprocessing.Fuse_FractionMeanNeuronMaxThreshold.connect(
            self.Fuse_FractionMeanNeuronMaxThreshold)

        self.opCache = OpArrayCache(parent=self)
        self.opCache.fixAtCurrent.setValue(False)
        self.CleanBlocks.connect(self.opCache.CleanBlocks)

        self.opPostprocessing.Input.connect(self.Input)
        self.opCache.Input.connect(self.opPostprocessing.Output)
        self.Output.connect(self.opCache.Output)

        self.opColorizeLabelImage = OpColorizeLabelImage(parent=self)
        self.opColorizeLabelImage.Input.connect(self.Output)
        self.ColorizedOutput.connect(self.opColorizeLabelImage.Output)

    def setupOutputs(self):
        self.opCache.blockShape.setValue(
            self.opPostprocessing.Output.meta.shape)

        self.Output.meta.assignFrom(self.opCache.Output.meta)

    def setInSlot(self, slot, subindex, key, value):
        assert slot == self.CacheInput

        self.opCache.setInSlot(self.opCache.Input, subindex, key, value)

    def propagateDirty(self, slot, subindex, roi):
        pass
class OpNanshePostprocessDataCached(Operator):
    """
    Given an input image and max/min bounds,
    masks out (i.e. sets to zero) all pixels that fall outside the bounds.
    """
    name = "OpNanshePostprocessDataCached"
    category = "Pointwise"


    Input = InputSlot()
    CacheInput = InputSlot(optional=True)

    SignificanceThreshold = InputSlot(value=3.0, stype="float")
    WaveletTransformScale = InputSlot(value=4, stype="int")
    NoiseThreshold = InputSlot(value=4.0, stype="float")
    AcceptedRegionShapeConstraints_MajorAxisLength_Min = InputSlot(value=0.0, stype="float")
    AcceptedRegionShapeConstraints_MajorAxisLength_Min_Enabled = InputSlot(value=True, stype="bool")
    AcceptedRegionShapeConstraints_MajorAxisLength_Max = InputSlot(value=25.0, stype="float")
    AcceptedRegionShapeConstraints_MajorAxisLength_Max_Enabled = InputSlot(value=True, stype="bool")

    PercentagePixelsBelowMax = InputSlot(value=0.8, stype="float")
    MinLocalMaxDistance = InputSlot(value=20.0, stype="float")

    AcceptedNeuronShapeConstraints_Area_Min = InputSlot(value=45, stype="int")
    AcceptedNeuronShapeConstraints_Area_Min_Enabled = InputSlot(value=True, stype="bool")
    AcceptedNeuronShapeConstraints_Area_Max = InputSlot(value=600, stype="int")
    AcceptedNeuronShapeConstraints_Area_Max_Enabled = InputSlot(value=True, stype="bool")

    AcceptedNeuronShapeConstraints_Eccentricity_Min = InputSlot(value=0.0, stype="float")
    AcceptedNeuronShapeConstraints_Eccentricity_Min_Enabled = InputSlot(value=True, stype="bool")
    AcceptedNeuronShapeConstraints_Eccentricity_Max = InputSlot(value=0.9, stype="float")
    AcceptedNeuronShapeConstraints_Eccentricity_Max_Enabled = InputSlot(value=True, stype="bool")

    AlignmentMinThreshold = InputSlot(value=0.6, stype="float")
    OverlapMinThreshold = InputSlot(value=0.6, stype="float")

    Fuse_FractionMeanNeuronMaxThreshold = InputSlot(value=0.01, stype="float")

    CleanBlocks = OutputSlot()
    Output = OutputSlot()
    ColorizedOutput = OutputSlot()

    def __init__(self, *args, **kwargs):
        super( OpNanshePostprocessDataCached, self ).__init__( *args, **kwargs )

        self.opPostprocessing = OpNanshePostprocessData(parent=self)

        self.opPostprocessing.SignificanceThreshold.connect(self.SignificanceThreshold)
        self.opPostprocessing.WaveletTransformScale.connect(self.WaveletTransformScale)
        self.opPostprocessing.NoiseThreshold.connect(self.NoiseThreshold)
        self.opPostprocessing.AcceptedRegionShapeConstraints_MajorAxisLength_Min.connect(self.AcceptedRegionShapeConstraints_MajorAxisLength_Min)
        self.opPostprocessing.AcceptedRegionShapeConstraints_MajorAxisLength_Min_Enabled.connect(self.AcceptedRegionShapeConstraints_MajorAxisLength_Min_Enabled)
        self.opPostprocessing.AcceptedRegionShapeConstraints_MajorAxisLength_Max.connect(self.AcceptedRegionShapeConstraints_MajorAxisLength_Max)
        self.opPostprocessing.AcceptedRegionShapeConstraints_MajorAxisLength_Max_Enabled.connect(self.AcceptedRegionShapeConstraints_MajorAxisLength_Max_Enabled)
        self.opPostprocessing.PercentagePixelsBelowMax.connect(self.PercentagePixelsBelowMax)
        self.opPostprocessing.MinLocalMaxDistance.connect(self.MinLocalMaxDistance)
        self.opPostprocessing.AcceptedNeuronShapeConstraints_Area_Min.connect(self.AcceptedNeuronShapeConstraints_Area_Min)
        self.opPostprocessing.AcceptedNeuronShapeConstraints_Area_Min_Enabled.connect(self.AcceptedNeuronShapeConstraints_Area_Min_Enabled)
        self.opPostprocessing.AcceptedNeuronShapeConstraints_Area_Max.connect(self.AcceptedNeuronShapeConstraints_Area_Max)
        self.opPostprocessing.AcceptedNeuronShapeConstraints_Area_Max_Enabled.connect(self.AcceptedNeuronShapeConstraints_Area_Max_Enabled)
        self.opPostprocessing.AcceptedNeuronShapeConstraints_Eccentricity_Min.connect(self.AcceptedNeuronShapeConstraints_Eccentricity_Min)
        self.opPostprocessing.AcceptedNeuronShapeConstraints_Eccentricity_Min_Enabled.connect(self.AcceptedNeuronShapeConstraints_Eccentricity_Min_Enabled)
        self.opPostprocessing.AcceptedNeuronShapeConstraints_Eccentricity_Max.connect(self.AcceptedNeuronShapeConstraints_Eccentricity_Max)
        self.opPostprocessing.AcceptedNeuronShapeConstraints_Eccentricity_Max_Enabled.connect(self.AcceptedNeuronShapeConstraints_Eccentricity_Max_Enabled)
        self.opPostprocessing.AlignmentMinThreshold.connect(self.AlignmentMinThreshold)
        self.opPostprocessing.OverlapMinThreshold.connect(self.OverlapMinThreshold)
        self.opPostprocessing.Fuse_FractionMeanNeuronMaxThreshold.connect(self.Fuse_FractionMeanNeuronMaxThreshold)


        self.opCache = OpArrayCache(parent=self)
        self.opCache.fixAtCurrent.setValue(False)
        self.CleanBlocks.connect( self.opCache.CleanBlocks )

        self.opPostprocessing.Input.connect( self.Input )
        self.opCache.Input.connect( self.opPostprocessing.Output )
        self.Output.connect( self.opCache.Output )

        self.opColorizeLabelImage = OpColorizeLabelImage(parent=self)
        self.opColorizeLabelImage.Input.connect(self.Output)
        self.ColorizedOutput.connect(self.opColorizeLabelImage.Output)

    def setupOutputs(self):
        self.opCache.blockShape.setValue( self.opPostprocessing.Output.meta.shape )

        self.Output.meta.assignFrom( self.opCache.Output.meta )

    def setInSlot(self, slot, subindex, key, value):
        assert slot == self.CacheInput

        self.opCache.setInSlot(self.opCache.Input, subindex, key, value)

    def propagateDirty(self, slot, subindex, roi):
        pass
class OpNansheGenerateDictionaryCached(Operator):
    """
    Given an input image and max/min bounds,
    masks out (i.e. sets to zero) all pixels that fall outside the bounds.
    """
    name = "OpNansheGenerateDictionaryCached"
    category = "Pointwise"


    Input = InputSlot()
    CacheInput = InputSlot(optional=True)

    K = InputSlot(value=100, stype="int")
    Gamma1 = InputSlot(value=0.0)
    Gamma2 = InputSlot(value=0.0)
    NumThreads = InputSlot(value=1)
    Batchsize = InputSlot(value=256)
    NumIter = InputSlot(value=100, stype="int")
    Lambda1 = InputSlot(value=0.2)
    Lambda2 = InputSlot(value=0.0)
    PosAlpha = InputSlot(value=True)
    PosD = InputSlot(value=True)
    Clean = InputSlot(value=True)
    Mode = InputSlot(value=2, stype="int")
    ModeD = InputSlot(value=0, stype="int")

    CleanBlocks = OutputSlot()
    Output = OutputSlot()

    def __init__(self, *args, **kwargs):
        super( OpNansheGenerateDictionaryCached, self ).__init__( *args, **kwargs )

        self.opDictionary = OpNansheGenerateDictionary(parent=self)

        self.opDictionary.K.connect(self.K)
        self.opDictionary.Gamma1.connect(self.Gamma1)
        self.opDictionary.Gamma2.connect(self.Gamma2)
        self.opDictionary.NumThreads.connect(self.NumThreads)
        self.opDictionary.Batchsize.connect(self.Batchsize)
        self.opDictionary.NumIter.connect(self.NumIter)
        self.opDictionary.Lambda1.connect(self.Lambda1)
        self.opDictionary.Lambda2.connect(self.Lambda2)
        self.opDictionary.PosAlpha.connect(self.PosAlpha)
        self.opDictionary.PosD.connect(self.PosD)
        self.opDictionary.Clean.connect(self.Clean)
        self.opDictionary.Mode.connect(self.Mode)
        self.opDictionary.ModeD.connect(self.ModeD)


        self.opCache = OpArrayCache(parent=self)
        self.opCache.fixAtCurrent.setValue(False)

        self.opDictionary.Input.connect( self.Input )
        self.opCache.Input.connect( self.opDictionary.Output )
        self.CleanBlocks.connect( self.opCache.CleanBlocks )
        self.Output.connect( self.opCache.Output )

    def setupOutputs(self):
        self.opCache.blockShape.setValue( self.opCache.Output.meta.shape )

    def setInSlot(self, slot, subindex, key, value):
        assert slot == self.CacheInput

        self.opCache.setInSlot(self.opCache.Input, subindex, key, value)

    def propagateDirty(self, slot, subindex, roi):
        pass
class OpNansheGenerateDictionaryCached(Operator):
    """
    Given an input image and max/min bounds,
    masks out (i.e. sets to zero) all pixels that fall outside the bounds.
    """
    name = "OpNansheGenerateDictionaryCached"
    category = "Pointwise"

    Input = InputSlot()
    CacheInput = InputSlot(optional=True)

    K = InputSlot(value=100, stype="int")
    Gamma1 = InputSlot(value=0.0)
    Gamma2 = InputSlot(value=0.0)
    NumThreads = InputSlot(value=1)
    Batchsize = InputSlot(value=256)
    NumIter = InputSlot(value=100, stype="int")
    Lambda1 = InputSlot(value=0.2)
    Lambda2 = InputSlot(value=0.0)
    PosAlpha = InputSlot(value=True)
    PosD = InputSlot(value=True)
    Clean = InputSlot(value=True)
    Mode = InputSlot(value=2, stype="int")
    ModeD = InputSlot(value=0, stype="int")

    CleanBlocks = OutputSlot()
    Output = OutputSlot()

    def __init__(self, *args, **kwargs):
        super(OpNansheGenerateDictionaryCached, self).__init__(*args, **kwargs)

        self.opDictionary = OpNansheGenerateDictionary(parent=self)

        self.opDictionary.K.connect(self.K)
        self.opDictionary.Gamma1.connect(self.Gamma1)
        self.opDictionary.Gamma2.connect(self.Gamma2)
        self.opDictionary.NumThreads.connect(self.NumThreads)
        self.opDictionary.Batchsize.connect(self.Batchsize)
        self.opDictionary.NumIter.connect(self.NumIter)
        self.opDictionary.Lambda1.connect(self.Lambda1)
        self.opDictionary.Lambda2.connect(self.Lambda2)
        self.opDictionary.PosAlpha.connect(self.PosAlpha)
        self.opDictionary.PosD.connect(self.PosD)
        self.opDictionary.Clean.connect(self.Clean)
        self.opDictionary.Mode.connect(self.Mode)
        self.opDictionary.ModeD.connect(self.ModeD)

        self.opCache = OpArrayCache(parent=self)
        self.opCache.fixAtCurrent.setValue(False)

        self.opDictionary.Input.connect(self.Input)
        self.opCache.Input.connect(self.opDictionary.Output)
        self.CleanBlocks.connect(self.opCache.CleanBlocks)
        self.Output.connect(self.opCache.Output)

    def setupOutputs(self):
        self.opCache.blockShape.setValue(self.opCache.Output.meta.shape)

    def setInSlot(self, slot, subindex, key, value):
        assert slot == self.CacheInput

        self.opCache.setInSlot(self.opCache.Input, subindex, key, value)

    def propagateDirty(self, slot, subindex, roi):
        pass