<commit_before>#ifndef AL_ISCLIENT_H
#define AL_ISCLIENT_H

#include "allocore/al_Allocore.hpp"
#include "allocore/protocol/al_OSC.hpp"

namespace al {

class InterfaceServerClient : public osc::PacketHandler {
 public:
  InterfaceServerClient(const char* serverAddress = "127.0.0.1", int port = 12001,
            int serverPort = 12000);

  virtual ~InterfaceServerClient();

  // application specific name and config
  virtual const char* name();
  virtual const char* interfaceServerConfig();

  // common config used for all interface server apps
  const char* defaultConfig();

  virtual void onMessage(osc::Message& m);

  void connect();
  void disconnect();

  osc::Recv& oscRecv() { return mOSCRecv; }
  osc::Send& oscSend() { return mOSCSend; }

  // default nav and lens, be sure to set these
  // if using a different nav / lens
  // Lens& lens() { return *mLens; }
  void setLens(Lens& l){ mLens=&l; }

  // Nav& nav() { return *mNav; }
  void setNav(Nav& n){ mNav=&n; }

 protected:
  osc::Recv mOSCRecv;
  osc::Send mOSCSend;
  Lens* mLens;
  Nav* mNav;
  double mNavSpeed, mNavTurnSpeed;

};

inline void InterfaceServerClient::onMessage(osc::Message& m) {
  std::cout << "Received: " << m.addressPattern() << std::endl;

  float x;
  if (m.addressPattern() == "/pose") {
    Pose pose;
    m >> pose.pos().x;
    m >> pose.pos().y;
    m >> pose.pos().z;
    m >> pose.quat().x;
    m >> pose.quat().y;
    m >> pose.quat().z;
    m >> pose.quat().w;
    (*mNav).set(pose);
  } else if (m.addressPattern() == "/mx") {
    m >> x;
    (*mNav).moveR(x * mNavSpeed);
  } else if (m.addressPattern() == "/my") {
    m >> x;
    (*mNav).moveU(x * mNavSpeed);
  } else if (m.addressPattern() == "/mz") {
    m >> x;
    (*mNav).moveF(x * -mNavSpeed);
  } else if (m.addressPattern() == "/tx") {
    m >> x;
    (*mNav).spinR(x * -mNavTurnSpeed);
  } else if (m.addressPattern() == "/ty") {
    m >> x;
    (*mNav).spinU(x * -mNavTurnSpeed);
  } else if (m.addressPattern() == "/tz") {
    m >> x;
    (*mNav).spinF(x * -mNavTurnSpeed);
  } else if (m.addressPattern() == "/home") {
    (*mNav).home();
  } else if (m.addressPattern() == "/halt") {
    (*mNav).halt();
  } else if (m.addressPattern() == "/eyeSep") {
    m >> x;
    (*mLens).eyeSep(x);
  } else if (m.addressPattern() == "/near") {
    m >> x;
    (*mLens).near(x);
  } else if (m.addressPattern() == "/far") {
    m >> x;
    (*mLens).far(x);
  } else if (m.addressPattern() == "/focalLength") {
    m >> x;
    (*mLens).focalLength(x);
  } else {
  }
  (*mNav).print();
}

InterfaceServerClient::InterfaceServerClient(const char* deviceServerAddress, int port,
                     int deviceServerPort)
    : mOSCRecv(port),
      mOSCSend(deviceServerPort, deviceServerAddress, 0, 4096) {

  oscRecv().bufferSize(32000);
  oscRecv().handler(*this);

  mNavSpeed = 0.1;
  mNavTurnSpeed = 0.02;
  mNav = new Nav();
  mLens = new Lens();
  (*mNav).smooth(0.8);
  (*mLens).near(0.1);
  (*mLens).far(100);
  (*mLens).focalLength(6.0);
  // (*mLens).eyeSep(0.03);
  (*mLens).eyeSepAuto();
}

inline InterfaceServerClient::~InterfaceServerClient() {
  disconnect();
}

inline void InterfaceServerClient::connect() {
  if (oscSend().opened()){
    oscSend().send("/interface/applicationManager/createApplicationWithText",
                   defaultConfig());
    oscSend().send("/interface/applicationManager/createApplicationWithText",
                   interfaceServerConfig());
  }
}

inline void InterfaceServerClient::disconnect() {
  oscSend().send("/interface/disconnectApplication", "default");
  oscSend().send("/interface/disconnectApplication", name());
}

inline const char* InterfaceServerClient::name() { return "app"; }

inline const char* InterfaceServerClient::interfaceServerConfig() {
  return R"(
      app = {
        name : 'app',
        transports :[ {type : 'osc', port : 12001}, ],
        inputs: {
          test: {min: 0, max: 1},
        },
        mappings: [
          { input: { io:'keyboard', name:' ' }, output:{ io:'app', name:'test' } },
        ]
      }
  )";
}

inline const char* InterfaceServerClient::defaultConfig() {
  return R"(
      var eye=0.2;
      var dd = function(v){
        if(Math.abs(v) < 0.03) return 0.0;
        else return v;
      }
      app = {
        name : 'default',
        transports :[ {type : 'osc', port : 12001}, ],
        inputs: {
          mx: {min: -1, max: 1, },
          my: {min: -1, max: 1, },
          mz: {min: -1, max: 1, },
          tx: {min: -1, max: 1, },
          ty: {min: -1, max: 1, },
          tz: {min: -1, max: 1, },
          home: {min: 0, max: 1, },
          halt: {min: 0, max: 1, },
          eyeSep: {min: 0, max:1 },
          near: {min: 0, max:1 },
          far: {min: 0, max:1 },
          focalLength: {min: 0, max:1 },
        },
        mappings: [
          { input: { io:'keyboard', name:'q' }, output:{ io:'default', name:'home'}, expression:function(v){console.log(v)} },
          { input: { io:'keyboard', name:'w' }, output:{ io:'default', name:'mz'}, },
          { input: { io:'keyboard', name:'a' }, output:{ io:'default', name:'mx'}, expression:function(v){return -v;} },
          { input: { io:'keyboard', name:'s' }, output:{ io:'default', name:'halt'}, },
          { input: { io:'keyboard', name:'x' }, output:{ io:'default', name:'mz'}, expression:function(v){return -v;} },
          { input: { io:'keyboard', name:'d' }, output:{ io:'default', name:'mx'}, },
          { input: { io:'keyboard', name:'i' }, output:{ io:'default', name:'eyeSep'}, expression:function(v){ eye += 0.01; console.log('eyesep: ',eye); return eye; } },
          { input: { io:'keyboard', name:'k' }, output:{ io:'default', name:'eyeSep'}, expression:function(v){ eye -= 0.01; console.log('eyesep: ',eye); return eye; } },

          { input: { io:'Logitech RumblePad 2 USB #1', name:'leftX' }, output:{ io:'default', name:'mx'}, expression:dd },
          { input: { io:'Logitech RumblePad 2 USB #1', name:'leftY' }, output:{ io:'default', name:'mz'}, expression:dd },
          { input: { io:'Logitech RumblePad 2 USB #1', name:'rightX' }, output:{ io:'default', name:'ty'}, expression:dd },
          { input: { io:'Logitech RumblePad 2 USB #1', name:'rightY' }, output:{ io:'default', name:'tx'}, expression:dd },

          { input: { io:'Logitech Cordless RumblePad 2 #1', name:'leftX' }, output:{ io:'default', name:'mx' }, expression:dd },
          { input: { io:'Logitech Cordless RumblePad 2 #1', name:'leftY' }, output:{ io:'default', name:'mz' }, expression:dd },
          { input: { io:'Logitech Cordless RumblePad 2 #1', name:'rightX' }, output:{ io:'default', name:'ty' }, expression:dd },
          { input: { io:'Logitech Cordless RumblePad 2 #1', name:'rightY' }, output:{ io:'default', name:'tx' }, expression:dd },
        ]
      }
  )";
}

}  // al::

#endif
<commit_msg>add handshake to interfaceserverclient<commit_after>#ifndef AL_ISCLIENT_H
#define AL_ISCLIENT_H

#include "allocore/al_Allocore.hpp"
#include "allocore/protocol/al_OSC.hpp"

namespace al {

class InterfaceServerClient : public osc::PacketHandler {
 public:
  InterfaceServerClient(const char* serverAddress = "127.0.0.1", int port = 12001,
            int serverPort = 12000);

  virtual ~InterfaceServerClient();

  // application specific name and config
  virtual const char* name();
  virtual const char* interfaceServerConfig();

  // common config used for all interface server apps
  const char* defaultConfig();

  virtual void onMessage(osc::Message& m);

  void connect();
  void handshake();
  void disconnect();

  osc::Recv& oscRecv() { return mOSCRecv; }
  osc::Send& oscSend() { return mOSCSend; }

  // default nav and lens, be sure to set these
  // if using a different nav / lens
  // Lens& lens() { return *mLens; }
  void setLens(Lens& l){ mLens=&l; }

  // Nav& nav() { return *mNav; }
  void setNav(Nav& n){ mNav=&n; }

 protected:
  osc::Recv mOSCRecv;
  osc::Send mOSCSend;
  Lens* mLens;
  Nav* mNav;
  double mNavSpeed, mNavTurnSpeed;

};

inline void InterfaceServerClient::onMessage(osc::Message& m) {
  std::cout << "Received: " << m.addressPattern() << std::endl;

  float x;
  if (m.addressPattern() == "/pose") {
    Pose pose;
    m >> pose.pos().x;
    m >> pose.pos().y;
    m >> pose.pos().z;
    m >> pose.quat().x;
    m >> pose.quat().y;
    m >> pose.quat().z;
    m >> pose.quat().w;
    (*mNav).set(pose);
  } else if (m.addressPattern() == "/mx") {
    m >> x;
    (*mNav).moveR(x * mNavSpeed);
  } else if (m.addressPattern() == "/my") {
    m >> x;
    (*mNav).moveU(x * mNavSpeed);
  } else if (m.addressPattern() == "/mz") {
    m >> x;
    (*mNav).moveF(x * -mNavSpeed);
  } else if (m.addressPattern() == "/tx") {
    m >> x;
    (*mNav).spinR(x * -mNavTurnSpeed);
  } else if (m.addressPattern() == "/ty") {
    m >> x;
    (*mNav).spinU(x * -mNavTurnSpeed);
  } else if (m.addressPattern() == "/tz") {
    m >> x;
    (*mNav).spinF(x * -mNavTurnSpeed);
  } else if (m.addressPattern() == "/home") {
    (*mNav).home();
  } else if (m.addressPattern() == "/halt") {
    (*mNav).halt();
  } else if (m.addressPattern() == "/eyeSep") {
    m >> x;
    (*mLens).eyeSep(x);
  } else if (m.addressPattern() == "/near") {
    m >> x;
    (*mLens).near(x);
  } else if (m.addressPattern() == "/far") {
    m >> x;
    (*mLens).far(x);
  } else if (m.addressPattern() == "/focalLength") {
    m >> x;
    (*mLens).focalLength(x);
  } else {
  }
  (*mNav).print();
}

InterfaceServerClient::InterfaceServerClient(const char* deviceServerAddress, int port,
                     int deviceServerPort)
    : mOSCRecv(port),
      mOSCSend(deviceServerPort, deviceServerAddress, 0, 4096) {

  oscRecv().bufferSize(32000);
  oscRecv().handler(*this);

  mNavSpeed = 0.1;
  mNavTurnSpeed = 0.02;
  mNav = new Nav();
  mLens = new Lens();
  (*mNav).smooth(0.8);
  (*mLens).near(0.1);
  (*mLens).far(100);
  (*mLens).focalLength(6.0);
  // (*mLens).eyeSep(0.03);
  (*mLens).eyeSepAuto();
}

inline InterfaceServerClient::~InterfaceServerClient() {
  disconnect();
}

inline void InterfaceServerClient::connect() {
  if (oscSend().opened()){
    oscSend().send("/interface/applicationManager/createApplicationWithText",
                   defaultConfig());
    oscSend().send("/interface/applicationManager/createApplicationWithText",
                   interfaceServerConfig());
  }
}

inline void InterfaceServerClient::handshake() {
  if (oscSend().opened()){
    oscSend().send("/interface/handshake",
                   name());
  }
}

inline void InterfaceServerClient::disconnect() {
  oscSend().send("/interface/disconnectApplication", "default");
  oscSend().send("/interface/disconnectApplication", name());
}

inline const char* InterfaceServerClient::name() { return "app"; }

inline const char* InterfaceServerClient::interfaceServerConfig() {
  return R"(
      app = {
        name : 'app',
        transports :[ {type : 'osc', port : 12001}, ],
        inputs: {
          test: {min: 0, max: 1},
        },
        mappings: [
          { input: { io:'keyboard', name:' ' }, output:{ io:'app', name:'test' } },
        ]
      }
  )";
}

inline const char* InterfaceServerClient::defaultConfig() {
  return R"(
      var eye=0.2;
      var dd = function(v){
        if(Math.abs(v) < 0.03) return 0.0;
        else return v;
      }
      app = {
        name : 'default',
        transports :[ {type : 'osc', port : 12001}, ],
        inputs: {
          mx: {min: -1, max: 1, },
          my: {min: -1, max: 1, },
          mz: {min: -1, max: 1, },
          tx: {min: -1, max: 1, },
          ty: {min: -1, max: 1, },
          tz: {min: -1, max: 1, },
          home: {min: 0, max: 1, },
          halt: {min: 0, max: 1, },
          eyeSep: {min: 0, max:1 },
          near: {min: 0, max:1 },
          far: {min: 0, max:1 },
          focalLength: {min: 0, max:1 },
        },
        mappings: [
          { input: { io:'keyboard', name:'q' }, output:{ io:'default', name:'home'}, expression:function(v){console.log(v)} },
          { input: { io:'keyboard', name:'w' }, output:{ io:'default', name:'mz'}, },
          { input: { io:'keyboard', name:'a' }, output:{ io:'default', name:'mx'}, expression:function(v){return -v;} },
          { input: { io:'keyboard', name:'s' }, output:{ io:'default', name:'halt'}, },
          { input: { io:'keyboard', name:'x' }, output:{ io:'default', name:'mz'}, expression:function(v){return -v;} },
          { input: { io:'keyboard', name:'d' }, output:{ io:'default', name:'mx'}, },
          { input: { io:'keyboard', name:'i' }, output:{ io:'default', name:'eyeSep'}, expression:function(v){ eye += 0.01; console.log('eyesep: ',eye); return eye; } },
          { input: { io:'keyboard', name:'k' }, output:{ io:'default', name:'eyeSep'}, expression:function(v){ eye -= 0.01; console.log('eyesep: ',eye); return eye; } },

          { input: { io:'Logitech RumblePad 2 USB #1', name:'leftX' }, output:{ io:'default', name:'mx'}, expression:dd },
          { input: { io:'Logitech RumblePad 2 USB #1', name:'leftY' }, output:{ io:'default', name:'mz'}, expression:dd },
          { input: { io:'Logitech RumblePad 2 USB #1', name:'rightX' }, output:{ io:'default', name:'ty'}, expression:dd },
          { input: { io:'Logitech RumblePad 2 USB #1', name:'rightY' }, output:{ io:'default', name:'tx'}, expression:dd },

          { input: { io:'Logitech Cordless RumblePad 2 #1', name:'leftX' }, output:{ io:'default', name:'mx' }, expression:dd },
          { input: { io:'Logitech Cordless RumblePad 2 #1', name:'leftY' }, output:{ io:'default', name:'mz' }, expression:dd },
          { input: { io:'Logitech Cordless RumblePad 2 #1', name:'rightX' }, output:{ io:'default', name:'ty' }, expression:dd },
          { input: { io:'Logitech Cordless RumblePad 2 #1', name:'rightY' }, output:{ io:'default', name:'tx' }, expression:dd },
        ]
      }
  )";
}

}  // al::

#endif
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkAzimuthElevationToCartesianTransformTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 2001 Insight Consortium
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * The name of the Insight Consortium, nor the names of any consortium members,
   nor of any contributors, may be used to endorse or promote products derived
   from this software without specific prior written permission.

  * Modified source versions must be plainly marked as such, and must not be
    misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/

#include <iostream>

#include "itkAzimuthElevationToCartesianTransform.h"

typedef  itk::Point<double,3>   PointType;

void PrintPoint( const PointType & p )
{
  for( unsigned int i=0; i<PointType::PointDimension; i++)
  {
    std::cout << p[i] << ", ";
  }
  std::cout << std::endl;
}

int main(
    int argc,
    char *argv[])
{

    const double ACCEPTABLE_ERROR = 1E-10;

    typedef itk::AzimuthElevationToCartesianTransform<> AzimuthElevationToCartesianTransformType;

    AzimuthElevationToCartesianTransformType::Pointer transform = AzimuthElevationToCartesianTransformType::New();
    transform->SetAzimuthElevationToCartesianParameters(1.0,5.0,45.0,45.0);
    PointType p;
    p[0] = 3;
    p[1] = 3;
    p[2] = 25;

    std::cout<< "original values of (theta,phi,r) p = "<<std::endl;
    PrintPoint(p);

    transform->SetForwardAzimuthElevationToCartesian();

    PointType answer = transform->TransformPoint(p);
    PrintPoint(answer);

    PointType answerBackwards = transform->BackTransformPoint(answer);
    PrintPoint(answerBackwards);

    transform->SetForwardCartesianToAzimuthElevation();
    PointType reverseDirectionAnswer = transform->BackTransformPoint(answerBackwards);
    PrintPoint(reverseDirectionAnswer);

    PointType reverseDirectionAnswerBackwards = transform->TransformPoint(reverseDirectionAnswer);
    PrintPoint(reverseDirectionAnswerBackwards);
    transform->Print(std::cout);

    bool same=true;
    for (unsigned int i=0; i < p.PointDimension && same; i++)
      {
      same = ((abs(p[i] - answerBackwards[i]) < ACCEPTABLE_ERROR) &&
      (abs(p[i] - reverseDirectionAnswerBackwards[i]) < ACCEPTABLE_ERROR) &&
      (abs(answer[i] - reverseDirectionAnswer[i]) < ACCEPTABLE_ERROR)) ;
      }
    if (!same)
      {
      std::cout << "itkAzimuthElevationToCartesianTransformTest failed" <<std::endl;
      return EXIT_FAILURE;
      }
    std::cout << "itkAzimuthElevationToCartesianTransformTest passed" <<std::endl;
    return EXIT_SUCCESS;
}
<commit_msg>ERR: warnings.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkAzimuthElevationToCartesianTransformTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 2001 Insight Consortium
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * The name of the Insight Consortium, nor the names of any consortium members,
   nor of any contributors, may be used to endorse or promote products derived
   from this software without specific prior written permission.

  * Modified source versions must be plainly marked as such, and must not be
    misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/

#include <iostream>

#include "itkAzimuthElevationToCartesianTransform.h"

typedef  itk::Point<double,3>   PointType;

void PrintPoint( const PointType & p )
{
  for( unsigned int i=0; i<PointType::PointDimension; i++)
  {
    std::cout << p[i] << ", ";
  }
  std::cout << std::endl;
}

int main(
    int argc,
    char *argv[])
{

    const double ACCEPTABLE_ERROR = 1E-10;

    typedef itk::AzimuthElevationToCartesianTransform<> AzimuthElevationToCartesianTransformType;

    AzimuthElevationToCartesianTransformType::Pointer transform = AzimuthElevationToCartesianTransformType::New();
    transform->SetAzimuthElevationToCartesianParameters(1.0,5.0,45,45);
    PointType p;
    p[0] = 3;
    p[1] = 3;
    p[2] = 25;

    std::cout<< "original values of (theta,phi,r) p = "<<std::endl;
    PrintPoint(p);

    transform->SetForwardAzimuthElevationToCartesian();

    PointType answer = transform->TransformPoint(p);
    PrintPoint(answer);

    PointType answerBackwards = transform->BackTransformPoint(answer);
    PrintPoint(answerBackwards);

    transform->SetForwardCartesianToAzimuthElevation();
    PointType reverseDirectionAnswer = transform->BackTransformPoint(answerBackwards);
    PrintPoint(reverseDirectionAnswer);

    PointType reverseDirectionAnswerBackwards = transform->TransformPoint(reverseDirectionAnswer);
    PrintPoint(reverseDirectionAnswerBackwards);
    transform->Print(std::cout);

    bool same=true;
    for (unsigned int i=0; i < p.PointDimension && same; i++)
      {
      same = ((abs(p[i] - answerBackwards[i]) < ACCEPTABLE_ERROR) &&
      (abs(p[i] - reverseDirectionAnswerBackwards[i]) < ACCEPTABLE_ERROR) &&
      (abs(answer[i] - reverseDirectionAnswer[i]) < ACCEPTABLE_ERROR)) ;
      }
    if (!same)
      {
      std::cout << "itkAzimuthElevationToCartesianTransformTest failed" <<std::endl;
      return EXIT_FAILURE;
      }
    std::cout << "itkAzimuthElevationToCartesianTransformTest passed" <<std::endl;
    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    DeformableRegistration2.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

// Software Guide : BeginLatex
//
// This example demostrates how to use the ``demons'' algorithm to deformably
// register two images. The first step is to include the header files.
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "itkDemonsRegistrationFilter.h"
#include "itkHistogramMatchingImageFilter.h"
#include "itkCastImageFilter.h"
#include "itkWarpImageFilter.h"
#include "itkLinearInterpolateImageFunction.h"
// Software Guide : EndCodeSnippet

//  The following section of code implements a Command observer
//  that will monitor the evolution of the registration process.
//
  class CommandIterationUpdate : public itk::Command
  {
  public:
    typedef  CommandIterationUpdate   Self;
    typedef  itk::Command             Superclass;
    typedef  itk::SmartPointer<CommandIterationUpdate>  Pointer;
    itkNewMacro( CommandIterationUpdate );
  protected:
    CommandIterationUpdate() {};

    typedef itk::Image< float, 2 > InternalImageType;
    typedef itk::Vector< float, 2 >    VectorPixelType;
    typedef itk::Image<  VectorPixelType, 2 > DeformationFieldType;

    typedef itk::DemonsRegistrationFilter<
                                InternalImageType,
                                InternalImageType,
                                DeformationFieldType>   RegistrationFilterType;

  public:

    void Execute(itk::Object *caller, const itk::EventObject & event)
      {
        Execute( (const itk::Object *)caller, event);
      }

    void Execute(const itk::Object * object, const itk::EventObject & event)
      {
         const RegistrationFilterType * filter =
          dynamic_cast< const RegistrationFilterType * >( object );
        if( typeid( event ) != typeid( itk::IterationEvent ) )
          {
          return;
          }
        std::cout << filter->GetMetric() << std::endl;
      }
  };

int main( int argc, char *argv[] )
{
  if( argc < 4 )
    {
    std::cerr << "Missing Parameters " << std::endl;
    std::cerr << "Usage: " << argv[0];
    std::cerr << " fixedImageFile movingImageFile ";
    std::cerr << " outputImageFile " << std::endl;
    std::cerr << " [outputDeformationFieldFile] " << std::endl;
    return 1;
    }

  // Software Guide : BeginLatex
  //
  // Second, we declare the types of the images.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  const unsigned int Dimension = 2;
  typedef unsigned short PixelType;

  typedef itk::Image< PixelType, Dimension >  FixedImageType;
  typedef itk::Image< PixelType, Dimension >  MovingImageType;
  // Software Guide : EndCodeSnippet

  // Set up the file readers
  typedef itk::ImageFileReader< FixedImageType  > FixedImageReaderType;
  typedef itk::ImageFileReader< MovingImageType > MovingImageReaderType;

  FixedImageReaderType::Pointer fixedImageReader   = FixedImageReaderType::New();
  MovingImageReaderType::Pointer movingImageReader = MovingImageReaderType::New();

  fixedImageReader->SetFileName( argv[1] );
  movingImageReader->SetFileName( argv[2] );

  // Software Guide : BeginLatex
  //
  // Image file readers are set up in a similar fashion to previous examples.
  // To support the re-mapping of the moving image intensity, we declare an
  // internal image type with a floating point pixel type and cast the input
  // images to the internal image type.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef float InternalPixelType;
  typedef itk::Image< InternalPixelType, Dimension > InternalImageType;
  typedef itk::CastImageFilter< FixedImageType,
                                InternalImageType > FixedImageCasterType;
  typedef itk::CastImageFilter< MovingImageType,
                                InternalImageType > MovingImageCasterType;

  FixedImageCasterType::Pointer fixedImageCaster   = FixedImageCasterType::New();
  MovingImageCasterType::Pointer movingImageCaster = MovingImageCasterType::New();

  fixedImageCaster->SetInput( fixedImageReader->GetOutput() );
  movingImageCaster->SetInput( movingImageReader->GetOutput() );
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // The demons algorithm relies on the assumption that pixels representing the
  // same homologous point on an object have the same intensity on both the
  // fixed and moving images to be registered. In this example, we will
  // preprocess the moving image to match the intensity between the images
  // using the \doxygen{HistogramMatchingImageFilter}.
  //
  // \index{itk::HistogramMatchingImageFilter}
  //
  // The basic idea is to match the histograms of the two images at a user-specified number of quantile values. For robustness, the histograms are
  // matched so that the background pixels are excluded from both histograms.
  // For MR images, a simple procedure is to exclude all gray values that are
  // smaller than the mean gray value of the image.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef itk::HistogramMatchingImageFilter<
                                    InternalImageType,
                                    InternalImageType >   MatchingFilterType;
  MatchingFilterType::Pointer matcher = MatchingFilterType::New();
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // For this example, we set the moving image as the source or input image and
  // the fixed image as the reference image.
  //
  // \index{itk::HistogramMatchingImageFilter!SetInput()}
  // \index{itk::HistogramMatchingImageFilter!SetSourceImage()}
  // \index{itk::HistogramMatchingImageFilter!SetReferenceImage()}
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  matcher->SetInput( movingImageCaster->GetOutput() );
  matcher->SetReferenceImage( fixedImageCaster->GetOutput() );
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // We then select the number of bins to represent the histograms and the
  // number of points or quantile values where the histogram is to be
  // matched.
  //
  // \index{itk::HistogramMatchingImageFilter!SetNumberOfHistogramLevels()}
  // \index{itk::HistogramMatchingImageFilter!SetNumberOfMatchPoints()}
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  matcher->SetNumberOfHistogramLevels( 1024 );
  matcher->SetNumberOfMatchPoints( 7 );
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // Simple background extraction is done by thresholding at the mean
  // intensity.
  //
  // \index{itk::HistogramMatchingImageFilter!ThresholdAtMeanIntensityOn()}
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  matcher->ThresholdAtMeanIntensityOn();
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // In the \doxygen{DemonsRegistrationFilter}, the deformation field is
  // represented as an image whose pixels are floating point vectors.
  //
  // \index{itk::DemonsRegistrationFilter}
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef itk::Vector< float, Dimension >    VectorPixelType;
  typedef itk::Image<  VectorPixelType, Dimension > DeformationFieldType;
  typedef itk::DemonsRegistrationFilter<
                                InternalImageType,
                                InternalImageType,
                                DeformationFieldType>   RegistrationFilterType;
  RegistrationFilterType::Pointer filter = RegistrationFilterType::New();
  // Software Guide : EndCodeSnippet

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

  // Software Guide : BeginLatex
  //
  // The input fixed image is simply the output of the fixed image casting
  // filter.  The input moving image is the output of the histogram matching
  // filter.
  //
  // \index{itk::DemonsRegistrationFilter!SetFixedImage()}
  // \index{itk::DemonsRegistrationFilter!SetMovingImage()}
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filter->SetFixedImage( fixedImageCaster->GetOutput() );
  filter->SetMovingImage( matcher->GetOutput() );
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // The demons registration filter has two parameters: the number of
  // iterations to be performed and the standard deviation of the Gaussian
  // smoothing kernel to be applied to the deformation field after each
  // iteration.
  // \index{itk::DemonsRegistrationFilter!SetNumberOfIterations()}
  // \index{itk::DemonsRegistrationFilter!SetStandardDeviations()}
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filter->SetNumberOfIterations( 150 );
  filter->SetStandardDeviations( 1.0 );
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // The registration algorithm is triggered by updating the filter. The
  // filter output is the computed deformation field.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filter->Update();
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // The \doxygen{WarpImageFilter} can be used to warp the moving image with
  // the output deformation field. Like the \doxygen{ResampleImageFilter},
  // the WarpImageFilter requires the specification of the input image to be
  // resampled, an input image interpolator, and the output image spacing and
  // origin.
  //
  // \index{itk::WarpImageFilter}
  // \index{itk::WarpImageFilter!SetInput()}
  // \index{itk::WarpImageFilter!SetInterpolator()}
  // \index{itk::WarpImageFilter!SetOutputSpacing()}
  // \index{itk::WarpImageFilter!SetOutputOrigin()}
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef itk::WarpImageFilter<
                          MovingImageType,
                          MovingImageType,
                          DeformationFieldType  >     WarperType;
  typedef itk::LinearInterpolateImageFunction<
                                   MovingImageType,
                                   double          >  InterpolatorType;
  WarperType::Pointer warper = WarperType::New();
  InterpolatorType::Pointer interpolator = InterpolatorType::New();
  FixedImageType::Pointer fixedImage = fixedImageReader->GetOutput();

  warper->SetInput( movingImageReader->GetOutput() );
  warper->SetInterpolator( interpolator );
  warper->SetOutputSpacing( fixedImage->GetSpacing() );
  warper->SetOutputOrigin( fixedImage->GetOrigin() );
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // Unlike the ResampleImageFilter, the WarpImageFilter
  // warps or transform the input image with respect to the deformation field
  // represented by an image of vectors.  The resulting warped or resampled
  // image is written to file as per previous examples.
  //
  // \index{itk::WarpImageFilter!SetDeformationField()}
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  warper->SetDeformationField( filter->GetOutput() );
  // Software Guide : EndCodeSnippet

  // Write warped image out to file
  typedef  unsigned char  OutputPixelType;
  typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
  typedef itk::CastImageFilter<
                        MovingImageType,
                        OutputImageType > CastFilterType;
  typedef itk::ImageFileWriter< OutputImageType >  WriterType;

  WriterType::Pointer      writer =  WriterType::New();
  CastFilterType::Pointer  caster =  CastFilterType::New();

  writer->SetFileName( argv[3] );

  caster->SetInput( warper->GetOutput() );
  writer->SetInput( caster->GetOutput()   );
  writer->Update();

  // Software Guide : BeginLatex
  //
  // Let's execute this example using the rat lung data from the previous example.
  // The associated data files can be found in \code{Examples/Data}:
  //
  // \begin{itemize}
  // \item \code{RatLungSlice1.mha}
  // \item \code{RatLungSlice2.mha}
  // \end{itemize}
  //
  // \begin{figure} \center
  // \includegraphics[width=0.44\textwidth]{DeformableRegistration2CheckerboardBefore.eps}
  // \includegraphics[width=0.44\textwidth]{DeformableRegistration2CheckerboardAfter.eps}
  // \itkcaption[Demon's deformable registration output]{Checkerboard comparisons
  // before and after demons-based deformable registration.}
  // \label{fig:DeformableRegistration2Output}
  // \end{figure}
  //
  // The result of the demons-based deformable registration is presented in
  // Figure \ref{fig:DeformableRegistration2Output}. The checkerboard
  // comparision shows that the algorithm was able to recover the misalignment
  // due to expiration.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginLatex
  //
  // It may be also desirable to write the deformation field as an image of
  // vectors.  This can be done with the following code.
  //
  // Software Guide : EndLatex

  if( argc > 4 ) // if a fourth line argument has been provided...
    {

  // Software Guide : BeginCodeSnippet
  typedef itk::ImageFileWriter< DeformationFieldType > FieldWriterType;
  FieldWriterType::Pointer fieldWriter = FieldWriterType::New();
  fieldWriter->SetFileName( argv[4] );
  fieldWriter->SetInput( filter->GetOutput() );

  fieldWriter->Update();
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // Note that the file format used for writing the deformation field must be
  // capable of representing multiple components per pixel. This is the case
  // for the MetaImage and VTK fileformats for example.
  //
  // Software Guide : EndLatex

    }

  return 0;
}

<commit_msg>ENH: Added code for saving the deformation field in a vector image file.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    DeformableRegistration2.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

#include "itkImageRegionIterator.h"

// Software Guide : BeginLatex
//
// This example demostrates how to use the ``demons'' algorithm to deformably
// register two images. The first step is to include the header files.
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "itkDemonsRegistrationFilter.h"
#include "itkHistogramMatchingImageFilter.h"
#include "itkCastImageFilter.h"
#include "itkWarpImageFilter.h"
#include "itkLinearInterpolateImageFunction.h"
// Software Guide : EndCodeSnippet

//  The following section of code implements a Command observer
//  that will monitor the evolution of the registration process.
//
  class CommandIterationUpdate : public itk::Command
  {
  public:
    typedef  CommandIterationUpdate   Self;
    typedef  itk::Command             Superclass;
    typedef  itk::SmartPointer<CommandIterationUpdate>  Pointer;
    itkNewMacro( CommandIterationUpdate );
  protected:
    CommandIterationUpdate() {};

    typedef itk::Image< float, 2 > InternalImageType;
    typedef itk::Vector< float, 2 >    VectorPixelType;
    typedef itk::Image<  VectorPixelType, 2 > DeformationFieldType;

    typedef itk::DemonsRegistrationFilter<
                                InternalImageType,
                                InternalImageType,
                                DeformationFieldType>   RegistrationFilterType;

  public:

    void Execute(itk::Object *caller, const itk::EventObject & event)
      {
        Execute( (const itk::Object *)caller, event);
      }

    void Execute(const itk::Object * object, const itk::EventObject & event)
      {
         const RegistrationFilterType * filter =
          dynamic_cast< const RegistrationFilterType * >( object );
        if( typeid( event ) != typeid( itk::IterationEvent ) )
          {
          return;
          }
        std::cout << filter->GetMetric() << std::endl;
      }
  };

int main( int argc, char *argv[] )
{
  if( argc < 4 )
    {
    std::cerr << "Missing Parameters " << std::endl;
    std::cerr << "Usage: " << argv[0];
    std::cerr << " fixedImageFile movingImageFile ";
    std::cerr << " outputImageFile " << std::endl;
    std::cerr << " [outputDeformationFieldFile] " << std::endl;
    return 1;
    }

  // Software Guide : BeginLatex
  //
  // Second, we declare the types of the images.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  const unsigned int Dimension = 2;
  typedef unsigned short PixelType;

  typedef itk::Image< PixelType, Dimension >  FixedImageType;
  typedef itk::Image< PixelType, Dimension >  MovingImageType;
  // Software Guide : EndCodeSnippet

  // Set up the file readers
  typedef itk::ImageFileReader< FixedImageType  > FixedImageReaderType;
  typedef itk::ImageFileReader< MovingImageType > MovingImageReaderType;

  FixedImageReaderType::Pointer fixedImageReader   = FixedImageReaderType::New();
  MovingImageReaderType::Pointer movingImageReader = MovingImageReaderType::New();

  fixedImageReader->SetFileName( argv[1] );
  movingImageReader->SetFileName( argv[2] );

  // Software Guide : BeginLatex
  //
  // Image file readers are set up in a similar fashion to previous examples.
  // To support the re-mapping of the moving image intensity, we declare an
  // internal image type with a floating point pixel type and cast the input
  // images to the internal image type.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef float InternalPixelType;
  typedef itk::Image< InternalPixelType, Dimension > InternalImageType;
  typedef itk::CastImageFilter< FixedImageType,
                                InternalImageType > FixedImageCasterType;
  typedef itk::CastImageFilter< MovingImageType,
                                InternalImageType > MovingImageCasterType;

  FixedImageCasterType::Pointer fixedImageCaster   = FixedImageCasterType::New();
  MovingImageCasterType::Pointer movingImageCaster = MovingImageCasterType::New();

  fixedImageCaster->SetInput( fixedImageReader->GetOutput() );
  movingImageCaster->SetInput( movingImageReader->GetOutput() );
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // The demons algorithm relies on the assumption that pixels representing the
  // same homologous point on an object have the same intensity on both the
  // fixed and moving images to be registered. In this example, we will
  // preprocess the moving image to match the intensity between the images
  // using the \doxygen{HistogramMatchingImageFilter}.
  //
  // \index{itk::HistogramMatchingImageFilter}
  //
  // The basic idea is to match the histograms of the two images at a user-specified number of quantile values. For robustness, the histograms are
  // matched so that the background pixels are excluded from both histograms.
  // For MR images, a simple procedure is to exclude all gray values that are
  // smaller than the mean gray value of the image.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef itk::HistogramMatchingImageFilter<
                                    InternalImageType,
                                    InternalImageType >   MatchingFilterType;
  MatchingFilterType::Pointer matcher = MatchingFilterType::New();
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // For this example, we set the moving image as the source or input image and
  // the fixed image as the reference image.
  //
  // \index{itk::HistogramMatchingImageFilter!SetInput()}
  // \index{itk::HistogramMatchingImageFilter!SetSourceImage()}
  // \index{itk::HistogramMatchingImageFilter!SetReferenceImage()}
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  matcher->SetInput( movingImageCaster->GetOutput() );
  matcher->SetReferenceImage( fixedImageCaster->GetOutput() );
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // We then select the number of bins to represent the histograms and the
  // number of points or quantile values where the histogram is to be
  // matched.
  //
  // \index{itk::HistogramMatchingImageFilter!SetNumberOfHistogramLevels()}
  // \index{itk::HistogramMatchingImageFilter!SetNumberOfMatchPoints()}
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  matcher->SetNumberOfHistogramLevels( 1024 );
  matcher->SetNumberOfMatchPoints( 7 );
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // Simple background extraction is done by thresholding at the mean
  // intensity.
  //
  // \index{itk::HistogramMatchingImageFilter!ThresholdAtMeanIntensityOn()}
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  matcher->ThresholdAtMeanIntensityOn();
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // In the \doxygen{DemonsRegistrationFilter}, the deformation field is
  // represented as an image whose pixels are floating point vectors.
  //
  // \index{itk::DemonsRegistrationFilter}
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef itk::Vector< float, Dimension >    VectorPixelType;
  typedef itk::Image<  VectorPixelType, Dimension > DeformationFieldType;
  typedef itk::DemonsRegistrationFilter<
                                InternalImageType,
                                InternalImageType,
                                DeformationFieldType>   RegistrationFilterType;
  RegistrationFilterType::Pointer filter = RegistrationFilterType::New();
  // Software Guide : EndCodeSnippet

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

  // Software Guide : BeginLatex
  //
  // The input fixed image is simply the output of the fixed image casting
  // filter.  The input moving image is the output of the histogram matching
  // filter.
  //
  // \index{itk::DemonsRegistrationFilter!SetFixedImage()}
  // \index{itk::DemonsRegistrationFilter!SetMovingImage()}
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filter->SetFixedImage( fixedImageCaster->GetOutput() );
  filter->SetMovingImage( matcher->GetOutput() );
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // The demons registration filter has two parameters: the number of
  // iterations to be performed and the standard deviation of the Gaussian
  // smoothing kernel to be applied to the deformation field after each
  // iteration.
  // \index{itk::DemonsRegistrationFilter!SetNumberOfIterations()}
  // \index{itk::DemonsRegistrationFilter!SetStandardDeviations()}
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filter->SetNumberOfIterations( 150 );
  filter->SetStandardDeviations( 1.0 );
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // The registration algorithm is triggered by updating the filter. The
  // filter output is the computed deformation field.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filter->Update();
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // The \doxygen{WarpImageFilter} can be used to warp the moving image with
  // the output deformation field. Like the \doxygen{ResampleImageFilter},
  // the WarpImageFilter requires the specification of the input image to be
  // resampled, an input image interpolator, and the output image spacing and
  // origin.
  //
  // \index{itk::WarpImageFilter}
  // \index{itk::WarpImageFilter!SetInput()}
  // \index{itk::WarpImageFilter!SetInterpolator()}
  // \index{itk::WarpImageFilter!SetOutputSpacing()}
  // \index{itk::WarpImageFilter!SetOutputOrigin()}
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef itk::WarpImageFilter<
                          MovingImageType,
                          MovingImageType,
                          DeformationFieldType  >     WarperType;
  typedef itk::LinearInterpolateImageFunction<
                                   MovingImageType,
                                   double          >  InterpolatorType;
  WarperType::Pointer warper = WarperType::New();
  InterpolatorType::Pointer interpolator = InterpolatorType::New();
  FixedImageType::Pointer fixedImage = fixedImageReader->GetOutput();

  warper->SetInput( movingImageReader->GetOutput() );
  warper->SetInterpolator( interpolator );
  warper->SetOutputSpacing( fixedImage->GetSpacing() );
  warper->SetOutputOrigin( fixedImage->GetOrigin() );
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // Unlike the ResampleImageFilter, the WarpImageFilter
  // warps or transform the input image with respect to the deformation field
  // represented by an image of vectors.  The resulting warped or resampled
  // image is written to file as per previous examples.
  //
  // \index{itk::WarpImageFilter!SetDeformationField()}
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  warper->SetDeformationField( filter->GetOutput() );
  // Software Guide : EndCodeSnippet

  // Write warped image out to file
  typedef  unsigned char  OutputPixelType;
  typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
  typedef itk::CastImageFilter<
                        MovingImageType,
                        OutputImageType > CastFilterType;
  typedef itk::ImageFileWriter< OutputImageType >  WriterType;

  WriterType::Pointer      writer =  WriterType::New();
  CastFilterType::Pointer  caster =  CastFilterType::New();

  writer->SetFileName( argv[3] );

  caster->SetInput( warper->GetOutput() );
  writer->SetInput( caster->GetOutput()   );
  writer->Update();

  // Software Guide : BeginLatex
  //
  // Let's execute this example using the rat lung data from the previous example.
  // The associated data files can be found in \code{Examples/Data}:
  //
  // \begin{itemize}
  // \item \code{RatLungSlice1.mha}
  // \item \code{RatLungSlice2.mha}
  // \end{itemize}
  //
  // \begin{figure} \center
  // \includegraphics[width=0.44\textwidth]{DeformableRegistration2CheckerboardBefore.eps}
  // \includegraphics[width=0.44\textwidth]{DeformableRegistration2CheckerboardAfter.eps}
  // \itkcaption[Demon's deformable registration output]{Checkerboard comparisons
  // before and after demons-based deformable registration.}
  // \label{fig:DeformableRegistration2Output}
  // \end{figure}
  //
  // The result of the demons-based deformable registration is presented in
  // Figure \ref{fig:DeformableRegistration2Output}. The checkerboard
  // comparision shows that the algorithm was able to recover the misalignment
  // due to expiration.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginLatex
  //
  // It may be also desirable to write the deformation field as an image of
  // vectors.  This can be done with the following code.
  //
  // Software Guide : EndLatex

  if( argc > 4 ) // if a fourth line argument has been provided...
    {

  // Software Guide : BeginCodeSnippet
  typedef itk::ImageFileWriter< DeformationFieldType > FieldWriterType;
  FieldWriterType::Pointer fieldWriter = FieldWriterType::New();
  fieldWriter->SetFileName( argv[4] );
  fieldWriter->SetInput( filter->GetOutput() );

  fieldWriter->Update();
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // Note that the file format used for writing the deformation field must be
  // capable of representing multiple components per pixel. This is the case
  // for the MetaImage and VTK fileformats for example.
  //
  // Software Guide : EndLatex

    }

  if( argc > 5 ) // if a fifth line argument has been provided...
    {

  typedef DeformationFieldType  VectorImage2DType;
  typedef DeformationFieldType::PixelType Vector2DType;

  VectorImage2DType::ConstPointer vectorImage2D = filter->GetOutput();

  VectorImage2DType::RegionType  region2D = vectorImage2D->GetBufferedRegion();
  VectorImage2DType::IndexType   index2D  = region2D.GetIndex();
  VectorImage2DType::SizeType    size2D   = region2D.GetSize();

  typedef itk::Vector< float,       3 >  Vector3DType;
  typedef itk::Image< Vector3DType, 3 >  VectorImage3DType;

  typedef itk::ImageFileWriter< VectorImage3DType > WriterType;

  WriterType::Pointer writer3D = WriterType::New();

  VectorImage3DType::Pointer vectorImage3D = VectorImage3DType::New();

  VectorImage3DType::RegionType  region3D;
  VectorImage3DType::IndexType   index3D;
  VectorImage3DType::SizeType    size3D;

  index3D[0] = index2D[0];
  index3D[1] = index2D[1];
  index3D[2] = 0;

  size3D[0]  = size2D[0];
  size3D[1]  = size2D[1];
  size3D[2]  = 1;

  region3D.SetSize( size3D );
  region3D.SetIndex( index3D );

  vectorImage3D->SetRegions( region3D );
  vectorImage3D->Allocate();

  typedef itk::ImageRegionConstIterator< VectorImage2DType > Iterator2DType;

  typedef itk::ImageRegionIterator< VectorImage3DType > Iterator3DType;

  Iterator2DType  it2( vectorImage2D, region2D );
  Iterator3DType  it3( vectorImage3D, region3D );

  it2.GoToBegin();
  it3.GoToBegin();

  Vector2DType vector2D;
  Vector3DType vector3D;

  vector3D[2] = 0; // set Z component to zero.

  while( !it2.IsAtEnd() )
    {
    vector2D = it2.Get();
    vector3D[0] = vector2D[0];
    vector3D[1] = vector2D[1];
    it3.Set( vector3D );
    ++it2;
    ++it3;
    }

  writer3D->SetInput( vectorImage3D );

  writer3D->SetFileName( argv[5] );

  try
    {
    writer3D->Update();
    }
  catch( itk::ExceptionObject & excp )
    {
    std::cerr << excp << std::endl;
    return -1;
    }

  }

  return 0;
}

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    DeformableRegistration7.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

// Software Guide : BeginLatex
//
// This example illustrates the use of the \doxygen{BSplineDeformableTransform}
// class for performing registration of two $3D$ images. The example code is
// for the most part identical to the code presented in
// Section~\ref{sec:DeformableRegistration}.  The major difference is that this
// example we set the image dimension to 3 and replace the
// \doxygen{LBFGSOptimizer} optimizer with the \doxygen{LBFGSBOptimizer}.  This
// optimizer is more appropriate for performing optimization in a parametric
// spaces of higher dimensions.
//
//
// \index{itk::BSplineDeformableTransform}
// \index{itk::BSplineDeformableTransform!DeformableRegistration}
// \index{itk::LBFGSOptimizer}
//
//
// Software Guide : EndLatex

#include "itkImageRegistrationMethod.h"
#include "itkMeanSquaresImageToImageMetric.h"
#include "itkLinearInterpolateImageFunction.h"
#include "itkImage.h"

#include "itkTimeProbesCollectorBase.h"

//  Software Guide : BeginLatex
//
//  The following are the most relevant headers to this example.
//
//  \index{itk::BSplineDeformableTransform!header}
//  \index{itk::LBFGSOptimizer!header}
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "itkBSplineDeformableTransform.h"
#include "itkLBFGSBOptimizer.h"
// Software Guide : EndCodeSnippet

//  Software Guide : BeginLatex
//
//  The parameter space of the \code{BSplineDeformableTransform} is composed by
//  the set of all the deformations associated with the nodes of the BSpline
//  grid.  This large number of parameters makes possible to represent a wide
//  variety of deformations, but it also has the price of requiring a
//  significant amount of computation time.
//
//  \index{itk::BSplineDeformableTransform!header}
//
//  Software Guide : EndLatex

#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

#include "itkResampleImageFilter.h"
#include "itkCastImageFilter.h"
#include "itkSquaredDifferenceImageFilter.h"

//  The following section of code implements a Command observer
//  used to monitor the evolution of the registration process.
//
#include "itkCommand.h"
class CommandIterationUpdate : public itk::Command
{
public:
  typedef  CommandIterationUpdate   Self;
  typedef  itk::Command             Superclass;
  typedef itk::SmartPointer<Self>  Pointer;
  itkNewMacro( Self );
protected:
  CommandIterationUpdate() {};
public:
  typedef itk::LBFGSBOptimizer     OptimizerType;
  typedef   const OptimizerType   *    OptimizerPointer;

  void Execute(itk::Object *caller, const itk::EventObject & event)
    {
      Execute( (const itk::Object *)caller, event);
    }

  void Execute(const itk::Object * object, const itk::EventObject & event)
    {
      OptimizerPointer optimizer =
        dynamic_cast< OptimizerPointer >( object );
      if( !(itk::IterationEvent().CheckEvent( &event )) )
        {
        return;
        }
      std::cout << optimizer->GetCurrentIteration() << "   ";
      std::cout << optimizer->GetValue() << "   ";
      std::cout << optimizer->GetInfinityNormOfProjectedGradient() << std::endl;
    }
};

int main( int argc, char *argv[] )
{
  if( argc < 4 )
    {
    std::cerr << "Missing Parameters " << std::endl;
    std::cerr << "Usage: " << argv[0];
    std::cerr << " fixedImageFile  movingImageFile outputImagefile  ";
    std::cerr << " [differenceOutputfile] [differenceBeforeRegistration] ";
    std::cerr << " [deformationField] ";
    return 1;
    }

  const    unsigned int    ImageDimension = 3;
  typedef  float           PixelType;

  typedef itk::Image< PixelType, ImageDimension >  FixedImageType;
  typedef itk::Image< PixelType, ImageDimension >  MovingImageType;

  //  Software Guide : BeginLatex
  //
  //  We instantiate now the type of the \code{BSplineDeformableTransform} using
  //  as template parameters the type for coordinates representation, the
  //  dimension of the space, and the order of the BSpline.
  //
  //  \index{BSplineDeformableTransform!New}
  //  \index{BSplineDeformableTransform!Instantiation}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  const unsigned int SpaceDimension = ImageDimension;
  const unsigned int SplineOrder = 3;
  typedef double CoordinateRepType;

  typedef itk::BSplineDeformableTransform<
                            CoordinateRepType,
                            SpaceDimension,
                            SplineOrder >     TransformType;
  // Software Guide : EndCodeSnippet

  typedef itk::LBFGSBOptimizer       OptimizerType;

  typedef itk::MeanSquaresImageToImageMetric<
                                    FixedImageType,
                                    MovingImageType >    MetricType;

  typedef itk:: LinearInterpolateImageFunction<
                                    MovingImageType,
                                    double          >    InterpolatorType;

  typedef itk::ImageRegistrationMethod<
                                    FixedImageType,
                                    MovingImageType >    RegistrationType;

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

  registration->SetMetric(        metric        );
  registration->SetOptimizer(     optimizer     );
  registration->SetInterpolator(  interpolator  );

  //  Software Guide : BeginLatex
  //
  //  The transform object is constructed below and passed to the registration
  //  method.
  //  \index{itk::RegistrationMethod!SetTransform()}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  TransformType::Pointer  transform = TransformType::New();
  registration->SetTransform( transform );
  // Software Guide : EndCodeSnippet

  typedef itk::ImageFileReader< FixedImageType  > FixedImageReaderType;
  typedef itk::ImageFileReader< MovingImageType > MovingImageReaderType;

  FixedImageReaderType::Pointer  fixedImageReader  = FixedImageReaderType::New();
  MovingImageReaderType::Pointer movingImageReader = MovingImageReaderType::New();

  fixedImageReader->SetFileName(  argv[1] );
  movingImageReader->SetFileName( argv[2] );

  FixedImageType::ConstPointer fixedImage = fixedImageReader->GetOutput();

  registration->SetFixedImage(  fixedImage   );
  registration->SetMovingImage(   movingImageReader->GetOutput()   );

  fixedImageReader->Update();

  FixedImageType::RegionType fixedRegion = fixedImage->GetBufferedRegion();

 registration->SetFixedImageRegion( fixedRegion );

  //  Software Guide : BeginLatex
  //
  //  Here we define the parameters of the BSplineDeformableTransform grid.  We
  //  arbitrarily decide to use a grid with $5 \times 5$ nodes within the image.
  //  The reader should note that the BSpline computation requires a
  //  finite support region ( 1 grid node at the lower borders and 2
  //  grid nodes at upper borders). Therefore in this example, we set
  //  the grid size to be $8 \times 8$ and place the grid origin such that
  //  grid node (1,1) coincides with the first pixel in the fixed image.
  //
  //  \index{BSplineDeformableTransform}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef TransformType::RegionType RegionType;
  RegionType bsplineRegion;
  RegionType::SizeType   gridSizeOnImage;
  RegionType::SizeType   gridBorderSize;
  RegionType::SizeType   totalGridSize;

  gridSizeOnImage.Fill( 5 );
  gridBorderSize.Fill( 3 );    // Border for spline order = 3 ( 1 lower, 2 upper )
  totalGridSize = gridSizeOnImage + gridBorderSize;

  bsplineRegion.SetSize( totalGridSize );

  typedef TransformType::SpacingType SpacingType;
  SpacingType spacing = fixedImage->GetSpacing();

  typedef TransformType::OriginType OriginType;
  OriginType origin = fixedImage->GetOrigin();;

  FixedImageType::SizeType fixedImageSize = fixedRegion.GetSize();

  for(unsigned int r=0; r<ImageDimension; r++)
    {
    spacing[r] *= floor( static_cast<double>(fixedImageSize[r] - 1)  /
                  static_cast<double>(gridSizeOnImage[r] - 1) );
    origin[r]  -=  spacing[r];
    }

  transform->SetGridSpacing( spacing );
  transform->SetGridOrigin( origin );
  transform->SetGridRegion( bsplineRegion );

  typedef TransformType::ParametersType     ParametersType;

  const unsigned int numberOfParameters =
               transform->GetNumberOfParameters();

  ParametersType parameters( numberOfParameters );

  parameters.Fill( 0.0 );

  transform->SetParameters( parameters );
  //  Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  We now pass the parameters of the current transform as the initial
  //  parameters to be used when the registration process starts.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  registration->SetInitialTransformParameters( transform->GetParameters() );
  // Software Guide : EndCodeSnippet

  std::cout << "Intial Parameters = " << std::endl;
  std::cout << transform->GetParameters() << std::endl;

  //  Software Guide : BeginLatex
  //
  //  Next we set the parameters of the LBFGSB Optimizer.
  //
  //  Software Guide : EndLatex
  OptimizerType::BoundSelectionType boundSelect( transform->GetNumberOfParameters() );
  OptimizerType::BoundValueType upperBound( transform->GetNumberOfParameters() );
  OptimizerType::BoundValueType lowerBound( transform->GetNumberOfParameters() );

  boundSelect.Fill( 0 );
  upperBound.Fill( 0.0 );
  lowerBound.Fill( 0.0 );

  optimizer->SetBoundSelection( boundSelect );
  optimizer->SetUpperBound( upperBound );
  optimizer->SetLowerBound( lowerBound );

  optimizer->SetCostFunctionConvergenceFactor( 1e+12 );
  optimizer->SetProjectedGradientTolerance( 1.0 );
  optimizer->SetMaximumNumberOfIterations( 500 );
  optimizer->SetMaximumNumberOfEvaluations( 500 );
  optimizer->SetMaximumNumberOfCorrections( 5 );

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

  // Add a time probe
  itk::TimeProbesCollectorBase collector;

  std::cout << std::endl << "Starting Registration" << std::endl;

  try
    {
    collector.Start( "Registration" );
    registration->StartRegistration();
    collector.Stop( "Registration" );
    }
  catch( itk::ExceptionObject & err )
    {
    std::cerr << "ExceptionObject caught !" << std::endl;
    std::cerr << err << std::endl;
    return -1;
    }

  OptimizerType::ParametersType finalParameters =
                    registration->GetLastTransformParameters();

  std::cout << "Last Transform Parameters" << std::endl;
  std::cout << finalParameters << std::endl;

  // Report the time taken by the registration
  collector.Report();

  // Software Guide : BeginCodeSnippet
  transform->SetParameters( finalParameters );
  // Software Guide : EndCodeSnippet

  typedef itk::ResampleImageFilter<
                            MovingImageType,
                            FixedImageType >    ResampleFilterType;

  ResampleFilterType::Pointer resample = ResampleFilterType::New();

  resample->SetTransform( transform );
  resample->SetInput( movingImageReader->GetOutput() );

  resample->SetSize(    fixedImage->GetLargestPossibleRegion().GetSize() );
  resample->SetOutputOrigin(  fixedImage->GetOrigin() );
  resample->SetOutputSpacing( fixedImage->GetSpacing() );
  resample->SetDefaultPixelValue( 100 );

  typedef  unsigned char  OutputPixelType;

  typedef itk::Image< OutputPixelType, ImageDimension > OutputImageType;

  typedef itk::CastImageFilter<
                        FixedImageType,
                        OutputImageType > CastFilterType;

  typedef itk::ImageFileWriter< OutputImageType >  WriterType;

  WriterType::Pointer      writer =  WriterType::New();
  CastFilterType::Pointer  caster =  CastFilterType::New();

  writer->SetFileName( argv[3] );

  caster->SetInput( resample->GetOutput() );
  writer->SetInput( caster->GetOutput()   );

  try
    {
    writer->Update();
    }
  catch( itk::ExceptionObject & err )
    {
    std::cerr << "ExceptionObject caught !" << std::endl;
    std::cerr << err << std::endl;
    return -1;
    }

  typedef itk::SquaredDifferenceImageFilter<
                                  FixedImageType,
                                  FixedImageType,
                                  OutputImageType > DifferenceFilterType;

  DifferenceFilterType::Pointer difference = DifferenceFilterType::New();

  WriterType::Pointer writer2 = WriterType::New();
  writer2->SetInput( difference->GetOutput() );

  // Compute the difference image between the
  // fixed and resampled moving image.
  if( argc >= 5 )
    {
    difference->SetInput1( fixedImageReader->GetOutput() );
    difference->SetInput2( resample->GetOutput() );
    writer2->SetFileName( argv[4] );
    try
      {
      writer2->Update();
      }
    catch( itk::ExceptionObject & err )
      {
      std::cerr << "ExceptionObject caught !" << std::endl;
      std::cerr << err << std::endl;
      return -1;
      }
    }

  // Compute the difference image between the
  // fixed and moving image before registration.
  if( argc >= 6 )
    {
    writer2->SetFileName( argv[5] );
    difference->SetInput1( fixedImageReader->GetOutput() );
    difference->SetInput2( movingImageReader->GetOutput() );
    try
      {
      writer2->Update();
      }
    catch( itk::ExceptionObject & err )
      {
      std::cerr << "ExceptionObject caught !" << std::endl;
      std::cerr << err << std::endl;
      return -1;
      }
    }

  // Generate the explicit deformation field resulting from
  // the registration.
  if( argc >= 7 )
    {

    typedef itk::Vector< float, ImageDimension >  VectorType;
    typedef itk::Image< VectorType, ImageDimension >  DeformationFieldType;

    DeformationFieldType::Pointer field = DeformationFieldType::New();
    field->SetRegions( fixedRegion );
    field->SetOrigin( fixedImage->GetOrigin() );
    field->SetSpacing( fixedImage->GetSpacing() );
    field->Allocate();

    typedef itk::ImageRegionIterator< DeformationFieldType > FieldIterator;
    FieldIterator fi( field, fixedRegion );

    fi.GoToBegin();

    TransformType::InputPointType  fixedPoint;
    TransformType::OutputPointType movingPoint;
    DeformationFieldType::IndexType index;

    VectorType displacement;

    while( ! fi.IsAtEnd() )
      {
      index = fi.GetIndex();
      field->TransformIndexToPhysicalPoint( index, fixedPoint );
      movingPoint = transform->TransformPoint( fixedPoint );
      displacement[0] = movingPoint[0] - fixedPoint[0];
      displacement[1] = movingPoint[1] - fixedPoint[1];
      fi.Set( displacement );
      ++fi;
      }

    typedef itk::ImageFileWriter< DeformationFieldType >  FieldWriterType;
    FieldWriterType::Pointer fieldWriter = FieldWriterType::New();

    fieldWriter->SetInput( field );

    fieldWriter->SetFileName( argv[6] );
    try
      {
      fieldWriter->Update();
      }
    catch( itk::ExceptionObject & excp )
      {
      std::cerr << "Exception thrown " << std::endl;
      std::cerr << excp << std::endl;
      return EXIT_FAILURE;
      }
    }

  return 0;
}

<commit_msg>STYLE: fix unfounded claim that LBFGSB is more appropriate for higher        dimensional spaces than LBFGS.  The actual reason for using LBFGSB        is that LBFGS does not behave well when the position in the parametric        space is close to the optimal value.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    DeformableRegistration7.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

// Software Guide : BeginLatex
//
// This example illustrates the use of the \doxygen{BSplineDeformableTransform}
// class for performing registration of two $3D$ images. The example code is
// for the most part identical to the code presented in
// Section~\ref{sec:DeformableRegistration}.  The major difference is that this
// example we set the image dimension to 3 and replace the
// \doxygen{LBFGSOptimizer} optimizer with the \doxygen{LBFGSBOptimizer}. We
// made the modification because we found that LBFGS does not behave well when
// the starting positions is at or close to optimal; instead we used LBFGSB in
// unconstrained mode.
//
//
// \index{itk::BSplineDeformableTransform}
// \index{itk::BSplineDeformableTransform!DeformableRegistration}
// \index{itk::LBFGSOptimizer}
//
//
// Software Guide : EndLatex

#include "itkImageRegistrationMethod.h"
#include "itkMeanSquaresImageToImageMetric.h"
#include "itkLinearInterpolateImageFunction.h"
#include "itkImage.h"

#include "itkTimeProbesCollectorBase.h"

//  Software Guide : BeginLatex
//
//  The following are the most relevant headers to this example.
//
//  \index{itk::BSplineDeformableTransform!header}
//  \index{itk::LBFGSOptimizer!header}
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "itkBSplineDeformableTransform.h"
#include "itkLBFGSBOptimizer.h"
// Software Guide : EndCodeSnippet

//  Software Guide : BeginLatex
//
//  The parameter space of the \code{BSplineDeformableTransform} is composed by
//  the set of all the deformations associated with the nodes of the BSpline
//  grid.  This large number of parameters makes possible to represent a wide
//  variety of deformations, but it also has the price of requiring a
//  significant amount of computation time.
//
//  \index{itk::BSplineDeformableTransform!header}
//
//  Software Guide : EndLatex

#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

#include "itkResampleImageFilter.h"
#include "itkCastImageFilter.h"
#include "itkSquaredDifferenceImageFilter.h"

//  The following section of code implements a Command observer
//  used to monitor the evolution of the registration process.
//
#include "itkCommand.h"
class CommandIterationUpdate : public itk::Command
{
public:
  typedef  CommandIterationUpdate   Self;
  typedef  itk::Command             Superclass;
  typedef itk::SmartPointer<Self>  Pointer;
  itkNewMacro( Self );
protected:
  CommandIterationUpdate() {};
public:
  typedef itk::LBFGSBOptimizer     OptimizerType;
  typedef   const OptimizerType   *    OptimizerPointer;

  void Execute(itk::Object *caller, const itk::EventObject & event)
    {
      Execute( (const itk::Object *)caller, event);
    }

  void Execute(const itk::Object * object, const itk::EventObject & event)
    {
      OptimizerPointer optimizer =
        dynamic_cast< OptimizerPointer >( object );
      if( !(itk::IterationEvent().CheckEvent( &event )) )
        {
        return;
        }
      std::cout << optimizer->GetCurrentIteration() << "   ";
      std::cout << optimizer->GetValue() << "   ";
      std::cout << optimizer->GetInfinityNormOfProjectedGradient() << std::endl;
    }
};

int main( int argc, char *argv[] )
{
  if( argc < 4 )
    {
    std::cerr << "Missing Parameters " << std::endl;
    std::cerr << "Usage: " << argv[0];
    std::cerr << " fixedImageFile  movingImageFile outputImagefile  ";
    std::cerr << " [differenceOutputfile] [differenceBeforeRegistration] ";
    std::cerr << " [deformationField] ";
    return 1;
    }

  const    unsigned int    ImageDimension = 3;
  typedef  float           PixelType;

  typedef itk::Image< PixelType, ImageDimension >  FixedImageType;
  typedef itk::Image< PixelType, ImageDimension >  MovingImageType;

  //  Software Guide : BeginLatex
  //
  //  We instantiate now the type of the \code{BSplineDeformableTransform} using
  //  as template parameters the type for coordinates representation, the
  //  dimension of the space, and the order of the BSpline.
  //
  //  \index{BSplineDeformableTransform!New}
  //  \index{BSplineDeformableTransform!Instantiation}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  const unsigned int SpaceDimension = ImageDimension;
  const unsigned int SplineOrder = 3;
  typedef double CoordinateRepType;

  typedef itk::BSplineDeformableTransform<
                            CoordinateRepType,
                            SpaceDimension,
                            SplineOrder >     TransformType;
  // Software Guide : EndCodeSnippet

  typedef itk::LBFGSBOptimizer       OptimizerType;

  typedef itk::MeanSquaresImageToImageMetric<
                                    FixedImageType,
                                    MovingImageType >    MetricType;

  typedef itk:: LinearInterpolateImageFunction<
                                    MovingImageType,
                                    double          >    InterpolatorType;

  typedef itk::ImageRegistrationMethod<
                                    FixedImageType,
                                    MovingImageType >    RegistrationType;

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

  registration->SetMetric(        metric        );
  registration->SetOptimizer(     optimizer     );
  registration->SetInterpolator(  interpolator  );

  //  Software Guide : BeginLatex
  //
  //  The transform object is constructed below and passed to the registration
  //  method.
  //  \index{itk::RegistrationMethod!SetTransform()}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  TransformType::Pointer  transform = TransformType::New();
  registration->SetTransform( transform );
  // Software Guide : EndCodeSnippet

  typedef itk::ImageFileReader< FixedImageType  > FixedImageReaderType;
  typedef itk::ImageFileReader< MovingImageType > MovingImageReaderType;

  FixedImageReaderType::Pointer  fixedImageReader  = FixedImageReaderType::New();
  MovingImageReaderType::Pointer movingImageReader = MovingImageReaderType::New();

  fixedImageReader->SetFileName(  argv[1] );
  movingImageReader->SetFileName( argv[2] );

  FixedImageType::ConstPointer fixedImage = fixedImageReader->GetOutput();

  registration->SetFixedImage(  fixedImage   );
  registration->SetMovingImage(   movingImageReader->GetOutput()   );

  fixedImageReader->Update();

  FixedImageType::RegionType fixedRegion = fixedImage->GetBufferedRegion();

 registration->SetFixedImageRegion( fixedRegion );

  //  Software Guide : BeginLatex
  //
  //  Here we define the parameters of the BSplineDeformableTransform grid.  We
  //  arbitrarily decide to use a grid with $5 \times 5$ nodes within the image.
  //  The reader should note that the BSpline computation requires a
  //  finite support region ( 1 grid node at the lower borders and 2
  //  grid nodes at upper borders). Therefore in this example, we set
  //  the grid size to be $8 \times 8$ and place the grid origin such that
  //  grid node (1,1) coincides with the first pixel in the fixed image.
  //
  //  \index{BSplineDeformableTransform}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef TransformType::RegionType RegionType;
  RegionType bsplineRegion;
  RegionType::SizeType   gridSizeOnImage;
  RegionType::SizeType   gridBorderSize;
  RegionType::SizeType   totalGridSize;

  gridSizeOnImage.Fill( 5 );
  gridBorderSize.Fill( 3 );    // Border for spline order = 3 ( 1 lower, 2 upper )
  totalGridSize = gridSizeOnImage + gridBorderSize;

  bsplineRegion.SetSize( totalGridSize );

  typedef TransformType::SpacingType SpacingType;
  SpacingType spacing = fixedImage->GetSpacing();

  typedef TransformType::OriginType OriginType;
  OriginType origin = fixedImage->GetOrigin();;

  FixedImageType::SizeType fixedImageSize = fixedRegion.GetSize();

  for(unsigned int r=0; r<ImageDimension; r++)
    {
    spacing[r] *= floor( static_cast<double>(fixedImageSize[r] - 1)  /
                  static_cast<double>(gridSizeOnImage[r] - 1) );
    origin[r]  -=  spacing[r];
    }

  transform->SetGridSpacing( spacing );
  transform->SetGridOrigin( origin );
  transform->SetGridRegion( bsplineRegion );

  typedef TransformType::ParametersType     ParametersType;

  const unsigned int numberOfParameters =
               transform->GetNumberOfParameters();

  ParametersType parameters( numberOfParameters );

  parameters.Fill( 0.0 );

  transform->SetParameters( parameters );
  //  Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  We now pass the parameters of the current transform as the initial
  //  parameters to be used when the registration process starts.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  registration->SetInitialTransformParameters( transform->GetParameters() );
  // Software Guide : EndCodeSnippet

  std::cout << "Intial Parameters = " << std::endl;
  std::cout << transform->GetParameters() << std::endl;

  //  Software Guide : BeginLatex
  //
  //  Next we set the parameters of the LBFGSB Optimizer.
  //
  //  Software Guide : EndLatex
  OptimizerType::BoundSelectionType boundSelect( transform->GetNumberOfParameters() );
  OptimizerType::BoundValueType upperBound( transform->GetNumberOfParameters() );
  OptimizerType::BoundValueType lowerBound( transform->GetNumberOfParameters() );

  boundSelect.Fill( 0 );
  upperBound.Fill( 0.0 );
  lowerBound.Fill( 0.0 );

  optimizer->SetBoundSelection( boundSelect );
  optimizer->SetUpperBound( upperBound );
  optimizer->SetLowerBound( lowerBound );

  optimizer->SetCostFunctionConvergenceFactor( 1e+12 );
  optimizer->SetProjectedGradientTolerance( 1.0 );
  optimizer->SetMaximumNumberOfIterations( 500 );
  optimizer->SetMaximumNumberOfEvaluations( 500 );
  optimizer->SetMaximumNumberOfCorrections( 5 );

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

  // Add a time probe
  itk::TimeProbesCollectorBase collector;

  std::cout << std::endl << "Starting Registration" << std::endl;

  try
    {
    collector.Start( "Registration" );
    registration->StartRegistration();
    collector.Stop( "Registration" );
    }
  catch( itk::ExceptionObject & err )
    {
    std::cerr << "ExceptionObject caught !" << std::endl;
    std::cerr << err << std::endl;
    return -1;
    }

  OptimizerType::ParametersType finalParameters =
                    registration->GetLastTransformParameters();

  std::cout << "Last Transform Parameters" << std::endl;
  std::cout << finalParameters << std::endl;

  // Report the time taken by the registration
  collector.Report();

  // Software Guide : BeginCodeSnippet
  transform->SetParameters( finalParameters );
  // Software Guide : EndCodeSnippet

  typedef itk::ResampleImageFilter<
                            MovingImageType,
                            FixedImageType >    ResampleFilterType;

  ResampleFilterType::Pointer resample = ResampleFilterType::New();

  resample->SetTransform( transform );
  resample->SetInput( movingImageReader->GetOutput() );

  resample->SetSize(    fixedImage->GetLargestPossibleRegion().GetSize() );
  resample->SetOutputOrigin(  fixedImage->GetOrigin() );
  resample->SetOutputSpacing( fixedImage->GetSpacing() );
  resample->SetDefaultPixelValue( 100 );

  typedef  unsigned char  OutputPixelType;

  typedef itk::Image< OutputPixelType, ImageDimension > OutputImageType;

  typedef itk::CastImageFilter<
                        FixedImageType,
                        OutputImageType > CastFilterType;

  typedef itk::ImageFileWriter< OutputImageType >  WriterType;

  WriterType::Pointer      writer =  WriterType::New();
  CastFilterType::Pointer  caster =  CastFilterType::New();

  writer->SetFileName( argv[3] );

  caster->SetInput( resample->GetOutput() );
  writer->SetInput( caster->GetOutput()   );

  try
    {
    writer->Update();
    }
  catch( itk::ExceptionObject & err )
    {
    std::cerr << "ExceptionObject caught !" << std::endl;
    std::cerr << err << std::endl;
    return -1;
    }

  typedef itk::SquaredDifferenceImageFilter<
                                  FixedImageType,
                                  FixedImageType,
                                  OutputImageType > DifferenceFilterType;

  DifferenceFilterType::Pointer difference = DifferenceFilterType::New();

  WriterType::Pointer writer2 = WriterType::New();
  writer2->SetInput( difference->GetOutput() );

  // Compute the difference image between the
  // fixed and resampled moving image.
  if( argc >= 5 )
    {
    difference->SetInput1( fixedImageReader->GetOutput() );
    difference->SetInput2( resample->GetOutput() );
    writer2->SetFileName( argv[4] );
    try
      {
      writer2->Update();
      }
    catch( itk::ExceptionObject & err )
      {
      std::cerr << "ExceptionObject caught !" << std::endl;
      std::cerr << err << std::endl;
      return -1;
      }
    }

  // Compute the difference image between the
  // fixed and moving image before registration.
  if( argc >= 6 )
    {
    writer2->SetFileName( argv[5] );
    difference->SetInput1( fixedImageReader->GetOutput() );
    difference->SetInput2( movingImageReader->GetOutput() );
    try
      {
      writer2->Update();
      }
    catch( itk::ExceptionObject & err )
      {
      std::cerr << "ExceptionObject caught !" << std::endl;
      std::cerr << err << std::endl;
      return -1;
      }
    }

  // Generate the explicit deformation field resulting from
  // the registration.
  if( argc >= 7 )
    {

    typedef itk::Vector< float, ImageDimension >  VectorType;
    typedef itk::Image< VectorType, ImageDimension >  DeformationFieldType;

    DeformationFieldType::Pointer field = DeformationFieldType::New();
    field->SetRegions( fixedRegion );
    field->SetOrigin( fixedImage->GetOrigin() );
    field->SetSpacing( fixedImage->GetSpacing() );
    field->Allocate();

    typedef itk::ImageRegionIterator< DeformationFieldType > FieldIterator;
    FieldIterator fi( field, fixedRegion );

    fi.GoToBegin();

    TransformType::InputPointType  fixedPoint;
    TransformType::OutputPointType movingPoint;
    DeformationFieldType::IndexType index;

    VectorType displacement;

    while( ! fi.IsAtEnd() )
      {
      index = fi.GetIndex();
      field->TransformIndexToPhysicalPoint( index, fixedPoint );
      movingPoint = transform->TransformPoint( fixedPoint );
      displacement[0] = movingPoint[0] - fixedPoint[0];
      displacement[1] = movingPoint[1] - fixedPoint[1];
      fi.Set( displacement );
      ++fi;
      }

    typedef itk::ImageFileWriter< DeformationFieldType >  FieldWriterType;
    FieldWriterType::Pointer fieldWriter = FieldWriterType::New();

    fieldWriter->SetInput( field );

    fieldWriter->SetFileName( argv[6] );
    try
      {
      fieldWriter->Update();
      }
    catch( itk::ExceptionObject & excp )
      {
      std::cerr << "Exception thrown " << std::endl;
      std::cerr << excp << std::endl;
      return EXIT_FAILURE;
      }
    }

  return 0;
}

<|endoftext|>


<commit_before><commit_msg>fixed crash in profiler, int values in profiler have empty space in exclusive time column<commit_after><|endoftext|>


<commit_before>/// \file
/// \ingroup tutorial_fit
/// \notebook -nodraw
/// Multi-Dimensional Parametrisation and Fitting
///
/// \macro_output
/// \macro_code
///
/// \authors Rene Brun, Christian Holm Christensen

#include "Riostream.h"
#include "TROOT.h"
#include "TApplication.h"
#include "TCanvas.h"
#include "TH1.h"
#include "TSystem.h"
#include "TBrowser.h"
#include "TFile.h"
#include "TRandom.h"
#include "TMultiDimFit.h"
#include "TVectorD.h"
#include "TMath.h"

//____________________________________________________________________
void makeData(Double_t* x, Double_t& d, Double_t& e)
{
  // Make data points
  Double_t upp[5] = { 10, 10, 10, 10,  1 };
  Double_t low[5] = {  0,  0,  0,  0, .1 };
  for (int i = 0; i < 4; i++)
    x[i] = (upp[i] - low[i]) * gRandom->Rndm() + low[i];

  d = x[0] * TMath::Sqrt(x[1] * x[1] + x[2] * x[2] + x[3] * x[3]);

  e = gRandom->Gaus(upp[4],low[4]);
}

//____________________________________________________________________
int CompareResults(TMultiDimFit *fit, bool doFit)
{
      //Compare results with reference run

      // the right coefficients (before fit)
   double GoodCoeffsNoFit[] = {
   -4.37056,
   43.1468,
   13.432,
   13.4632,
   13.3964,
   13.328,
   13.3016,
   13.3519,
   4.49724,
   4.63876,
   4.89036,
   -3.69982,
   -3.98618,
   -3.86195,
   4.36054,
   -4.02597,
   4.57037,
   4.69845,
   2.83819,
   -3.48855,
   -3.97612
   };

      // the right coefficients (after fit)
   double GoodCoeffs[] = {
      -4.399,
      43.15,
      13.41,
      13.49,
      13.4,
      13.23,
      13.34,
      13.29,
      4.523,
      4.659,
      4.948,
      -4.026,
      -4.045,
      -3.939,
      4.421,
      -4.006,
      4.626,
      4.378,
      3.516,
      -4.111,
      -3.823,
   };

   // Good Powers
   int GoodPower[] = {
   1,  1,  1,  1,
   2,  1,  1,  1,
   1,  1,  1,  2,
   1,  1,  2,  1,
   1,  2,  1,  1,
   2,  2,  1,  1,
   2,  1,  1,  2,
   2,  1,  2,  1,
   1,  1,  1,  3,
   1,  3,  1,  1,
   1,  1,  5,  1,
   1,  1,  2,  2,
   1,  2,  1,  2,
   1,  2,  2,  1,
   2,  1,  1,  3,
   2,  2,  1,  2,
   2,  1,  3,  1,
   2,  3,  1,  1,
   1,  2,  2,  2,
   2,  1,  2,  2,
   2,  2,  2,  1
   };

   Int_t nc = fit->GetNCoefficients();
   Int_t nv = fit->GetNVariables();
   const Int_t *powers = fit->GetPowers();
   const Int_t *pindex = fit->GetPowerIndex();
   if (nc != 21) return 1;
   const TVectorD *coeffs = fit->GetCoefficients();
   int k = 0;
   for (Int_t i=0;i<nc;i++) {
      if (doFit) {
         if (!TMath::AreEqualRel((*coeffs)[i],GoodCoeffs[i],1e-3)) return 2;
      }
      else {
         if (TMath::Abs((*coeffs)[i] - GoodCoeffsNoFit[i]) > 5e-5) return 2;
      }
      for (Int_t j=0;j<nv;j++) {
         if (powers[pindex[i]*nv+j] != GoodPower[k]) return 3;
         k++;
      }
   }

   // now test the result of the generated function
   gROOT->ProcessLine(".L MDF.C");

   Double_t refMDF = (doFit) ? 43.95 : 43.98;
   // this does not work in CLing since the function is not defined
   //Double_t x[]    = {5,5,5,5};
   //Double_t rMDF   = MDF(x);
   //LM:  need to return the address of the result since it is casted to a long (this should not be in a tutorial !)
   Long_t iret = gROOT->ProcessLine(" Double_t xvalues[] = {5,5,5,5}; double result=MDF(xvalues); &result;");
   Double_t rMDF = * ( (Double_t*)iret);
   //printf("%f\n",rMDF);
   if (TMath::Abs(rMDF -refMDF) > 1e-2) return 4;
   return 0;
}

//____________________________________________________________________
Int_t multidimfit(bool doFit = true)
{

   cout << "*************************************************" << endl;
   cout << "*             Multidimensional Fit              *" << endl;
   cout << "*                                               *" << endl;
   cout << "* By Christian Holm <cholm@nbi.dk> 14/10/00     *" << endl;
   cout << "*************************************************" << endl;
   cout << endl;

   // Initialize global TRannom object.
   gRandom = new TRandom();

   // Open output file
   TFile* output = new TFile("mdf.root", "RECREATE");

   // Global data parameters
   Int_t nVars       = 4;
   Int_t nData       = 500;
   Double_t x[4];

   // make fit object and set parameters on it.
   TMultiDimFit* fit = new TMultiDimFit(nVars, TMultiDimFit::kMonomials,"v");

   Int_t mPowers[]   = { 6 , 6, 6, 6 };
   fit->SetMaxPowers(mPowers);
   fit->SetMaxFunctions(1000);
   fit->SetMaxStudy(1000);
   fit->SetMaxTerms(30);
   fit->SetPowerLimit(1);
   fit->SetMinAngle(10);
   fit->SetMaxAngle(10);
   fit->SetMinRelativeError(.01);

   // variables to hold the temporary input data
   Double_t d;
   Double_t e;

   // Print out the start parameters
   fit->Print("p");

   printf("======================================\n");

   // Create training sample
   Int_t i;
   for (i = 0; i < nData ; i++) {

      // Make some data
      makeData(x,d,e);

      // Add the row to the fit object
      fit->AddRow(x,d,e);
   }

   // Print out the statistics
   fit->Print("s");

   // Book histograms
   fit->MakeHistograms();

   // Find the parameterization
   fit->FindParameterization();

   // Print coefficents
   fit->Print("rc");

   // Get the min and max of variables from the training sample, used
   // for cuts in test sample.
   Double_t *xMax = new Double_t[nVars];
   Double_t *xMin = new Double_t[nVars];
   for (i = 0; i < nVars; i++) {
      xMax[i] = (*fit->GetMaxVariables())(i);
      xMin[i] = (*fit->GetMinVariables())(i);
   }

   nData = fit->GetNCoefficients() * 100;
   Int_t j;

   // Create test sample
   for (i = 0; i < nData ; i++) {
      // Make some data
      makeData(x,d,e);

      for (j = 0; j < nVars; j++)
         if (x[j] < xMin[j] || x[j] > xMax[j])
      break;

      // If we get through the loop above, all variables are in range
      if (j == nVars)
         // Add the row to the fit object
         fit->AddTestRow(x,d,e);
      else
         i--;
   }
   //delete gRandom;

   // Test the parameterizatio and coefficents using the test sample.
   if (doFit)
      fit->Fit("M");

   // Print result
   fit->Print("fc v");

   // Write code to file
   fit->MakeCode();

   // Write histograms to disk, and close file
   output->Write();
   output->Close();
   delete output;

   // Compare results with reference run
   Int_t compare = CompareResults(fit, doFit);
   if (!compare) {
      printf("\nmultidimfit ..............................................  OK\n");
   } else {
      printf("\nmultidimfit ..............................................  fails case %d\n",compare);
   }

   // We're done
   delete fit;
   return compare;
}
<commit_msg>Mem leak in multidimfit.C tutorial<commit_after>/// \file
/// \ingroup tutorial_fit
/// \notebook -nodraw
/// Multi-Dimensional Parametrisation and Fitting
///
/// \macro_output
/// \macro_code
///
/// \authors Rene Brun, Christian Holm Christensen

#include "Riostream.h"
#include "TROOT.h"
#include "TApplication.h"
#include "TCanvas.h"
#include "TH1.h"
#include "TSystem.h"
#include "TBrowser.h"
#include "TFile.h"
#include "TRandom.h"
#include "TMultiDimFit.h"
#include "TVectorD.h"
#include "TMath.h"

//____________________________________________________________________
void makeData(Double_t* x, Double_t& d, Double_t& e)
{
  // Make data points
  Double_t upp[5] = { 10, 10, 10, 10,  1 };
  Double_t low[5] = {  0,  0,  0,  0, .1 };
  for (int i = 0; i < 4; i++)
    x[i] = (upp[i] - low[i]) * gRandom->Rndm() + low[i];

  d = x[0] * TMath::Sqrt(x[1] * x[1] + x[2] * x[2] + x[3] * x[3]);

  e = gRandom->Gaus(upp[4],low[4]);
}

//____________________________________________________________________
int CompareResults(TMultiDimFit *fit, bool doFit)
{
      //Compare results with reference run

      // the right coefficients (before fit)
   double GoodCoeffsNoFit[] = {
   -4.37056,
   43.1468,
   13.432,
   13.4632,
   13.3964,
   13.328,
   13.3016,
   13.3519,
   4.49724,
   4.63876,
   4.89036,
   -3.69982,
   -3.98618,
   -3.86195,
   4.36054,
   -4.02597,
   4.57037,
   4.69845,
   2.83819,
   -3.48855,
   -3.97612
   };

      // the right coefficients (after fit)
   double GoodCoeffs[] = {
      -4.399,
      43.15,
      13.41,
      13.49,
      13.4,
      13.23,
      13.34,
      13.29,
      4.523,
      4.659,
      4.948,
      -4.026,
      -4.045,
      -3.939,
      4.421,
      -4.006,
      4.626,
      4.378,
      3.516,
      -4.111,
      -3.823,
   };

   // Good Powers
   int GoodPower[] = {
   1,  1,  1,  1,
   2,  1,  1,  1,
   1,  1,  1,  2,
   1,  1,  2,  1,
   1,  2,  1,  1,
   2,  2,  1,  1,
   2,  1,  1,  2,
   2,  1,  2,  1,
   1,  1,  1,  3,
   1,  3,  1,  1,
   1,  1,  5,  1,
   1,  1,  2,  2,
   1,  2,  1,  2,
   1,  2,  2,  1,
   2,  1,  1,  3,
   2,  2,  1,  2,
   2,  1,  3,  1,
   2,  3,  1,  1,
   1,  2,  2,  2,
   2,  1,  2,  2,
   2,  2,  2,  1
   };

   Int_t nc = fit->GetNCoefficients();
   Int_t nv = fit->GetNVariables();
   const Int_t *powers = fit->GetPowers();
   const Int_t *pindex = fit->GetPowerIndex();
   if (nc != 21) return 1;
   const TVectorD *coeffs = fit->GetCoefficients();
   int k = 0;
   for (Int_t i=0;i<nc;i++) {
      if (doFit) {
         if (!TMath::AreEqualRel((*coeffs)[i],GoodCoeffs[i],1e-3)) return 2;
      }
      else {
         if (TMath::Abs((*coeffs)[i] - GoodCoeffsNoFit[i]) > 5e-5) return 2;
      }
      for (Int_t j=0;j<nv;j++) {
         if (powers[pindex[i]*nv+j] != GoodPower[k]) return 3;
         k++;
      }
   }

   // now test the result of the generated function
   gROOT->ProcessLine(".L MDF.C");

   Double_t refMDF = (doFit) ? 43.95 : 43.98;
   // this does not work in CLing since the function is not defined
   //Double_t x[]    = {5,5,5,5};
   //Double_t rMDF   = MDF(x);
   //LM:  need to return the address of the result since it is casted to a long (this should not be in a tutorial !)
   Long_t iret = gROOT->ProcessLine(" Double_t xvalues[] = {5,5,5,5}; double result=MDF(xvalues); &result;");
   Double_t rMDF = * ( (Double_t*)iret);
   //printf("%f\n",rMDF);
   if (TMath::Abs(rMDF -refMDF) > 1e-2) return 4;
   return 0;
}

//____________________________________________________________________
Int_t multidimfit(bool doFit = true)
{

   cout << "*************************************************" << endl;
   cout << "*             Multidimensional Fit              *" << endl;
   cout << "*                                               *" << endl;
   cout << "* By Christian Holm <cholm@nbi.dk> 14/10/00     *" << endl;
   cout << "*************************************************" << endl;
   cout << endl;

   // Initialize global TRannom object.
   gRandom = new TRandom();

   // Open output file
   TFile* output = new TFile("mdf.root", "RECREATE");

   // Global data parameters
   Int_t nVars       = 4;
   Int_t nData       = 500;
   Double_t x[4];

   // make fit object and set parameters on it.
   TMultiDimFit* fit = new TMultiDimFit(nVars, TMultiDimFit::kMonomials,"v");

   Int_t mPowers[]   = { 6 , 6, 6, 6 };
   fit->SetMaxPowers(mPowers);
   fit->SetMaxFunctions(1000);
   fit->SetMaxStudy(1000);
   fit->SetMaxTerms(30);
   fit->SetPowerLimit(1);
   fit->SetMinAngle(10);
   fit->SetMaxAngle(10);
   fit->SetMinRelativeError(.01);

   // variables to hold the temporary input data
   Double_t d;
   Double_t e;

   // Print out the start parameters
   fit->Print("p");

   printf("======================================\n");

   // Create training sample
   Int_t i;
   for (i = 0; i < nData ; i++) {

      // Make some data
      makeData(x,d,e);

      // Add the row to the fit object
      fit->AddRow(x,d,e);
   }

   // Print out the statistics
   fit->Print("s");

   // Book histograms
   fit->MakeHistograms();

   // Find the parameterization
   fit->FindParameterization();

   // Print coefficents
   fit->Print("rc");

   // Get the min and max of variables from the training sample, used
   // for cuts in test sample.
   Double_t *xMax = new Double_t[nVars];
   Double_t *xMin = new Double_t[nVars];
   for (i = 0; i < nVars; i++) {
      xMax[i] = (*fit->GetMaxVariables())(i);
      xMin[i] = (*fit->GetMinVariables())(i);
   }

   nData = fit->GetNCoefficients() * 100;
   Int_t j;

   // Create test sample
   for (i = 0; i < nData ; i++) {
      // Make some data
      makeData(x,d,e);

      for (j = 0; j < nVars; j++)
         if (x[j] < xMin[j] || x[j] > xMax[j])
      break;

      // If we get through the loop above, all variables are in range
      if (j == nVars)
         // Add the row to the fit object
         fit->AddTestRow(x,d,e);
      else
         i--;
   }
   //delete gRandom;

   // Test the parameterizatio and coefficents using the test sample.
   if (doFit)
      fit->Fit("M");

   // Print result
   fit->Print("fc v");

   // Write code to file
   fit->MakeCode();

   // Write histograms to disk, and close file
   output->Write();
   output->Close();
   delete output;

   // Compare results with reference run
   Int_t compare = CompareResults(fit, doFit);
   if (!compare) {
      printf("\nmultidimfit ..............................................  OK\n");
   } else {
      printf("\nmultidimfit ..............................................  fails case %d\n",compare);
   }

   // We're done
   delete fit;
   delete [] xMin;
   delete [] xMax;
   return compare;
}
<|endoftext|>