void MutualInformationRegistration::updateRegistration() {
    if(!isReady())
        return;

    convertVolumes();

    //typedef itk::RegularStepGradientDescentOptimizer OptimizerType;
    typedef itk::VersorRigid3DTransformOptimizer OptimizerType;
    typedef OptimizerType::ScalesType       OptimizerScalesType;
    typedef itk::LinearInterpolateImageFunction< InternalImageType, double             > InterpolatorType;
    typedef itk::MattesMutualInformationImageToImageMetric< InternalImageType, InternalImageType >   MetricType;
    typedef itk::MultiResolutionImageRegistrationMethod< InternalImageType, InternalImageType >   RegistrationType;

    typedef itk::MultiResolutionPyramidImageFilter< InternalImageType, InternalImageType >   FixedImagePyramidType;
    typedef itk::MultiResolutionPyramidImageFilter< InternalImageType, InternalImageType >   MovingImagePyramidType;

    OptimizerType::Pointer      optimizer     = OptimizerType::New();
    InterpolatorType::Pointer   interpolator  = InterpolatorType::New();
    RegistrationType::Pointer   registration  = RegistrationType::New();
    MetricType::Pointer         metric        = MetricType::New();

    FixedImagePyramidType::Pointer fixedImagePyramid = FixedImagePyramidType::New();
    MovingImagePyramidType::Pointer movingImagePyramid = MovingImagePyramidType::New();

    registration->SetOptimizer(optimizer);
    registration->SetTransform(transform_);
    registration->SetInterpolator(interpolator);
    registration->SetMetric(metric);
    registration->SetFixedImagePyramid(fixedImagePyramid);
    registration->SetMovingImagePyramid(movingImagePyramid);

    OptimizerScalesType optimizerScales( transform_->GetNumberOfParameters() );

    float rotScale = 1.0 / 1000.0f;
    optimizerScales[0] = 1.0f;
    optimizerScales[1] = 1.0f;
    optimizerScales[2] = 1.0f;
    optimizerScales[3] = rotScale;
    optimizerScales[4] = rotScale;
    optimizerScales[5] = rotScale;
    optimizer->SetScales( optimizerScales );
    optimizer->SetMaximumStepLength(0.2);
    optimizer->SetMinimumStepLength(0.0001);

    InternalImageType::Pointer fixed = voreenToITK<float>(fixedVolumeFloat_);
    InternalImageType::Pointer moving = voreenToITK<float>(movingVolumeFloat_);
    registration->SetFixedImage(fixed);
    registration->SetMovingImage(moving);
    registration->SetFixedImageRegion( fixed->GetBufferedRegion() );

    registration->SetInitialTransformParameters( transform_->GetParameters() );

    metric->SetNumberOfHistogramBins(numHistogramBins_.get());

    size_t numVoxels = hmul(fixedVolumeFloat_->getDimensions());
    metric->SetNumberOfSpatialSamples(numVoxels * numSamples_.get());

    metric->ReinitializeSeed( 76926294 );

    //// Define whether to calculate the metric derivative by explicitly
    //// computing the derivatives of the joint PDF with respect to the Transform
    //// parameters, or doing it by progressively accumulating contributions from
    //// each bin in the joint PDF.
    metric->SetUseExplicitPDFDerivatives(explicitPDF_.get());

    optimizer->SetNumberOfIterations(numIterations_.get());

    optimizer->SetRelaxationFactor(relaxationFactor_.get());

    // Create the Command observer and register it with the optimizer.
    CommandIterationUpdate::Pointer observer = CommandIterationUpdate::New();
    optimizer->AddObserver( itk::IterationEvent(), observer );

    typedef RegistrationInterfaceCommand<RegistrationType> CommandType;
    CommandType::Pointer command = CommandType::New();
    registration->AddObserver( itk::IterationEvent(), command );

    registration->SetNumberOfLevels(numLevels_.get());

    try
    {
        registration->StartRegistration();
        std::cout << "Optimizer stop condition: " << registration->GetOptimizer()->GetStopConditionDescription() << std::endl;
    }
    catch( itk::ExceptionObject & err )
    {
        std::cout << "ExceptionObject caught !" << std::endl;
        std::cout << err << std::endl;
        //return EXIT_FAILURE;
    }

    ParametersType finalParameters = registration->GetLastTransformParameters();
    transform_->SetParameters(finalParameters);

    unsigned int numberOfIterations = optimizer->GetCurrentIteration();

    double bestValue = optimizer->GetValue();

    // Print out results
    std::cout << "Result = " << std::endl;
    std::cout << " Versor " << finalParameters[0] << " " << finalParameters[1] << " " << finalParameters[2] << std::endl;
    std::cout << " Translation " << finalParameters[1] << " " << finalParameters[4] << " " << finalParameters[5] << std::endl;
    std::cout << " Iterations    = " << numberOfIterations << std::endl;
    std::cout << " Metric value  = " << bestValue          << std::endl;

    invalidate(INVALID_RESULT);
}