//----------------------------------------------------------------------------------
//! Handle field changes of the field \c field.
//----------------------------------------------------------------------------------
void METKSurfaceDistance3D::handleNotification(Field *field) {
    ML_TRACE_IN("METKSurfaceDistance3D::handleNotification(Field *field)");
    if (field == _nearDistance || field == _nearDistanceColor || field == _farDistance || field == _farDistanceColor) {
        if (_nearDistance->getFloatValue() > _farDistance->getFloatValue()) {
            _nearDistance->setFloatValue(_farDistance->getFloatValue());
        }
        if (_nearDistance->getFloatValue() < 0.0f) {
            _nearDistance->setFloatValue(0.0f);
        }
        if (_farDistance->getFloatValue() < 0.0f) {
            _farDistance->setFloatValue(0.0f);
        }
        T_ColorShapeIterator iter;
        for (iter = _colorShapeVec.begin(); iter != _colorShapeVec.end(); iter++) {
            (*iter)->_nearDistance = _nearDistance->getFloatValue();
            (*iter)->_farDistance = _farDistance->getFloatValue();
            float r, g, b;
            _nearDistanceColor->getColorValue(r, g, b);
            (*iter)->_nearDistanceColor.setValue(r, g, b);
            _farDistanceColor->getColorValue(r, g, b);
            (*iter)->_farDistanceColor.setValue(r, g, b);
            (*iter)->compute();
        }
    }

    if (field == getInField(0)) {
        _inputImageIsValid = false;
        _image = getUpdatedInImg(0);

        if (_image) {
            _inImageBox = new SubImgBox(_image->getBoxFromImgExt());
            _inputImageIsValid = true;
            T_ColorShapeIterator iter;
            for (iter = _colorShapeVec.begin(); iter != _colorShapeVec.end(); iter++) {
                (*iter)->compute();
            }

        } else {
            _inputImageIsValid = false;

            if (_inImageBox) {
                delete _inImageBox;
                _inImageBox = 0;
            }
            _inImageBox = NULL;
            _image      = NULL;
        }
    }
    inherited::handleNotification(field);
}
//----------------------------------------------------------------------------------
//! Constructor
//----------------------------------------------------------------------------------
SegmentationEvaluationMetric::SegmentationEvaluationMetric ()
  : BaseOp(2, 0)
{
  ML_TRACE_IN("SegmentationEvaluationMetric::SegmentationEvaluationMetric ()");

  // Suppress calls of handleNotification on field changes to
  // avoid side effects during initialization phase.
  handleNotificationOff();

  // Get reference to the container for parameters/fields.
  FieldContainer &fields = *getFieldContainer();

  // Add fields to the module and set their values.
  // Also attach them to the output images to notify connected modules about changes.

  (_segmentationThresholdFld = fields.addInt("segmentationThreshold"))->setIntValue(0);
  (_referenceThresholdFld = fields.addInt("referenceThreshold"))->setIntValue(0);
  
  (_truePositiveFld = fields.addInt("truePositive"))->setIntValue(0);
  (_trueNegativeFld = fields.addInt("trueNegative"))->setIntValue(0);
  (_falsePositiveFld = fields.addInt("falsePositive"))->setIntValue(0);
  (_falseNegativeFld = fields.addInt("falseNegative"))->setIntValue(0);
  (_sensitivityFld = fields.addDouble("sensitivity"))->setDoubleValue(0.0);
  (_specificityFld = fields.addDouble("specificity"))->setDoubleValue(0.0);
  (_prevalenceFld = fields.addDouble("prevalence"))->setDoubleValue(0.0);
  (_levelOfTestFld = fields.addDouble("levelOfTest"))->setDoubleValue(0.0);
  (_diceSimilarityCoefficientFld = fields.addDouble("diceSimilarityCoefficient"))->setDoubleValue(0.0);
  (_cFactorFld = fields.addDouble("cFactor"))->setDoubleValue(0.0);

  (_isAutoApplyFld = fields.addBool("isAutoApply"))->setBoolValue(false);
  _applyFld = fields.addNotify("apply");

  // Connect input field(s) with output field(s) to notify
  // connected modules if input image(s) change.
  for (int inIdx=0; inIdx < 2; ++inIdx){
    for (int outIdx=0; outIdx < 0; ++outIdx){
      getInField(inIdx)->attachField(getOutField(outIdx));
    }
  }

  // Reactivate calls of handleNotification on field changes.
  handleNotificationOn();

  // Activate inplace data buffers for output outIndex and input inIndex.
  // setOutImgInplace(outIndex, inIndex);

  // Activate page data bypass from input inIdx to output outIdx.
  // Note that the module must still be able to calculate the output image.
  // setBypass(outIndex, inIndex);

  // Activate parallel execution of calcOutSubImage.
  // setThreadSupport(supportMode);
  // with supportMode =
  //   NO_THREAD_SUPPORT                 //! The module is not thread safe at all.
  //   CALC_OUTSUBIMAGE_ON_STD_TYPES     //! calcOutSubImage can be called in parallel for scalar voxel types.
  //   CALC_OUTSUBIMAGE_ON_CARRIER_TYPES //! calcOutSubImage can be called in parallel for carrier voxel types.
  //   CALC_OUTSUBIMAGE_ON_ALL_TYPES     //! calcOutSubImage can be called in parallel for all voxel types.
  // Warning: You should be familiar with multithreading before activating this feature.

  // Specify whether the module can only process standard scalar voxel types or
  // also registered voxel types (vec2, mat2, complexf, Vector, etc.)
  // setVoxelDataTypeSupport(permittedTypes);
  // with permittedTypes =
  //   ONLY_STANDARD_TYPES               //! Only standard scalar voxels are supported.
  //   FULLY_OPERATIONAL                 //! Scalar and registered voxels types are supported.
  //   MINIMUM_OPERATIONAL               //! Scalar and registered voxel types are supported.
  //                                     //! Voxel operators are not used by algorithm.
  //
  // See ML Programming Guide, "Configuring Image Processing Behaviour of the BaseOp"
  // for further details.
}