]> Creatis software - clitk.git/commitdiff
Merge branch 'master' of /home/dsarrut/clitk3.server
authorDavid Sarrut <david.sarrut@creatis.insa-lyon.fr>
Mon, 29 Aug 2011 06:33:45 +0000 (08:33 +0200)
committerDavid Sarrut <david.sarrut@creatis.insa-lyon.fr>
Mon, 29 Aug 2011 06:33:45 +0000 (08:33 +0200)
41 files changed:
CMakeLists.txt
common/clitkImageCommon.h
common/clitkImageCommon.txx
common/clitkImageToImageGenericFilterBase.cxx
common/clitkImageToImageGenericFilterBase.h
common/clitkXdrImageIOReader.cxx
itk/clitkReconstructThroughDilationImageFilter.h
itk/clitkReconstructThroughDilationImageFilter.txx
registration/itkMattesMutualInformationImageToImageMetricFor3DBLUTFFD.h
registration/itkMattesMutualInformationImageToImageMetricFor3DBLUTFFD.txx
scripts/common.sh [deleted file]
scripts/create_mhd_3D.sh [new file with mode: 0755]
scripts/create_mhd_4D-2.0.sh [new file with mode: 0755]
scripts/create_mhd_4D_pattern.sh [new file with mode: 0755]
scripts/create_midP-2.0.sh [new file with mode: 0755]
scripts/create_midP.sh [new file with mode: 0755]
scripts/create_midP_masks-2.0.sh [new file with mode: 0755]
scripts/create_midP_masks.sh
scripts/midp_common.sh [new file with mode: 0755]
scripts/midp_template.conf [new file with mode: 0644]
scripts/pts_to_landmarks.sh [new file with mode: 0755]
scripts/registration.sh [new file with mode: 0755]
tests/tools/CMakeLists.txt
tools/CMakeLists.txt
tools/clitkImageConvert.cxx
tools/clitkImageConvert.ggo
tools/clitkMedianTemporalDimensionGenericFilter.txx
tools/clitkTransformLandmarks.cxx
tools/clitkTransformLandmarks.ggo
vv/qt_ui/vvHelpDialog.ui
vv/qt_ui/vvOverlayPanel.ui
vv/vv.cxx
vv/vvMainWindow.cxx
vv/vvMainWindow.h
vv/vvOverlayPanel.cxx
vv/vvOverlayPanel.h
vv/vvSlicer.cxx
vv/vvSlicer.h
vv/vvSlicerManager.cxx
vv/vvSlicerManager.h
vv/vvSlicerManagerCommand.cxx

index 6fe2e34e275ee708f07ae74bf40e73bdd7a75366..48f125772db517ac6d22b08b3a8ba6169fcf6f14 100644 (file)
@@ -109,3 +109,20 @@ ENDIF(CLITK_BUILD_VV)
 IF(BUILD_TESTING)
   ADD_SUBDIRECTORY(tests)
 ENDIF(BUILD_TESTING)
+
+#=========================================================
+# Install scripts when running make install
+SET(SCRIPTS 
+  scripts/midp_common.sh
+  scripts/registration.sh
+  scripts/create_midP.sh
+  scripts/create_midP-2.0.sh        
+  scripts/create_mhd_4D.sh          
+  scripts/create_mhd_4D_pattern.sh  
+  scripts/create_midP_masks.sh  
+  scripts/create_midP_masks-2.0.sh  
+  scripts/pts_to_landmarks.sh
+)
+
+INSTALL (FILES ${SCRIPTS} DESTINATION bin PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_EXECUTE WORLD_EXECUTE)
+
index fbddb20d3ddabaaba554b0a662c36beba77b0364..32bba4916c1ec25244a09655bd1a3dcdf6cd54d2 100644 (file)
@@ -58,11 +58,11 @@ typename ImageType::Pointer readImage(const std::string & filename, const bool v
 template<typename ImageType>
 typename ImageType::Pointer readImage(const std::vector<std::string> & filenames, const bool verbose=false);
 template<class ImageType>
-void writeImage(const typename ImageType::Pointer image, const std::string & filename, const bool verbose=false);
+void writeImage(const typename ImageType::Pointer image, const std::string & filename, const bool verbose=false, const bool compression=false);
 //   template<class ImageType>
 //   void writeConstImage(const typename ImageType::ConstPointer image, const std::string & filename, const bool verbose=false);
 template<class ImageType>
-void writeImage(const ImageType* image, const std::string & filename, const bool verbose=false);
+void writeImage(const ImageType* image, const std::string & filename, const bool verbose=false, const bool compression=false);
 
 //--------------------------------------------------------------------
 // Read/print image header
index 5aa3b2eba55e44db3e973328c370b05935f95cab..a07c66f0459eca0743c41c460937e48a484c75a0 100644 (file)
@@ -188,34 +188,22 @@ typename ImageType::Pointer readImage(const std::vector<std::string> & filenames
 
 //--------------------------------------------------------------------
 template<class ImageType>
-void writeImage(const typename ImageType::Pointer image, const std::string & filename, const bool verbose)
+void writeImage(const typename ImageType::Pointer image, const std::string & filename, const bool verbose, const bool compression)
 {
-  typedef itk::ImageFileWriter<ImageType> WriterType;
-  typename WriterType::Pointer writer = WriterType::New();
-  writer->SetFileName(filename.c_str());
-  writer->SetInput(image);
-  if (verbose) {
-    std::cout << "Writing [" << filename << "] ... " << std::endl;
-  }
-  try {
-    writer->Update();
-  } catch( itk::ExceptionObject & err ) {
-    std::cerr << "Exception while writing image [" << filename << "]" << std::endl;
-    std::cerr << err << std::endl;
-    exit(-1);
-  }
+  return writeImage(image.GetPointer(), filename, verbose, compression);
 }
 //--------------------------------------------------------------------
 
 
 //--------------------------------------------------------------------
 template<class ImageType>
-void writeImage(const ImageType* image, const std::string & filename, const bool verbose)
+void writeImage(const ImageType* image, const std::string & filename, const bool verbose, const bool compression)
 {
   typedef itk::ImageFileWriter<ImageType> WriterType;
   typename WriterType::Pointer writer = WriterType::New();
   writer->SetFileName(filename.c_str());
   writer->SetInput(image);
+  writer->SetUseCompression(compression);
   if (verbose) {
     std::cout << "Writing [" << filename << "] ... " << std::endl;
   }
index 8b0505d7bb2ec214db028ef0fba9a1211640a5f3..5f9cfac54d283c092418ca372ea6355577d59043 100644 (file)
@@ -36,6 +36,7 @@ clitk::ImageToImageGenericFilterBase::ImageToImageGenericFilterBase(std::string
   m_FailOnImageTypeError = true;
   m_ReadOnDisk = true;
   m_WriteOnDisk = true;
+  m_WriteCompression = false;
   // m_LastError = "";
   // StopOnErrorOn();
   SetFilterBase(NULL);
@@ -72,6 +73,14 @@ void clitk::ImageToImageGenericFilterBase::EnableWriteOnDisk(bool b)
 //--------------------------------------------------------------------
 
 
+//--------------------------------------------------------------------
+void clitk::ImageToImageGenericFilterBase::EnableWriteCompression(bool b)
+{
+  m_WriteCompression = b;
+}
+//--------------------------------------------------------------------
+
+
 //--------------------------------------------------------------------
 void clitk::ImageToImageGenericFilterBase::SetInputFilename(const std::string & filename)
 {
@@ -321,7 +330,7 @@ template<class ImageType>
 void clitk::ImageToImageGenericFilterBase::SetNextOutput(typename ImageType::Pointer output)
 {
   if (m_WriteOnDisk && m_OutputFilenames.size()) {
-    clitk::writeImage<ImageType>(output, m_OutputFilenames.front(), m_IOVerbose);
+    clitk::writeImage<ImageType>(output, m_OutputFilenames.front(), m_IOVerbose, m_WriteCompression);
     m_OutputFilenames.pop_front();
   }
   if (m_InputVVImages.size()) //We assume that if a vv image is set as input, we want one as the output
index 039b850a59199ead284232b2ee13681080042c31..03b4f4acfa030d91b52e0804b521e06e6f30ed25 100644 (file)
@@ -62,6 +62,7 @@ namespace clitk {
     void SetInputFilenames(const std::vector<std::string> & filenames);
     void EnableReadOnDisk(bool b);
     void EnableWriteOnDisk(bool b);
+    void EnableWriteCompression(bool b);
     void SetOutputFilename(const std::string & filename);
     void AddOutputFilename(const std::string filename);
     void SetOutputFilenames(const std::vector<std::string> & filenames);
@@ -94,6 +95,8 @@ namespace clitk {
   protected:  
     bool m_ReadOnDisk;
     bool m_WriteOnDisk;
+    bool m_WriteCompression;
+
     /// Call this function to dispatch an output towards the correct sink
     template<class ImageType> 
     void SetNextOutput(typename ImageType::Pointer output);
index b9380a2e2ff476421d98676a2d0c592b861683d0..07384efe5cc9e965e9f07e3ed33655128a68a5c2 100644 (file)
@@ -700,11 +700,13 @@ int clitk::XdrImageIO::ReadImageInformationWithError()
         SetOrigin(i,10*p[0]);
 
         //Test if rectilinear image is actually uniform (tolerance 0.1 mm)
-        for (j=0; j<GetDimensions(i)-1; j++) {
-          if (fabs((p[j+1]-p[j])*10-GetSpacing(i))>0.1) {
-            free(points);
-            fclose(fstream);
-            return ER_NOT_HANDLED;
+        if(i<3) { // Only for first 3 dimensions because spacing is barely used in other dims
+          for (j=0; j<GetDimensions(i)-1; j++) {
+            if (fabs((p[j+1]-p[j])*10-GetSpacing(i))>0.1) {
+              free(points);
+              fclose(fstream);
+              return ER_NOT_HANDLED;
+            }
           }
         }
         p += (int)GetDimensions(i);
index 1c2f6a3a76eb601964a73c5b0f2e4846493c4e78..32d31fe51075bf235a8256d9d8066f38d7bf509a 100644 (file)
 #include "itkConnectedComponentImageFilter.h"
 #include "itkStatisticsImageFilter.h"
 #include "itkCastImageFilter.h"
-#include "itkDifferenceImageFilter.h"
+#if ITK_VERSION_MAJOR >= 4
+  #include "itkTestingComparisonImageFilter.h"
+#else
+  #include "itkDifferenceImageFilter.h"
+#endif
 #include "itkThresholdImageFilter.h"
 
 namespace clitk 
index 82e28e6e6c421be11de171eae8a1b7733791b30e..8e30eb39e6dbb4efeae79b8a6493d1094a4d22d0 100644 (file)
@@ -68,7 +68,11 @@ namespace clitk
     typedef itk::StatisticsImageFilter<InternalImageType> StatisticsImageFilterType;
     typedef itk::BinaryBallStructuringElement<InternalPixelType,InputImageDimension > KernelType;
     typedef clitk::ConditionalBinaryDilateImageFilter<InternalImageType, InternalImageType , KernelType> ConditionalBinaryDilateImageFilterType;
+#if ITK_VERSION_MAJOR >= 4
+    typedef itk::Testing::ComparisonImageFilter<InternalImageType, InternalImageType> DifferenceImageFilterType;
+#else
     typedef itk::DifferenceImageFilter<InternalImageType, InternalImageType> DifferenceImageFilterType;
+#endif
     typedef itk::CastImageFilter<InternalImageType, OutputImageType> OutputCastImageFilterType;
     typedef clitk::SetBackgroundImageFilter<InternalImageType, InternalImageType, InternalImageType> SetBackgroundImageFilterType;
 
index 091e36cb57f5eac7a56e58a381475806e97a88e2..a31fe349856f97799509af9fe6ce4e328012d5d1 100644 (file)
 #include "itkBSplineDerivativeKernelFunction.h"
 #include "itkCentralDifferenceImageFunction.h"
 #include "itkBSplineInterpolateImageFunction.h"
-#include "itkBSplineDeformableTransform.h"
+#if ITK_VERSION_MAJOR >= 4
+  #include "itkBSplineTransform.h"
+#else
+  #include "itkBSplineDeformableTransform.h"
+#endif
 #include "itkArray2D.h"
 
 namespace itk
@@ -471,10 +475,17 @@ private:
   /**
    * Typedefs for the BSplineDeformableTransform.
    */
+#if ITK_VERSION_MAJOR >= 4
+  typedef BSplineTransform<
+  CoordinateRepresentationType,
+  ::itk::GetImageDimension<FixedImageType>::ImageDimension,
+  DeformationSplineOrder> BSplineTransformType;
+#else
   typedef BSplineDeformableTransform<
   CoordinateRepresentationType,
   ::itk::GetImageDimension<FixedImageType>::ImageDimension,
   DeformationSplineOrder> BSplineTransformType;
+#endif
   typedef typename BSplineTransformType::WeightsType
   BSplineTransformWeightsType;
   typedef typename BSplineTransformType::ParameterIndexArrayType
index f13fe2aa81b9d950cdb80795f5f0d640d92ae947..852583b8373c52a804e9e007b329bf07edd6c645 100644 (file)
 #include "itkImageRegionIterator.h"
 #include "itkImageIterator.h"
 #include "vnl/vnl_math.h"
-#include "itkBSplineDeformableTransform.h"
+#if ITK_VERSION_MAJOR >= 4
+  #include "itkBSplineTransform.h"
+#else
+  #include "itkBSplineDeformableTransform.h"
+#endif
 
 namespace itk
 {
diff --git a/scripts/common.sh b/scripts/common.sh
deleted file mode 100755 (executable)
index e06bf25..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#! /bin/sh
-
-
-MAX_THREADS=2
-
-check_threads()
-{
-    while [[ $(jobs -p | wc -l) -ge $1 ]]; do
-        jobs
-        sleep 10
-    done
-}
-
-
diff --git a/scripts/create_mhd_3D.sh b/scripts/create_mhd_3D.sh
new file mode 100755 (executable)
index 0000000..fbb9760
--- /dev/null
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+
+#################################################################################
+# create_mhd_3D        argument : {image data} raw_image nom_fichier_de_sortie #
+#################################################################################
+if [ $# -lt 1 ] 
+then
+    echo "Usage: create_mhd_3D.sh dimx dimy dimz spcx spcy spcz offx offy offz pixel_type raw_image_file output_file"
+    echo "dim*: dimensions of the image"
+    echo "spc*: pixel spacing along each dimension"
+    echo "off*: offset along each dimension"
+    echo "pixel_type: CHAR, UCHAR, SHORT, USHORT, FLOAT"
+    echo "raw_image_file: image to be referenced by the mhd file created"
+    echo "output_file: mhd to be created"
+    exit 1
+fi
+
+# can point to existing raw files
+n=`ls ${11} | wc -l`
+if [ $n -eq 0 ] 
+then
+    echo "${11} does not exist. Cannot create mhd file."
+    exit 
+fi
+
+# check if the raw file has the "raw" extension
+n=`ls ${11} | grep .raw | wc -l`
+if [ $n -eq 0 ] 
+then
+    # change extension to raw
+    raw_base=`echo ${11} | cut -d . -f 1`; 
+    raw_file=$raw_base".raw"; 
+    mv ${11} $raw_file
+else
+    raw_file=${11}
+fi
+
+# create file (with some default values...)
+echo "NDims = 3" > ${12}
+echo "TransformMatrix = 1 0 0 0 1 0 0 0 1" >> ${12}
+echo "Offset = " $7 $8 $9 >> ${12}
+echo "CenterOfRotation = 0 0 0" >> ${12}
+echo "AnatomicalOrientation = RAI" >> ${12}
+echo "ElementSpacing = " $4 $5 $6 >> ${12}
+echo "DimSize = " $1 $2 $3 >> ${12}
+echo "ElementType = MET_"${10} >> ${12}
+echo "ElementDataFile = " $raw_file >> ${12}
+
+
diff --git a/scripts/create_mhd_4D-2.0.sh b/scripts/create_mhd_4D-2.0.sh
new file mode 100755 (executable)
index 0000000..c10e098
--- /dev/null
@@ -0,0 +1,49 @@
+#!/bin/sh +x
+
+
+write_mhd_4D()
+{
+  cat $orig | sed "s/NDims = .*/NDims = 4/
+                 s/TransformMatrix = .*/TransformMatrix = 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1/
+                 /Offset/ s/.*/& 0/
+                 /CenterOfRotation/ s/.*/& 0/
+                 s/AnatomicalOrientation = .*/AnatomicalOrientation = ????/
+                 /ElementSpacing/ s/.*/& 1/
+                 /DimSize/ s/.*/& $nbph/
+                 s/ElementDataFile = .*/ElementDataFile = LIST/" > "$1/$file_name_4D"
+  
+  for ph in $listph
+  do
+    phase=`basename $ph`
+    echo "$phase" >> "$1/$file_name_4D"
+  done
+}
+
+#################################################
+# create_mhd_4D        argument : repertoire   #
+#################################################
+if [ $# -lt 1 ]
+then
+  echo "Usage: create_mhd_4D.sh DIRECTORY"
+  exit 1
+fi
+
+dirname=`dirname $1`
+pattern=`basename $1`
+
+list_phase_file=`ls -1 $1*[0-9].mhd`
+nb_phase_file=`ls -1 $1*[0-9].mhd | wc -l`
+if [ $nb_phase_file = 0 ]
+then
+  echo "Error: no phase found"
+  exit 1
+fi
+
+nbph=$nb_phase_file
+orig=`echo $list_phase_file | cut -f 1 -d ' '`
+listph=`echo $list_phase_file | sed 's:\.mhd:\.raw:g'`
+
+file_name_4D=`echo "${pattern}4D.mhd"`
+
+write_mhd_4D $dirname
+echo "$dirname/$file_name_4D"
diff --git a/scripts/create_mhd_4D_pattern.sh b/scripts/create_mhd_4D_pattern.sh
new file mode 100755 (executable)
index 0000000..4d64347
--- /dev/null
@@ -0,0 +1,60 @@
+#!/bin/sh +x
+
+###############################################################################
+#
+# FILE: create_mhd_pattern.sh
+# AUTHOR: Rômulo Pinho 05/08/2011
+#
+# Similar to create_mhd_4D.sh, but receives a pattern as input.
+# 
+# Example:
+# create_mhd_pattern.sh "<path>/all_my_phases_start_like_this_"
+#
+###############################################################################
+
+write_mhd_4D()
+{
+  cat $orig | sed "s/NDims = .*/NDims = 4/
+                 s/TransformMatrix = .*/TransformMatrix = 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1/
+                 /Offset/ s/.*/& 0/
+                 /CenterOfRotation/ s/.*/& 0/
+                 s/AnatomicalOrientation = .*/AnatomicalOrientation = ????/
+                 /ElementSpacing/ s/.*/& 1/
+                 /DimSize/ s/.*/& $nbph/
+                 s/ElementDataFile = .*/ElementDataFile = LIST/" > "$1/$file_name_4D"
+  
+  for ph in $listph
+  do
+    phase=`basename $ph`
+    echo "$phase" >> "$1/$file_name_4D"
+  done
+}
+
+#################################################
+# create_mhd_4D        argument : repertoire   #
+#################################################
+if [ $# -lt 1 ]
+then
+  echo "Usage: $0 PATTERN"
+  exit 1
+fi
+
+dirname=`dirname $1`
+pattern=`basename $1`
+
+list_phase_file=`ls -1 $1*[0-9].mhd`
+nb_phase_file=`ls -1 $1*[0-9].mhd | wc -l`
+if [ $nb_phase_file = 0 ]
+then
+  echo "Error: no phase found"
+  exit 1
+fi
+
+nbph=$nb_phase_file
+orig=`echo $list_phase_file | cut -f 1 -d ' '`
+listph=`echo $list_phase_file | sed 's:\.mhd:\.raw:g'`
+
+file_name_4D=`echo "${pattern}4D.mhd"`
+
+write_mhd_4D $dirname
+echo "$dirname/$file_name_4D"
diff --git a/scripts/create_midP-2.0.sh b/scripts/create_midP-2.0.sh
new file mode 100755 (executable)
index 0000000..93290c8
--- /dev/null
@@ -0,0 +1,209 @@
+#!/bin/sh -x
+
+###############################################################################
+#
+# FILE: create_midP-2.0.sh
+# AUTHOR: Rômulo Pinho 05/08/2011
+#
+# Version 2.0 of the create_midP.sh script. The most relevant changes are:
+#   * receives a .conf file as input, with variables related to the registration
+#   parameters and to paramters of the script itself (see accompanying midp_template.conf)
+#   for details.
+#   * separates execution steps: it's now possible to choose which operation to execute
+#   (mask, registration, midp, or all).
+#   * some steps are now in different modules, to facilitate re-use (see "includes" section).
+#   * minor modifications on output file names.
+#   * attempt to simplify the code a bit.
+#
+###############################################################################
+
+######################### includes
+
+source `dirname $0`/create_midP_masks-2.0.sh using-as-lib 2 nn
+source `dirname $0`/registration.sh
+source `dirname $0`/midp_common.sh
+
+registration()
+{
+  echo
+  echo "----------- Registration ------------"
+  start=`date`
+  echo "start: $start"
+  echo
+
+  mkdir -p $vf_dir
+  mkdir -p $output_dir
+
+  # banded images may be created as separate files,
+  # with the specified preffix, which is interesting for debugging. 
+  # if blank, it means that the original images (those without bands) 
+  # will be used (see create_midP_masks-2.0.sh for details).
+  banded="banded_"
+
+  # params read from conf file
+  params="$nb_iter $nb_samples $sampling_algo $nb_hist_bins $nb_levels $bspline_spacing $metric $optimizer $interpolator"
+
+  # register all phases to the reference
+  for i in $( seq 0 $((${#phase_files[@]} - 1))); do
+    phase_file=${phase_files[$i]}
+    phase_nb=${phase_nbs[$i]}
+    
+    if [ "$phase_nb" != "$ref_phase_nb" ]; then
+      # inside params
+      reference_in=$mask_dir/${banded}inside_$ref_phase_nb.mhd
+      target_in=$mask_dir/${banded}inside_$phase_nb.mhd
+      mask_ref_in=$mask_dir/mask_inside_$ref_phase_nb.mhd
+      mask_targ_in=$mask_dir/mask_inside_$phase_nb.mhd
+      vf_in=$vf_dir/vf_inside_${ref_phase_nb}_$phase_nb.mhd
+      result_in=$output_dir/result_inside_${ref_phase_nb}_$phase_nb.mhd
+      log_in=$log_dir/log_inside_${ref_phase_nb}_$phase_nb.log
+
+      # outside params
+      reference_out=$mask_dir/${banded}outside_$ref_phase_nb.mhd
+      target_out=$mask_dir/${banded}outside_$phase_nb.mhd
+      mask_ref_out=$mask_dir/mask_outside_$ref_phase_nb.mhd
+      mask_targ_out=$mask_dir/mask_outside_$phase_nb.mhd
+      vf_out=$vf_dir/vf_outside_$ref_phase_nb\_$phase_nb.mhd
+      result_out=$output_dir/result_outside_$ref_phase_nb\_$phase_nb.mhd
+      log_out=$log_dir/log_outside_${ref_phase_nb}_$phase_nb.log
+
+      # registration
+      if [ "$method" == "blutdir" ]; then
+        registration_blutdir $reference_in $target_in $mask_ref_in $mask_targ_in $vf_in $result_in $params $log_in
+        registration_blutdir $reference_out $target_out $mask_ref_out $mask_targ_out $vf_out $result_out $params $log_out
+      elif [ "$method" == "elastix" ]; then
+        registration_elastix $reference_in $target_in $mask_ref_in $mask_targ_in $vf_in $result_in $params $log_in
+        registration_elastix $reference_out $target_out $mask_ref_out $mask_targ_out $vf_out $result_out $params $log_out
+      fi
+
+      # combine in and out vf
+      motion_mask=$mask_dir/mm_$phase_nb.mhd
+      vf_result=$vf_dir/vf_${ref_phase_nb}_$phase_nb.mhd
+      clitkCombineImage -i $vf_in -j $vf_out -m $motion_mask -o $vf_result
+      clitkZeroVF -i $vf_in -o vf_zero.mhd
+      clitkCombineImage -i $vf_result -j vf_zero.mhd -m $patient_mask -o $vf_result
+      rm vf_zero.*
+
+      # save for later...
+      vf_ref=$vf_in
+    fi
+  done
+
+  # create (zero) vf from reference to reference
+  clitkZeroVF -i $vf_ref -o $vf_dir/vf_${ref_phase_nb}_${ref_phase_nb}.mhd
+
+  # create 4D vf
+  create_mhd_4D_pattern.sh $vf_dir/vf_${ref_phase_nb}_
+
+  echo
+  echo "-------- Registration done ! --------"
+  end=`date`
+  echo "start: $start"
+  echo "end: $end"
+  echo
+}
+
+midp()
+{
+  echo
+  echo "----------- Mid-position ------------"
+  start=`date`
+  echo "start: $start"
+  echo
+
+  mkdir -p $midp_dir
+
+  ########### calculate the midp wrt the reference phase
+  phase_nb=$ref_phase_nb
+  echo "Calculating midp_$phase_nb.mhd..."
+  vf_midp=$midp_dir/vf_$phase_nb\_midp.mhd
+  midp=$midp_dir/midp_$phase_nb.mhd
+  # average the vf's from reference phase to phase
+  clitkAverageTemporalDimension -i $vf_dir/vf_${ref_phase_nb}_4D.mhd -o $vf_midp
+  # invert the vf (why?)
+  clitkInvertVF -i $vf_midp -o $vf_midp
+  # create the midp by warping the reference phase with the reference vf
+  clitkWarpImage -i $ref_phase_file -o $midp --vf=$vf_midp -s 1
+
+  ref_vf_midp=$vf_midp
+  ref_midp=$midp
+  clitkImageConvert -i $ref_midp -o $ref_midp -t float
+
+  ########### calculate the midp wrt the other phases
+  for i in $( seq 0 $((${#phase_files[@]} - 1))); do
+    phase_file=${phase_files[$i]}
+    phase_nb=${phase_nbs[$i]}
+    vf_midp=$midp_dir/vf_$phase_nb\_midp.mhd
+    midp=$midp_dir/midp_$phase_nb.mhd
+
+    if [ "$phase_nb" != "$ref_phase_nb" ]; then
+      echo "Calculating midp_$phase_nb.mhd..."
+      # calculate vf from phase to midp, using the vf from reference phase to midp (-i)
+      # and the vf from reference phase to phase (-j)
+      clitkComposeVF -i $ref_vf_midp -j $vf_dir/vf_$ref_phase_nb\_$phase_nb.mhd -o $vf_midp
+      clitkWarpImage -i $phase_file -o $midp --vf=$vf_midp -s 1
+      clitkImageConvert -i $midp -o $midp -t float
+    fi
+  done
+
+  create_mhd_4D_pattern.sh $midp_dir/midp_
+  echo "Calculating midp_avg.mhd..."
+  clitkAverageTemporalDimension -i $midp_dir/midp_4D.mhd -o $midp_dir/midp_avg.mhd
+  echo "Calculating midp_med.mhd..."
+  clitkMedianTemporalDimension -i $midp_dir/midp_4D.mhd -o $midp_dir/midp_med.mhd
+
+  # clean-up
+  rm $midp_dir/vf_*
+      
+  echo
+  echo "-------- Mid-position done ! --------"
+  end=`date`
+  echo "start: $start"
+  echo "end: $end"
+  echo
+}
+
+
+
+######################### main
+
+if [ $# != 3 ]; then
+  echo "Usage: create_midP-2.0.sh CT_4D REF_PHASE CONF_FILE"
+  exit -1
+fi
+
+echo
+echo "--------------- START ---------------"
+begining=`date --rfc-3339=seconds`
+# echo "beginning: $begining"
+echo
+
+# variable declarations
+mhd4d=$1
+ref_phase=$2
+conf=$3
+source $conf
+
+mkdir -p $log_dir
+mask_dir="MASK-${mask_interpolation_spacing}mm-$mask_interpolation_algorithm"
+
+extract_4d_phases_ref $mhd4d $ref_phase
+
+if [ "$step" == "mask" -o "$step" == "all" ]; then
+  motion_mask $mhd4d $mask_interpolation_spacing $mask_interpolation_algorithm 
+fi 
+
+if [ "$step" == "registration" -o "$step" == "all" ]; then
+  registration
+fi 
+
+if [ "$step" == "midp" -o "$step" == "all" ]; then
+  midp
+fi 
+
+echo
+echo "---------------- END ----------------"
+terminating=`date --rfc-3339=seconds`
+echo "beginning: $begining"
+echo "terminating: $terminating"
+echo
diff --git a/scripts/create_midP.sh b/scripts/create_midP.sh
new file mode 100755 (executable)
index 0000000..7591efb
--- /dev/null
@@ -0,0 +1,535 @@
+#!/bin/sh -x
+
+#################################################################
+# create_MidP  arguments : CT_4D.mhd ref_phase spacing         #
+#################################################################
+source `dirname $0`/midp_common.sh
+
+extract_patient()
+{
+  echo "$image_name -> Extracting patient..."
+  $CLITK/clitkExtractPatient -i $image_name -o MASK/patient_$image_name --noAutoCrop
+  $CLITK/clitkBinarizeImage -i MASK/patient_$image_name -o MASK/patient_$image_name -l 1 -u 1 --mode=BG
+  $CLITK/clitkSetBackground -i $image_name -o MASK/patient_only_$image_name --mask MASK/patient_$image_name --outsideValue -1000
+}
+
+extract_bones()
+{
+  echo "$image_name -> Extracting bones..."
+  $CLITK/clitkImageConvert -i $image_name -o MASK/float_$image_name -t float
+  $CLITK/clitkExtractBones -i MASK/float_$image_name -o MASK/bones_$image_name --lower1 120 --upper1 2000 --lower2 70 --upper2 2000 --smooth --time 0.0625 --noAutoCrop
+  $CLITK/clitkMorphoMath -i MASK/bones_$image_name -o MASK/bones_$image_name --type 2 --radius 4,4,2
+}
+
+resample()
+{
+  echo "$image_name -> Resampling..."
+  $CLITK/clitkResampleImage -i MASK/patient_$image_name -o MASK/patient_$image_name --spacing $spacing
+  $CLITK/clitkResampleImage -i MASK/patient_only_$image_name -o MASK/patient_only_$image_name --spacing $spacing
+  #$CLITK/clitkResampleImage -i MASK/bones_$image_name -o MASK/bones_$image_name --like MASK/patient_only_$image_name
+}
+
+compute_motion_mask()
+{
+#   $CLITK/clitkMotionMask -i MASK/patient_only_$image_name -o MASK/mm_$image_name --featureBones=MASK/bones_$image_name --upperThresholdLungs -400 --fillingLevel 94 --offsetDetect 0,-5,0 --pad --writeFeature=MASK/feature_$image_name --writeEllips=MASK/inital_ellipse_$image_name --writeGrownEllips=MASK/growing_ellipse_$image_name;
+$CLITK/clitkMotionMask -i MASK/patient_only_$image_name -o MASK/mm_$image_name --upperThresholdLungs -400 --fillingLevel 94 --offsetDetect 0,-5,0 --pad --writeFeature=MASK/feature_$image_name --writeEllips=MASK/inital_ellipse_$image_name --writeGrownEllips=MASK/growing_ellipse_$image_name;
+}
+
+set_background()
+{
+  echo "$image_name -> Setting Background..."
+  $CLITK/clitkSetBackground -i MASK/patient_only_$image_name -o MASK/inside_$image_name --mask MASK/mm_$image_name --outsideValue -1200
+  $CLITK/clitkSetBackground -i MASK/patient_only_$image_name -o MASK/outside_$image_name --mask MASK/mm_$image_name --outsideValue -1200 --fg
+}
+
+create_registration_masks()
+{
+  echo "$image_name -> Creating registration masks..."
+  $CLITK/clitkMorphoMath -i MASK/mm_$image_name -o MASK/regmask_in_$image_name --type 1 --radius 8
+  $CLITK/clitkExtractPatient -i MASK/outside_$image_name -o MASK/regmask_out_$image_name --noAutoCrop
+  $CLITK/clitkMorphoMath -i MASK/regmask_out_$image_name -o MASK/regmask_out_$image_name --type 1 --radius 8
+}
+
+remove_files()
+{
+  echo "Removing temporary files..."
+  image_name_base=`echo $image_name | sed 's/mhd//'`
+  case $1 in
+    1)
+      rm MASK/float_$image_name_base*;;
+    2)
+      rm MASK/bones_$image_name_base*;;
+    3)
+      rm MASK/patient_only_$image_name_base*;;
+    4)
+      #rm MASK/patient_$image_name_base*
+      #rm MASK/mm_$image_name_base*
+      rm -f $vf_dir/vf_tmp_in_${ref}_${phase}.*
+      rm -f $vf_dir/vf_tmp_out_${ref}_${phase}.*
+      #rm MASK/regmask_in_$image_name_base*
+      #rm MASK/regmask_out_$image_name_base*
+      ;;
+    5)
+#       rm -f coeff_*
+      #rm $vf_dir/vf_in_*
+      #rm $vf_dir/vf_out_*
+#       rm MASK/regmask_*
+#       rm MASK/mm_*
+      ;;
+    6)
+      ;;
+      #rm -f $vf_dir/_4D.*
+      #rm -f $vf_dir/vf_MIDP_${ref}.*
+      #rm -f $vf_dir/vf_${ref}_MIDP.*;;
+    7)
+      ;; #rm $vf_dir/vf_MIDP_${phase}.*;;
+    8)
+      rm $vf_dir/*.txt
+      rm $vf_dir/*.log
+  esac
+}
+
+mm_preprocessing()
+{
+  extract_patient
+  #extract_bones
+  remove_files 1
+  resample
+}
+
+mm_postprocessing()
+{
+  remove_files 2
+  set_background
+  remove_files 3
+  create_registration_masks
+}
+
+# mm_workflow()
+# {
+#   extract_patient
+#   extract_bones
+#   remove_files 1
+#   resample
+#   echo "$image_name -> Computing motion mask..."
+#   compute_motion_mask >> LOG/motion_mask_$image_name.log
+#   remove_files 2
+#   set_background
+#   remove_files 3
+#   create_registration_masks
+# }
+
+motion_mask()
+{
+  echo
+  echo "------------ Motion mask ------------"
+  start=`date`
+  echo "start: $start"
+  echo
+  mkdir -p "MASK"
+  rm -f "LOG/motion_mask*.log"
+  regmask_in_list=""
+  regmask_out_list=""
+  reg_in_list=""
+  reg_out_list=""
+
+  # multi-threaded pre-processing for motion mask calcs
+  for phase in $phase_list
+  do
+    image_name=`echo $phase | sed 's/raw/mhd/'`
+    check_threads $MAX_THREADS
+    #mm_preprocessing &
+  done
+
+  # single-threaded motion mask calc
+  check_threads 1
+  for phase in $phase_list
+  do
+    image_name=`echo $phase | sed 's/raw/mhd/'`
+
+    echo "$image_name -> Computing motion mask..."
+    #compute_motion_mask >> LOG/motion_mask_$image_name.log
+  done
+
+  # multi-threaded post-processing of motion mask calcs
+  for phase in $phase_list
+  do
+    image_name=`echo $phase | sed 's/raw/mhd/'`
+    check_threads $MAX_THREADS 
+    #mm_postprocessing &
+    regmask_in_list="$regmask_in_list regmask_in_$image_name"
+    regmask_out_list="$regmask_out_list regmask_out_$image_name"
+    reg_in_list="$reg_in_list inside_$image_name"
+    reg_out_list="$reg_out_list outside_$image_name"
+  done
+
+  wait
+  echo
+  echo "-------- Motion mask done ! ---------"
+  end=`date`
+  echo "start: $start"
+  echo "end: $end"
+  echo
+}
+
+compute_BLUTDIR()
+{
+  ########## register in ##########
+  for reg_in in $reg_in_list
+  do
+    if [ ! -z `echo $reg_in | grep "$phase"` ]
+    then
+      target_in=$reg_in
+    fi
+  done
+  echo "Computing BLUTDIR $reference_in -> $target_in ..."
+  #$CLITK/clitkBLUTDIR --reference="MASK/$reference_in" --target="MASK/$target_in" --output="MASK/reg_$target_in" --referenceMask="MASK/$reference_mask_in" --vf="$vf_dir/vf_in_${ref}_${phase}.mhd" $coeff_in_ini --coeff="$coeff_dir/coeff_in_${ref}_${phase}.mhd" $registration_parameters_BLUTDIR >> LOG/registration_${ref}_${phase}.log
+  $CLITK/clitkBLUTDIR --reference="MASK/$reference_in" --target="MASK/$target_in" --output="MASK/reg_$target_in" --referenceMask="MASK/$reference_mask_in" --vf="$vf_dir/vf_in_${ref}_${phase}.mhd" --coeff="$coeff_dir/coeff_in_${ref}_${phase}.mhd" $registration_parameters_BLUTDIR >> LOG/registration_${ref}_${phase}.log
+  coeff_in_ini="--initCoeff=$coeff_dir/coeff_in_${ref}_${phase}.mhd"
+  ########## register out ##########
+  for reg_out in $reg_out_list
+  do
+    if [ ! -z `echo $reg_out | grep "$phase"` ]
+    then
+      target_out=$reg_out
+    fi
+  done
+  echo "Computing BLUTDIR $reference_out -> $target_out ..."
+  #$CLITK/clitkBLUTDIR --reference="MASK/$reference_out" --target="MASK/$target_out" --output="MASK/reg_$target_out" --referenceMask="MASK/$reference_mask_out" --vf="$vf_dir/vf_out_${ref}_${phase}.mhd" $coeff_out_ini --coeff="$coeff_dir/coeff_out_${ref}_${phase}.mhd" $registration_parameters_BLUTDIR >> LOG/registration_${ref}_${phase}.log
+  $CLITK/clitkBLUTDIR --reference="MASK/$reference_out" --target="MASK/$target_out" --output="MASK/reg_$target_out" --referenceMask="MASK/$reference_mask_out" --vf="$vf_dir/vf_out_${ref}_${phase}.mhd" --coeff="$coeff_dir/coeff_out_${ref}_${phase}.mhd" $registration_parameters_BLUTDIR >> LOG/registration_${ref}_${phase}.log
+  coeff_out_ini="--initCoeff=$coeff_dir/coeff_out_${ref}_${phase}.mhd"
+  ##################################
+  $CLITK/clitkCombineImage -i $vf_dir/vf_in_${ref}_${phase}.mhd -j $vf_dir/vf_out_${ref}_${phase}.mhd -m MASK/mm_$image_name -o $vf_dir/vf_${ref}_${phase}.mhd
+  $CLITK/clitkZeroVF -i $vf_dir/vf_${ref}_${phase}.mhd -o $vf_dir/vf_${ref}_${ref}.mhd
+  $CLITK/clitkCombineImage -i $vf_dir/vf_${ref}_${phase}.mhd -j $vf_dir/vf_${ref}_${ref}.mhd -m MASK/patient_$image_name -o $vf_dir/vf_${ref}_${phase}.mhd
+  remove_files 4
+}
+
+compute_DEMONSDIR()
+{
+  ########## register in ##########
+  for reg_in in $reg_in_list
+  do
+    if [ ! -z `echo $reg_in | grep "_$phase"` ]
+    then
+      target_in=$reg_in
+    fi
+  done
+  echo "Computing DEMONSDIR $reference_in -> $target_in ..."
+  $CLITK/clitkDemonsDeformableRegistration --reference="MASK/$reference_in" --target="MASK/$target_in" --output="MASK/reg_$target_in" --vf="$vf_dir/vf_in_${ref}_${phase}.mhd" $vf_in_ini $registration_parameters_DEMONSDIR #&>> LOG/registration_${ref}_${phase}.log
+  vf_in_ini="--init=$vf_dir/vf_in_${ref}_${phase}.mhd"
+  ########## register out ##########
+  for reg_out in $reg_out_list
+  do
+    if [ ! -z `echo $reg_out | grep "_$phase"` ]
+    then
+      target_out=$reg_out
+    fi
+  done
+  echo "Computing DEMONSDIR $reference_out -> $target_out ..."
+  $CLITK/clitkDemonsDeformableRegistration --reference="MASK/$reference_out" --target="MASK/$target_out" --output="MASK/reg_$target_out" --vf="$vf_dir/vf_out_${ref}_${phase}.mhd" $vf_out_ini $registration_parameters_DEMONSDIR #&>> LOG/registration_${ref}_${phase}.log
+  vf_out_ini="--init=$vf_dir/vf_out_${ref}_${phase}.mhd"
+  ##################################
+  $CLITK/clitkCombineImage -i $vf_dir/vf_in_${ref}_${phase}.mhd -j $vf_dir/vf_out_${ref}_${phase}.mhd -m MASK/mm_$image_name -o $vf_dir/vf_${ref}_${phase}.mhd
+  $CLITK/clitkZeroVF -i $vf_dir/vf_${ref}_${phase}.mhd -o $vf_dir/vf_${ref}_${ref}.mhd
+  $CLITK/clitkCombineImage -i $vf_dir/vf_${ref}_${phase}.mhd -j $vf_dir/vf_${ref}_${ref}.mhd -m MASK/patient_$image_name -o $vf_dir/vf_${ref}_${phase}.mhd
+  remove_files 4
+}
+
+compute_ELASTIX()
+{
+  ########## register in ##########
+  for reg_in in $reg_in_list
+  do
+    if [ ! -z `echo $reg_in | grep "_$phase"` ]
+    then
+      target_in=$reg_in
+    fi
+  done
+  echo "Computing ELASTIX $reference_in -> $target_in ..."
+  exec_dir=`which elastix`
+  exec_dir=`dirname $exec_dir`
+  cat $exec_dir/params_BSpline.txt | sed -e "s+<NbIterations>+500+" \
+                              -e "s+<LabelsFile>++" \
+                              -e "s+<HistBins>+25+" \
+                              -e "s+<Levels>+3+" \
+                              -e "s+<NbSamples>+2000+" \
+                              -e "s+<SamplerType>+Random+" \
+                              -e "s+<Spacing>+32+" > params_BSpline.txt 
+  elastix -f "MASK/$reference_in" -m "MASK/$target_in" -fMask "MASK/$reference_mask_in" -out $vf_dir -p params_BSpline.txt > /dev/null
+  transformix -tp $vf_dir/TransformParameters.0.txt -out $vf_dir -def all > /dev/null  
+  mv $vf_dir/deformationField.mhd $vf_dir/vf_in_${ref}_${phase}.mhd
+  mv $vf_dir/deformationField.raw $vf_dir/vf_in_${ref}_${phase}.raw
+  sed -i "s:deformationField:vf_in_${ref}_${phase}:" $vf_dir/vf_in_${ref}_${phase}.mhd
+  mv $vf_dir/result.0.mhd MASK/reg_$target_in
+  targetraw=`echo reg_$target_in | sed 's:mhd:raw:'`
+  sed -i "s:result.0.mhd:$targetraw" MASK/reg_$target_in
+  mv $vf_dir/result.0.raw MASK/$targetraw
+  remove_files 8
+
+  ########## register out ##########
+  for reg_out in $reg_out_list
+  do
+    if [ ! -z `echo $reg_out | grep "_$phase"` ]
+    then
+      target_out=$reg_out
+    fi
+  done
+  echo "Computing ELASTIX $reference_out -> $target_out ..."
+  elastix -f "MASK/$reference_out" -m "MASK/$target_out" -fMask "MASK/$reference_mask_out" -out $vf_dir -p params_BSpline.txt > /dev/null
+  transformix -tp $vf_dir/TransformParameters.0.txt -out $vf_dir -def all > /dev/null  
+  mv $vf_dir/deformationField.mhd $vf_dir/vf_out_${ref}_${phase}.mhd
+  mv $vf_dir/deformationField.raw $vf_dir/vf_out_${ref}_${phase}.raw
+  sed -i "s:deformationField:vf_out_${ref}_${phase}:" $vf_dir/vf_out_${ref}_${phase}.mhd
+  mv $vf_dir/result.0.mhd MASK/reg_$target_out
+  targetraw=`echo reg_$target_out | sed 's:mhd:raw:'`
+  sed -i "s:result.0.mhd:$targetraw" MASK/reg_$target_out
+  mv $vf_dir/result.0.raw MASK/$targetraw
+  remove_files 8
+
+  ##################################
+  $CLITK/clitkCombineImage -i $vf_dir/vf_in_${ref}_${phase}.mhd -j $vf_dir/vf_out_${ref}_${phase}.mhd -m MASK/mm_$image_name -o $vf_dir/vf_${ref}_${phase}.mhd
+  $CLITK/clitkZeroVF -i $vf_dir/vf_${ref}_${phase}.mhd -o $vf_dir/vf_${ref}_${ref}.mhd
+  $CLITK/clitkCombineImage -i $vf_dir/vf_${ref}_${phase}.mhd -j $vf_dir/vf_${ref}_${ref}.mhd -m MASK/patient_$image_name -o $vf_dir/vf_${ref}_${phase}.mhd
+  remove_files 4
+}
+
+registration()
+{
+  echo
+  echo "----------- Registration ------------"
+  start=`date`
+  echo "start: $start"
+  echo
+
+  rm -f "LOG/registration*.log"
+
+  # wait any unfinished threads
+  check_threads 1
+
+  for reg_in in $reg_in_list
+  do
+    if [ ! -z `echo $reg_in | grep "$ref"` ]
+    then
+      reference_in=$reg_in
+    fi
+  done
+  for reg_out in $reg_out_list
+  do
+    if [ ! -z `echo $reg_out | grep "$ref"` ]
+    then
+      reference_out=$reg_out
+    fi
+  done
+  for regmask_in in $regmask_in_list
+  do
+    if [ ! -z `echo $regmask_in | grep "$ref"` ]
+    then
+      reference_mask_in=$regmask_in
+    fi
+  done
+  for regmask_out in $regmask_out_list
+  do
+    if [ ! -z `echo $regmask_out | grep "$ref"` ]
+    then
+      reference_mask_out=$regmask_out
+    fi
+  done
+
+  registration_parameters_BLUTDIR="--spacing=32,32,32 --interp=2 --metric=11 --bins=25 --samples=1 --levels=3 --verbose " #--coeffEveryN 5"
+  registration_parameters_DEMONSDIR="--demons=3 --levels=1"
+  registration_parameters_ELASTIX="--demons=3 --levels=1"
+
+  coeff_in_ini=""
+  coeff_out_ini=""
+  vf_in_ini=""
+  vf_out_ini=""
+  
+  for phase in $list_phases
+  do
+    for img in $phase_list
+    do
+      if [ ! -z `echo $img | grep "$phase" | grep -v "[0-9]$phase"` ]
+      then
+       image_name=`echo $img | sed 's/raw/mhd/'`
+      fi
+    done
+    if [ $method = 1 ]
+    then
+      compute_BLUTDIR
+    elif [ $method = 2 ]
+    then
+      compute_DEMONSDIR
+    elif [ $method = 3 ]
+    then
+      compute_ELASTIX
+    fi
+  done
+  remove_files 5
+
+  echo
+  echo "-------- Registration done ! --------"
+  end=`date`
+  echo "start: $start"
+  echo "end: $end"
+  echo
+}
+
+calculate_vf_MIDP_REF()
+{
+  echo "Calculating vf_REF_MIDP.mhd..."
+  remove_files 6
+  create_mhd_4D.sh $vf_dir #"vf_4D.mhd"
+  $CLITK/clitkAverageTemporalDimension -i $vf_dir/_4D.mhd -o $vf_dir/vf_${ref}_MIDP.mhd
+  $CLITK/clitkInvertVF -i $vf_dir/vf_${ref}_MIDP.mhd -o $vf_dir/vf_MIDP_${ref}.mhd
+}
+
+calculate_CT_MIDP_REF()
+{
+  reference=`ls *.mhd | grep $ref #| grep -v "[0-9]$ref.mhd"`
+  echo "Calculating CT_MIDP_REF.mhd '$reference'..."
+  $CLITK/clitkWarpImage -i $reference -o CT_MIDP_REF.mhd --vf=$vf_dir/vf_MIDP_${ref}.mhd -s 1
+}
+
+calculate_CT_MIDP_PHASE()
+{
+  echo "Calculating CT_MIDP_${phase}.mhd..."
+  $CLITK/clitkComposeVF -i $vf_dir/vf_MIDP_${ref}.mhd -j $vf_dir/vf_${ref}_${phase}.mhd -o $vf_dir/vf_MIDP_${phase}.mhd
+  phase_img=`ls *.mhd | grep "${phase}" # | grep -v "[0-9]$ref.mhd"`
+  $CLITK/clitkWarpImage -i $phase_img -o MIDP/CT_MIDP_${phase}.mhd --vf=$vf_dir/vf_MIDP_${phase}.mhd -s 1
+  $CLITK/clitkImageConvert -i MIDP/CT_MIDP_${phase}.mhd -o MIDP/CT_MIDP_${phase}.mhd -t float
+  remove_files 7
+}
+
+prepare_MIDP_images()
+{
+  echo "Preparing MIDP images..."
+  cp CT_MIDP_REF.mhd MIDP/CT_MIDP_${ref}.mhd
+  cp CT_MIDP_REF.raw MIDP/CT_MIDP_${ref}.raw
+  cat MIDP/CT_MIDP_${ref}.mhd | sed "s/ElementDataFile = .*/ElementDataFile = CT\_MIDP\_${ref}\.raw/" > MIDP/CT_MIDP_${ref}_tmp.mhd
+  rm MIDP/CT_MIDP_${ref}.mhd
+  mv MIDP/CT_MIDP_${ref}_tmp.mhd MIDP/CT_MIDP_${ref}.mhd
+  $CLITK/clitkImageConvert -i MIDP/CT_MIDP_${ref}.mhd -o MIDP/CT_MIDP_${ref}.mhd -t float
+  create_mhd_4D.sh MIDP #"CT_MIDP_4D.mhd"
+}
+
+calculate_CT_MIDP_MOY()
+{
+  echo "Calculating CT_MIDP_MOY.mhd..."
+  $CLITK/clitkAverageTemporalDimension -i MIDP/_4D.mhd -o CT_MIDP_MOY.mhd
+}
+
+calculate_CT_MIDP_MED()
+{
+  echo "Calculating CT_MIDP_MED.mhd..."
+  $CLITK/clitkMedianTemporalDimension -i MIDP/_4D.mhd -o CT_MIDP_MED.mhd
+}
+
+calculate_CT_MIDP_MIP()
+{
+  echo "Calculating CT_MIDP_MIP.mhd..."
+  $CLITK/clitkMIP -i MIDP/_4D.mhd -o CT_MIDP_MIP.mhd -d 3
+}
+
+mid_position()
+{
+  echo
+  echo "----------- Mid-position ------------"
+  start=`date`
+  echo "start: $start"
+  echo
+  
+  mkdir -p "MIDP"
+
+  calculate_vf_MIDP_REF
+  calculate_CT_MIDP_REF
+  for phase in $list_phases
+  do  
+    check_threads $MAX_THREADS
+    calculate_CT_MIDP_PHASE &
+  done
+  wait
+  prepare_MIDP_images
+  calculate_CT_MIDP_MED &
+  calculate_CT_MIDP_MIP &
+  calculate_CT_MIDP_MOY &
+  wait
+      
+  echo
+  echo "-------- Mid-position done ! --------"
+  end=`date`
+  echo "start: $start"
+  echo "end: $end"
+  echo
+}
+
+#################
+#      main    #
+#################
+
+if [ $# -lt 1 ]
+then
+    echo "Usage: create_midP.sh CT_4D.mhd ref_phase computation_spacing(mm) method(1:BSPLINE, 2:DEMONS)"
+    exit 1
+fi
+CLITK=~/creatis/clitk3/build/bin
+CT_4D_path=$1
+CT_4D=`basename $CT_4D_path`
+work_dir=`dirname $CT_4D_path`
+cd $work_dir
+ref=$2
+spacing=$3
+method=$4
+
+vf_dir="VF"
+coeff_dir="$vf_dir/coeff"
+
+mkdir -p $vf_dir
+mkdir -p $coeff_dir
+
+echo
+echo "--------------- START ---------------"
+begining=`date`
+echo "start: $begining"
+echo
+
+mkdir -p "LOG"
+phase_list=`grep ".raw" $CT_4D`
+echo "phases -> " $phase_list
+nb_phases=`grep ".raw" $CT_4D | wc -l`
+gt_ref=""
+lt_ref=""
+
+phase_files=( `cat $CT_4D | grep ".raw" | sed 's:.raw:.mhd:'` )
+echo "Phase files are ${phase_files[@]}"
+
+phase_nbs=( `echo ${phase_files[@]} | grep -o '[[:alpha:][:punct:]][0-9]\{1,2\}[[:punct:]]' | grep -o '[0-9]\{1,2\}'` )
+#phase_nbs=( `echo ${phase_files[@]} | grep -o '[0-9]\{1,2\}'` )  
+echo "Phase numbers are ${phase_nbs[@]}"
+
+
+for ph in $phase_list
+do
+  #ph_nb=`echo $ph | grep -o "[0-9][0-9]*\.raw" | sed -e 's/\.raw//'`
+  ph_nb=`echo $ph | grep -o "[0-9][0-9]"`  
+  if [ $ph_nb -gt $ref ]
+  then
+    gt_ref="$gt_ref $ph_nb"
+  elif [ $ph_nb -lt $ref ]
+  then
+    lt_ref="$lt_ref $ph_nb"
+  fi
+done
+list_phases="$gt_ref $lt_ref"
+echo list_phases $list_phases
+
+motion_mask
+registration
+mid_position
+
+echo
+echo "---------------- END ----------------"
+terminating=`date`
+echo "start: $begining"
+echo "end: $terminating"
+echo
diff --git a/scripts/create_midP_masks-2.0.sh b/scripts/create_midP_masks-2.0.sh
new file mode 100755 (executable)
index 0000000..8a8babf
--- /dev/null
@@ -0,0 +1,258 @@
+#! /bin/bash -x
+
+###############################################################################
+#
+# FILE: create_midP-2.0.sh
+# AUTHOR: Rômulo Pinho 05/08/2011
+#
+# Version 2.0 of the create_midP_masks.sh script. The most relevant changes are:
+#   * creation of bands around input and output image regions to try to improve 
+#   the registration along lung boundaries (naturally, it depends on the quality
+#   of motion mask generation).
+#   * some steps are now in different modules, to facilitate re-use (see "includes" section).
+#   * minor modifications on output file names.
+#   * attempt to simplify the code a bit.
+#
+###############################################################################
+
+source `dirname $0`/midp_common.sh
+
+extract_patient()
+{
+  echo "$phase_file -> Extracting patient..."
+  clitkExtractPatient -i $phase_file -o $mask_dir_tmp/patient_mask_$phase_nb.mhd --noAutoCrop -a $afdb_file $ExtractPatientExtra
+  clitkSetBackground -i $phase_file -o $mask_dir_tmp/patient_$phase_nb.mhd --mask $mask_dir_tmp/patient_mask_$phase_nb.mhd --outsideValue -1000
+}
+
+extract_bones()
+{
+  if [ x = x$ExtractBonesLower1 ]; then
+    ExtractBonesLower1=120
+  fi
+  if [ x = x$ExtractBonesLower2 ]; then
+    ExtractBonesLower2=80
+  fi
+  echo "$phase_file -> Extracting bones..."
+  clitkImageConvert -i $phase_file -o $mask_dir_tmp/float_$phase_nb.mhd -t float
+  clitkExtractBones -i $mask_dir_tmp/float_$phase_nb.mhd -o $mask_dir_tmp/bones_$phase_nb.mhd -a $afdb_file --lower1 $ExtractBonesLower1 --upper1 2000 --lower2 $ExtractBonesLower2 --upper2 2000 --smooth --time 0.0625 --noAutoCrop
+}
+
+extract_lungs()
+{
+  echo "$phase_file -> Extracting lungs..."
+  clitkExtractLung -i $phase_file -o $mask_dir_tmp/lungs_$phase_nb.mhd -a $afdb_file --noAutoCrop
+}
+
+resample()
+{
+  echo "$phase_file -> Resampling..."
+  clitkResampleImage -i $mask_dir_tmp/patient_$phase_nb.mhd -o $mask_dir_tmp/patient_$phase_nb.mhd --spacing $resample_spacing --interp $resample_algo
+
+  clitkResampleImage -i $mask_dir_tmp/lungs_$phase_nb.mhd -o $mask_dir_tmp/lungs_$phase_nb.mhd --like $mask_dir_tmp/patient_$phase_nb.mhd
+}
+
+compute_motion_mask()
+{
+  if [ x = x$MotionMaskOffsetDetect ]; then
+    MotionMaskOffsetDetect="0,-5,0"
+  fi
+  if [ x = x$FillingLevel ]; then
+    FillingLevel=94
+  fi
+
+  clitkMotionMask -i $mask_dir_tmp/patient_$phase_nb.mhd -o $mask_dir_tmp/mm_$phase_nb.mhd --featureLungs $mask_dir_tmp/lungs_$phase_nb.mhd --upperThresholdLungs -400 --fillingLevel $FillingLevel --offsetDetect $MotionMaskOffsetDetect --pad --writeFeature=$mask_dir_tmp/feature_$phase_nb.mhd $MotionMaskExtra 
+  #--monitor=$mask_dir_tmp/monitor_$phase_nb.mhd
+}
+
+create_banded_mask()
+{
+  input=$1
+  input_mask=$2
+  output=$3
+  output_mask=$4
+  radius=$5
+
+  input_dir=`dirname $input`
+  input_base=`basename $input`
+
+  # first band
+  clitkMorphoMath -i $input_mask -o $input_dir/extra1_$input_base --type 1 --radius $radius
+  clitkImageArithm -i $input_dir/extra1_$input_base -j $input_mask -o $input_dir/band1_$input_base -t 7
+  clitkBinarizeImage -i $input_dir/band1_$input_base -o $input_dir/band1_$input_base -l 1 -u 1 --fg 100 --mode both
+  clitkImageConvert -i $input_dir/band1_$input_base -o $input_dir/short_band1_$input_base -t short
+  
+  # second band
+  clitkMorphoMath -i $input_dir/extra1_$input_base -o $input_dir/extra2_$input_base --type 1 --radius $radius
+  clitkImageArithm -i $input_dir/extra2_$input_base -j $input_dir/extra1_$input_base -o $input_dir/band2_$input_base -t 7
+  clitkBinarizeImage -i $input_dir/band2_$input_base -o $input_dir/band2_$input_base -l 1 -u 1 --fg 200 --mode both
+  clitkImageConvert -i $input_dir/band2_$input_base -o $input_dir/short_band2_$input_base -t short
+  
+  # combine bands with masks
+  clitkImageArithm -i $input_mask -j $input_dir/band1_$input_base -o $output_mask -t 0
+  clitkImageArithm -i $output_mask -j $input_dir/band2_$input_base -o $output_mask -t 0
+  # combine bands with image
+  clitkCombineImage -i $input_dir/short_band1_$input_base -j $input -m $input_dir/band1_$input_base -o $output
+  clitkCombineImage -i $input_dir/short_band2_$input_base -j $output -m $input_dir/band2_$input_base -o $output
+
+  # clean-up
+  rm `echo $input_dir/extra?_$input_base | sed 's:.mhd:.*:g'`
+  rm `echo $input_dir/band?_$input_base | sed 's:.mhd:.*:g'`
+  rm `echo $input_dir/short_band?_$input_base | sed 's:.mhd:.*:g'`
+}
+
+create_registration_masks()
+{
+  # extract inside and outside lung regions from the patient image, 
+  # using the motion mask computed previously
+  echo "$phase_file -> Setting Background..."
+  clitkSetBackground -i $mask_dir_tmp/patient_$phase_nb.mhd -o $mask_dir_tmp/inside_$phase_nb.mhd --mask $mask_dir_tmp/mm_$phase_nb.mhd --outsideValue -1200
+  clitkSetBackground -i $mask_dir_tmp/patient_$phase_nb.mhd -o $mask_dir_tmp/outside_$phase_nb.mhd --mask $mask_dir_tmp/mm_$phase_nb.mhd --outsideValue -1200 --fg
+
+  # the registration masks for inside (and outside) region correspond
+  # to the motion mask (and its complement) plus extra grey value bands,
+  # obtained with morphological dilations.
+  # 
+  echo "$phase_file -> Creating registration masks..."
+  # inside
+  create_banded_mask $mask_dir_tmp/inside_$phase_nb.mhd $mask_dir_tmp/mm_$phase_nb.mhd $mask_dir_tmp/banded_inside_$phase_nb.mhd $mask_dir_tmp/mask_inside_$phase_nb.mhd 4
+  # outside 
+  clitkExtractPatient -i $mask_dir_tmp/outside_$phase_nb.mhd -o $mask_dir_tmp/mm_outside_$phase_nb.mhd --noAutoCrop
+  create_banded_mask $mask_dir_tmp/outside_$phase_nb.mhd $mask_dir_tmp/mm_outside_$phase_nb.mhd $mask_dir_tmp/banded_outside_$phase_nb.mhd $mask_dir_tmp/mask_outside_$phase_nb.mhd 4
+}
+
+mm_preprocessing()
+{
+  extract_patient
+  # extract_bones
+  extract_lungs
+  # remove_tmp_masks 1
+  resample
+}
+
+mm_postprocessing()
+{
+  # remove_tmp_masks 2
+  # remove_tmp_masks 3
+  create_registration_masks
+}
+
+motion_mask()
+{
+  #set cmd line variables
+  mhd4d=$1
+  resample_spacing=$2
+  resample_algo=$3
+
+  dir=`dirname $1`
+  cd $dir
+    
+  # import variables specific to each patient
+  source ./variables
+
+  #set other global variables
+  mask_dir="MASK-${resample_spacing}mm-$resample_algo"
+  mask_dir_tmp="tmp.$mask_dir"
+  extract_4d_phases $mhd4d
+
+  echo
+  echo "------------ Motion mask from create_midP_masks.sh ------------"
+  start=`date`
+  echo "start: $start"
+  echo
+
+  # the motion masks are first created in a tmp directory. this directory is 
+  # later going to be renamed to the final motion mask directory. concurrent
+  # executions trying to create the same set of masks will be blocked until
+  # the first execution finishes. naturally, these other executions will not
+  # recreate the masks. so first we try to create the tmp directory. 
+  # if the creation fails, it means that another execution is
+  # already creating the masks, so this execution will be blocked. the
+  # execution is unblocked only when the creation of masks is finished and
+  # the mask directory is renamed.
+  #
+  # ATTENTION: RP - 08/02/2011
+  # robustness issue: tmp directory may exist but may be empty or 
+  # incomplete. the solution is to check per file, but I'll leave it like 
+  # this for the moment.
+  do_mm=0
+  if [ $(ls -d $mask_dir 2> /dev/null | wc -l) -eq 0 ]; then
+    mkdir $mask_dir_tmp 2> /dev/null
+    return_mkdir=$?
+    if [ $return_mkdir == 0 ]; then
+      do_mm=1 
+    else
+      while [[ $(ls -d $mask_dir 2> /dev/null | wc -l) -eq 0 ]]; do
+        echo "waiting creation of motion masks..."
+        sleep 2
+      done
+      echo "finished waiting"
+    fi  
+  fi
+  
+#   do_mm=1
+#   mask_dir_tmp=$mask_dir
+  if [ $do_mm == 1 ]; then
+    mask_log_dir=$mask_dir_tmp/LOG
+    mkdir -p $mask_log_dir
+
+    # multi-threaded pre-processing for motion mask calcs
+    for i in $( seq 0 $((${#phase_nbs[@]} - 1))); do
+      phase_nb=${phase_nbs[$i]}
+      phase_file=${phase_files[$i]}
+      afdb_file=`echo $phase_file | sed 's/mhd/afdb/'`
+
+      check_threads $MAX_THREADS
+      mm_preprocessing &
+    done
+
+    # single-threaded motion mask calc
+    for i in $( seq 0 $((${#phase_nbs[@]} - 1))); do
+      phase_nb=${phase_nbs[$i]}
+      phase_file=${phase_files[$i]}
+
+      check_threads 1
+      echo "$phase_file -> Computing motion mask..."
+      compute_motion_mask > $mask_log_dir/motion_mask_$phase_file.log
+    done
+
+    # multi-threaded post-processing of motion mask calcs
+    for i in $( seq 0 $((${#phase_nbs[@]} - 1))); do
+      phase_nb=${phase_nbs[$i]}
+      phase_file=${phase_files[$i]}
+
+      check_threads $MAX_THREADS 
+      mm_postprocessing &
+    done
+
+    # rename tmp mask directory after mask creation
+    check_threads 1
+    mv -f $mask_dir_tmp $mask_dir
+  fi
+
+  echo
+  echo "-------- Motion mask done ! ---------"
+  end=`date`
+  echo "start: $start"
+  echo "end: $end"
+  echo
+}
+
+
+#################
+# main  #
+#################
+
+if [ $# != 3 ]; then
+  echo "Usage: $0 CT_4D RESAMPLE_SPACING RESAMPLE_ALGORITHM"
+  exit -1
+fi
+
+#
+# variables exported in this scope
+#
+# mask_dir: directory where all masks are kept
+#
+
+if [ $1 != "using-as-lib" ]; then
+  motion_mask $1 $2 $3
+fi
index 9c851770f931e7a28d83d120611bafbae0ba7a1b..845237d6a31dd3a4923fdc7acd4786b262b073c1 100755 (executable)
@@ -1,6 +1,6 @@
 #! /bin/bash -x
 
-common.sh
+source `dirname $0`/midp_common.sh
 
 extract_patient()
 {
@@ -241,7 +241,7 @@ fi
 #
 # variables exported in this scope
 #
-# mask_dir: directory where all mask are kept
+# mask_dir: directory where all masks are kept
 # regmask_in_list: list of registration mask files (inside lungs)
 # regmask_out_list: list of registration mask files (outised lungs)
 # reg_in_list: list of registration image files (inside lungs)
diff --git a/scripts/midp_common.sh b/scripts/midp_common.sh
new file mode 100755 (executable)
index 0000000..0f76707
--- /dev/null
@@ -0,0 +1,110 @@
+#! /bin/sh +x
+
+###############################################################################
+#
+# FILE: midp_common.sh
+# AUTHOR: Rômulo Pinho 05/08/2011
+#
+# Helper file with many functions used in the midP scripts.
+#
+###############################################################################
+
+
+# block execution untill the number of threads (jobs) launched by the
+# current process is below the given number of threads. 
+MAX_THREADS=2
+check_threads()
+{
+  nbth=$1
+  while [[ $(jobs -p | wc -l) -ge $nbth ]]; do
+      jobs
+      sleep 10
+  done
+}
+
+#
+# receive a 4D file and and extract the corresponding phase numbers
+# export the variables containing each of the extracted data
+#
+extract_4d_phase_numbers()
+{
+  mhd4d=$1
+
+  nb_phases=${#phase_files[@]}
+
+  # get everything except numbers and punctuation
+  cat $mhd4d | grep ".raw" | sed 's:.raw:.mhd:' | sed 's/.mhd//' | grep -o "[^0-9[:punct:]]*" | sort -u > /tmp/patterns.txt
+
+  # find which patterns have the phases connected to it
+  patterns=`cat /tmp/patterns.txt`
+  if [ -z "$patterns" ]; then
+    phase_nbs=( `cat $mhd4d | grep ".raw" | sed 's:.raw:.mhd:' | sed 's/.mhd//' | grep "[0-9]\+"` )
+  else
+    for i in $patterns; do 
+
+      # check if the pattern appears before the phase number
+      nb_phases_found=`cat $mhd4d | grep ".raw" | sed 's:.raw:.mhd:' | sed 's/.mhd//' | grep -o "$i[0-9[:punct:]]\+" | sort -u | wc -l`
+      if [ $nb_phases_found == $nb_phases ]; then
+        # keep only what identifies the phase number
+        phase_nbs=( `cat $mhd4d | grep ".raw" | sed 's:.raw:.mhd:' | sed 's/.mhd//' | grep -o "$i[0-9[:punct:]]\+" | grep -o "[^${i}]\+" | grep -o "[0-9]\+[[:punct:]]*[0-9]*" | grep -o "[0-9]*[[:punct:]]*[0-9]\+"` ) 
+        break
+      fi
+    
+      # check if the pattern appears after the phase number
+      nb_phases_found=`cat $mhd4d | grep ".raw" | sed 's:.raw:.mhd:' | sed 's/.mhd//' | grep -o "[0-9[:punct:]]\+$i" | sort -u | wc -l`
+      if [ $nb_phases_found == $nb_phases ]; then
+        # keep only what identifies the phase number
+        phase_nbs=( `cat $mhd4d | grep ".raw" | sed 's:.raw:.mhd:' | sed 's/.mhd//' | grep -o "[0-9[:punct:]]\+$i" | grep -o "[^${i}]\+" | grep -o "[0-9]\+[[:punct:]]*[0-9]*" | grep -o "[0-9]*[[:punct:]]*[0-9]\+"` ) 
+        break
+      fi
+
+    done
+  fi
+
+  echo "Phase numbers are ${phase_nbs[@]}"
+  rm /tmp/patterns.txt
+}
+
+#
+# receive a 4D file and extract the corresponding phase files, 
+# and phase numbers.
+# export the variables containing each of the extracted data
+#
+extract_4d_phases()
+{
+  mhd4d=$1
+
+  echo "4D file is $mhd4d"
+
+  # array of phase files
+  phase_files=( `cat $mhd4d | grep ".raw" | sed 's:.raw:.mhd:'` )
+  echo "Phase files are ${phase_files[@]}"
+
+  extract_4d_phase_numbers $mhd4d 
+}
+
+
+#
+# receive a 4D file and the reference phase number as input 
+# and extract the corresponding phase files, phase numbers, 
+# and reference phase file. 
+#
+# export the variables containing each of the extracted data
+#
+extract_4d_phases_ref()
+{
+  extract_4d_phases $1
+
+  # reference phase file
+  ref_phase_file=`cat $mhd4d | grep ".raw" | sed 's:.raw:.mhd:' | grep $2`
+  echo "Reference phase is $ref_phase_file"
+
+  # reference phase number
+  for i in $( seq 0 $((${#phase_nbs[@]} - 1))); do
+    ref_phase_nb=`echo ${phase_nbs[$i]} | grep $2`
+    if [ -n "$ref_phase_nb" ]; then
+      echo "Reference phase number is $ref_phase_nb"
+      break
+    fi
+  done
+}
diff --git a/scripts/midp_template.conf b/scripts/midp_template.conf
new file mode 100644 (file)
index 0000000..8fde2c8
--- /dev/null
@@ -0,0 +1,67 @@
+###############################################################################
+#
+# FILE: midp_template.conf
+# AUTHOR: Rômulo Pinho 05/08/2011
+#
+# Template configuration file for create_midP-2.0.sh. Values between <> must be
+# changed according to the methods.
+#
+###############################################################################
+
+# output directories
+vf_dir="<VFDIR>"
+midp_dir="<MIDPDIR>"
+output_dir="<OUTDIR>"
+log_dir="<LOGDIR>"
+
+# script step to be executed (mask, registration, midp, all)
+# midp depends on registration, which depends on mask
+step="all"
+
+# mask parameters
+#
+# interpolation algorithm for resampling (see clitkResampleImage)
+mask_interpolation_algorithm="<MASK_INTERPOLATION_ALGORITHM>"
+# interpolation spacing (in mm)
+mask_interpolation_spacing=<MASK_INTERPOLATION_SPACING>
+
+# registration method (blut, elastix)
+method="<METHOD>"
+
+# registration parameters (depend on registration method - see descriptions)
+#
+
+# b-spline spacing (blut, elastix)
+bspline_spacing=<BSPLINE_SPACING>
+
+# multi-resolution levels
+nb_levels=<NB_LEVELS>
+
+# number of histogram bins (blut, elastix)
+nb_hist_bins=<NB_HIST_BINS>
+
+# number of points (samples) to calculate metric
+# (blut: percentage of image size; elastix: absolute number)
+nb_samples=<NBSAMPLES>
+
+# algorithm used to sample points for the metric
+# (elastix: see docs)
+sampling_algo="<SAMPLING_ALGO>"
+
+# number of iterations (blut, elastix)
+nb_iter=<NB_ITER>
+
+# tolerance (stop condition for the metric) (blut)
+tolerance=<TOLERANCE>
+
+# metric used in the registration
+# (blut: see clitkBLUTDIR; elastix: see docs)
+metric="<METRIC>"
+
+# interpolation type
+# (blut: see clitkBLUTDIR; elastix: see docs)
+interpolator="<INTERPOLATOR>"
+
+# optmizer
+# (blut: see clitkBLUTDIR; elastix: see docs)
+optimizer="<OPTIMIZER>"
diff --git a/scripts/pts_to_landmarks.sh b/scripts/pts_to_landmarks.sh
new file mode 100755 (executable)
index 0000000..87bc9ee
--- /dev/null
@@ -0,0 +1,27 @@
+#! /bin/sh
+
+###############################################################################
+#
+# FILE: pts_to_landmarks
+# AUTHOR: Vivien Delmon
+#
+# Conversion from landmarks in the format used in clitkCalculateTRE (.pts) 
+# to the format used in VV (.txt).
+#
+###############################################################################
+
+if [ $# -ne 2 ]; then
+  echo "Usage: $0 input.pts output.txt" 1>&2
+fi
+
+to_append=/tmp/$RANDOM
+to_prepend=/tmp/$RANDOM
+
+for i in $(seq 0 $((`cat $1 | wc -l` - 1)));
+do
+  echo 0' '0 >> $to_append
+  echo $i >> $to_prepend
+done
+
+echo "LANDMARKS1" > $2
+paste -d ' ' $to_prepend $1 $to_append >> $2
diff --git a/scripts/registration.sh b/scripts/registration.sh
new file mode 100755 (executable)
index 0000000..40d5fbe
--- /dev/null
@@ -0,0 +1,124 @@
+#! /bin/sh
+
+###############################################################################
+#
+# FILE: registration.sh
+# AUTHOR: Rômulo Pinho 05/08/2011
+#
+# Helper file with registration functions using different methods.
+# Each function receives a set of parameters that overall apply to any
+# registration algorithm, as follows:
+# 
+# reference=$1 : reference (fixed) image
+# target=$2 : target (moving) image
+# mask_ref=$3 : mask for the reference image
+# mask_targ=$4 : mask for the moving image
+# vf=$5 : output vector field representing the registration
+# result=$6 : result image after applying the vector field
+# nb_iter=$7 : maximum number of iterations
+# nb_samples=$8 : number of image samples used in the metric calulcation
+# sampling_algo=$9 : algorithm used in the selection of image samples
+# hist_bins=${10} : number of histogram bins used in the metric calculation
+# nb_levels=${11} : number of image resolutions
+# spacing=${12} : spacing of the b-spline grid of the fines resolution
+# metric=${13} : metric algorithm
+# optimizer=${14} : optimizer
+# interpolator=${15} : image interpolator 
+# log=${16} : log file
+#
+# New registration functions may be added to this file at any moment, 
+# respecting the interface defined above.
+#
+###############################################################################
+
+
+################# BLUTDIR #####################
+registration_blutdir()
+{
+  reference=$1
+  target=$2
+  mask_ref=$3
+  mask_targ=$4
+  vf=$5
+  result=$6
+  nb_iter=$7
+  nb_samples=$8
+  sampling_algo=$9
+  hist_bins=${10}
+  nb_levels=${11}
+  spacing=${12}
+  metric=${13}
+  optimizer=${14}
+  interpolator=${15}
+  log=${16}
+
+  echo "Computing BLUTDIR $reference -> $target ..."
+  blutdir_params="--levels $nb_levels  --metric $metric --optimizer $optimizer --samples $nb_samples --spacing $spacing,$spacing,$spacing --bins $hist_bins --maxIt $nb_iter --interp $interpolator --verbose"
+  cmd="clitkBLUTDIR -r $reference -t $target -m $mask_ref --targetMask $mask_targ --vf $vf -o $result $blutdir_params"
+  $cmd > $log
+}
+
+################# ELASTIX #####################
+registration_elastix()
+{
+  reference=$1
+  target=$2
+  mask_ref=$3
+  mask_targ=$4
+  vf=$5
+  result=$6
+  nb_iter=$7
+  nb_samples=$8
+  sampling_algo=$9
+  hist_bins=${10}
+  nb_levels=${11}
+  spacing=${12}
+  metric=${13}
+  optimizer=${14}
+  interpolator=${15}
+  
+  ########## register in ##########
+  for reg_in in $reg_in_list
+  do
+    if [ ! -z `echo $reg_in | grep "_$phase"` ]
+    then
+      target_in=$reg_in
+    fi
+  done
+  echo "Computing ELASTIX $reference -> $target ..."
+  exec_dir=`which elastix`
+  exec_dir=`dirname $exec_dir`
+  suffix=${nb_samples}_${nb_iter}_${nb_levels}
+  cat $exec_dir/params_BSpline.txt | sed -e "s+<NbIterations>+$nb_iter+" \
+                              -e "s+<LabelsFile>++" \
+                              -e "s+<HistBins>+$hist_bins+" \
+                              -e "s+<Levels>+$nb_levels+" \
+                              -e "s+<NbSamples>+$nb_samples+" \
+                              -e "s+<SamplerType>+$sampling_algo+" \
+                              -e "s+<Spacing>+$spacing+" > params_BSpline_${suffix}.txt 
+
+  vf_dir=`dirname $vf`
+  vf_base=`basename $vf .mhd`
+  result_dir=`dirname $result`
+  result_base=`basename $result .mhd`
+
+  # image registration
+  cmd="elastix -f $reference -m $target -fMask $mask_ref -mMask $mask_targ -out $result_dir -p params_BSpline_${suffix}.txt"
+  $cmd  > /dev/null
+
+  # generate vector field
+  cmd="transformix -tp $result_dir/TransformParameters.0.txt -out $vf_dir -def all"
+  $cmd  > /dev/null
+
+  # post-processing
+  mv $vf_dir/deformationField.mhd $vf
+  mv $vf_dir/deformationField.raw `echo $vf | sed 's/mhd/raw/'`
+  sed -i "s+deformationField+$vf_base+" $vf
+
+  mv $result_dir/result.0.mhd $result
+  mv $result_dir/result.0.raw `echo $result | sed 's/mhd/raw/'`
+  sed -i "s+result.0+$result_base+" $result
+
+  mv $result_dir/elasitx.log $log
+  mv $result_dir/TransformParameters.0.txt $result_dir/${result_base}_TransformParameters.0.txt
+}
\ No newline at end of file
index a253ca9adc6c592df00c5523cb554b5cf408229d..3d5e87f63900a6220e18e2f8eaa380113fada321 100644 (file)
@@ -43,7 +43,7 @@ ADD_TEST(clitkGetDirection_3d ${exe} clitkGetDirection -i ${p}Lung3D.mhd      ${p}Lu
 #=========================================================
 # clitkBinarize
 ADD_TEST(clitkBinarizeBGl0.1356_4d ${exe} clitkBinarizeImage -i ${p}Deformation4D.mhd --mode BG -l 0.1356 -o Deformation4D_ref.binarizeBGl0.1356.mhd ${p}Deformation4D_ref.binarizeBGl0.1356)
-ADD_TEST(clitkBinarizeFGl0.1556_3d ${exe} clitkBinarizeImage -i ${p}Lung3D.mhd        --mode FG -l 0.1556 -o Deformation3D_ref.binarizeFGl0.1556.mhd ${p}Deformation3D_ref.binarizeFGl0.1556)
+ADD_TEST(clitkBinarizeFGl0.1556_3d ${exe} clitkBinarizeImage -i ${p}Lung3D.mhd        --mode FG -l 0.1556 -o Lung3D_ref.binarizeFGl0.1556.mhd ${p}Lung3D_ref.binarizeFGl0.1556)
 
 UNSET(tmpFile)
 UNSET(exe)
index bdd7d7447079b062ff8dd221bea4b8816f584425..e79de4027db17c788f7207fe923c51a8e6768403 100644 (file)
@@ -38,7 +38,7 @@ IF (CLITK_BUILD_TOOLS)
   WRAP_GGO(clitkImageInfo_GGO_C clitkImageInfo.ggo)
   ADD_EXECUTABLE(clitkImageInfo clitkImageInfo.cxx ${clitkImageInfo_GGO_C})
   TARGET_LINK_LIBRARIES(clitkImageInfo clitkCommon ${ITK_LIBRARIES})
-  SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkDicom2Image)
+  SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkImageInfo)
 
   ADD_EXECUTABLE(clitkImageConvert clitkImageConvert.cxx)
   TARGET_LINK_LIBRARIES(clitkImageConvert clitkImageConvertLib clitkCommon ${ITK_LIBRARIES})
index 7b14021ab28d9b13abd6159c17715172b9ecb33a..297b63711f6c107f389ea487b9049221582a4b44 100644 (file)
@@ -56,6 +56,7 @@ int main(int argc, char * argv[])
   filter->SetInputFilenames(l);
   filter->SetIOVerbose(args_info.verbose_flag);
   filter->SetOutputFilename(args_info.output_arg);
+  filter->EnableWriteCompression(args_info.compression_flag);
   if (args_info.type_given) filter->SetOutputPixelType(args_info.type_arg);
 
   // Go !
index 22e32916e4f76736b312cea8f00461c62cb2ae7f..395b43542655cbaf7bd5535bd9e4811750d77e46 100644 (file)
@@ -8,3 +8,4 @@ option "input"          i  "Input image filename"                       string  no multiple
 option "output"        o  "Output image filename"                      string  yes
 option "type"          t  "Output type (float, ushort ...)"            string  no
 option "verbose"       v  "Verbose"                                    flag    off
+option "compression"    c  "Compress output"                                   flag    off
index 253b49315a0e546850f8bd6b679f7029fed259b7..f23e2771ff5fe2d4821f63aafee59b6c747dcc01 100644 (file)
@@ -184,22 +184,23 @@ namespace clitk
 
       // Take the median
       double value;
+      typename InputImageType::IndexValueType temporal_dimension = size4D[Dimension-1];
+      std::vector<PixelType> temp(temporal_dimension);
       while (!(iterators[0]).IsAtEnd()) {
         value=0.;
-        std::vector<PixelType> temp;
-        for (unsigned int i=0; i<size4D[Dimension-1]; i++) {
-          temp.push_back(iterators[i].Get());
+        for (unsigned int i=0; i<temporal_dimension; i++) {
+          temp[i] = iterators[i].Get();
           ++(iterators[i]);
         }
-        if (temp.size() % 2) {
-          nth_element(temp.begin(),temp.begin()+((temp.size()-1)/2+1),temp.end());
-          value=temp[(temp.size()-1)/2];
+        if (temporal_dimension & 1) {
+          nth_element(temp.begin(), temp.begin() + temporal_dimension/2,temp.end());
+          value = temp[temporal_dimension/2];
         } else {
-          nth_element(temp.begin(),temp.begin()+(temp.size())/2,temp.end());
-          value=temp[temp.size()/2];
-          nth_element(temp.begin(),temp.begin()+ (temp.size()/2+1),temp.end());
-          value+=temp[temp.size()/2+1];
-          value/=2;
+          nth_element(temp.begin(), temp.begin() + temporal_dimension/2 - 1, temp.end());
+          value = temp[temporal_dimension/2 - 1];
+          nth_element(temp.begin(), temp.begin() + temporal_dimension/2, temp.end());
+          value += temp[temporal_dimension/2];
+          value /= 2;
         }
         avIt.Set(value);
         ++avIt;
index ea84d18674c8712845468accfffb6707d6a28913..86745a419363ad9d97194b0e9ccdf921c39ee39e 100644 (file)
@@ -36,6 +36,7 @@ void write_points_txt(const std::string& fileName, const PointArrayType& points,
 void read_points_pts(const std::string& fileName, PointArrayType& points);
 void write_points_pts(const std::string& fileName, const PointArrayType& points);
 
+void apply_spacing(const PointArrayType& input, const double* spacing, PointArrayType& output);
 void transform_points(const PointArrayType& input, const MatrixType& matrix, PointArrayType& output);
 
 
@@ -46,8 +47,6 @@ int main(int argc, char** argv)
   GGO(clitkTransformLandmarks, args_info);
   verbose = args_info.verbose_flag;
 
-  MatrixType matrix = clitk::ReadMatrix3D(args_info.matrix_arg);
-
   TxtDataArrayType data;
   PointArrayType inputPoints;
   if (strcmp(args_info.type_arg, "txt") == 0) {
@@ -58,13 +57,29 @@ int main(int argc, char** argv)
   }
   
   PointArrayType outputPoints;
-  transform_points(inputPoints, matrix, outputPoints);
+  PointArrayType spacingPoints;
+  PointArrayType* workingInputPoints = &inputPoints;
+  PointArrayType* workingOutputPoints = &outputPoints;
+  if (args_info.spacing_given) {
+    if (verbose) std::cout << "Processing spacing..." << std::endl;
+    
+    apply_spacing(*workingInputPoints, args_info.spacing_arg, spacingPoints);
+    workingInputPoints = &spacingPoints;
+    workingOutputPoints = &spacingPoints;
+  }
+
+  MatrixType matrix;
+  if (args_info.matrix_given) {
+    matrix = clitk::ReadMatrix3D(args_info.matrix_arg);
+    transform_points(*workingInputPoints, matrix, outputPoints);
+    workingOutputPoints = &outputPoints;
+  }
 
   if (strcmp(args_info.type_arg, "txt") == 0) {
-    write_points_txt(args_info.output_arg, outputPoints, data);
+    write_points_txt(args_info.output_arg, *workingOutputPoints, data);
   }
   else {
-    write_points_pts(args_info.output_arg, outputPoints);
+    write_points_pts(args_info.output_arg, *workingOutputPoints);
   }
   
   return 0;
@@ -74,14 +89,14 @@ void read_points_txt(const std::string& fileName, PointArrayType& points, TxtDat
 {
   std::ifstream landmarksFile(fileName.c_str());
   if (landmarksFile.fail()) {
-    std::cout << "ERROR: could not open '" << fileName << "'" << std::endl;
+    std::cerr << "ERROR: could not open '" << fileName << "'" << std::endl;
     exit(-2);
   }
   
   std::string line;
   std::getline(landmarksFile, line);
   if (line.find("LANDMARKS") == std::string::npos) {
-    std::cout << "ERROR: invalid landmarks file '" << fileName << "'" << std::endl;
+    std::cerr << "ERROR: invalid landmarks file '" << fileName << "'" << std::endl;
     exit(-3);
   }
   
@@ -119,14 +134,14 @@ void read_points_pts(const std::string& fileName, PointArrayType& points)
 {
   std::ifstream landmarksFile(fileName.c_str());
   if (landmarksFile.fail()) {
-    std::cout << "ERROR: could not open '" << fileName << "'" << std::endl;
+    std::cerr << "ERROR: could not open '" << fileName << "'" << std::endl;
     exit(-2);
   }
   
   std::string line;
   std::getline(landmarksFile, line);
   if (line.find("#X") != 0) {
-    std::cout << "ERROR: invalid landmarks file '" << fileName << "'" << std::endl;
+    std::cerr << "ERROR: invalid landmarks file '" << fileName << "'" << std::endl;
     exit(-3);
   }
   
@@ -156,6 +171,22 @@ void write_points_pts(const std::string& fileName, const PointArrayType& points)
     landmarksFile << points[i][0] << "\t" << points[i][1] << "\t" << points[i][2] << "\t" << std::endl;
 }
 
+void apply_spacing(const PointArrayType& input, const double* spacing, PointArrayType& output)
+{
+  PointType out;
+  out.Fill(1);
+  
+  for (size_t i = 0; i < input.size(); i++) {
+    out[0] = input[i][0] * spacing[0];
+    out[1] = input[i][1] * spacing[1];
+    out[2] = input[i][2] * spacing[2];
+    if (verbose){
+      std::cout << "output " << out << std::endl;
+    }
+    output.push_back(out);
+  }
+}
+
 void transform_points(const PointArrayType& input, const MatrixType& matrix, PointArrayType& output)
 {
   for (size_t i = 0; i < input.size(); i++) {
index 71186ef19eec14c84b3a8f35af5e5a55a1d4f6f4..c731c23086539cfdecd138621afd6b8a6c0606a9 100644 (file)
@@ -7,7 +7,8 @@ option "config"     - "Config file"       string    no
 option "verbose"    v     "Verbose"       flag    off
 
 option "input"    i "Input landmarks filename"      string    yes
-option "matrix"   m "Input 4x4 matrix filename ('.mat' file)"      string    yes
+option "matrix"   m "Input 4x4 matrix filename ('.mat' file)"      string    no
+option "spacing"   s "If given, applies the given spacing (x,y,z) to the input points."      double    no multiple  default="1"
 option "output"                o       "Output landmarks filename"                     string          yes
 option "type"          t       "Landmarks type ('pts' for Jef; 'txt' for VV)"          string          no              default="txt" 
 
index 6c827c350650fdb74ed7e350fe541da027926051..29623b35426578c50b7bfa2165c34e9f785990f7 100644 (file)
@@ -22,9 +22,9 @@
         <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
 &lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
 p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
 &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:12pt; font-weight:600;&quot;&gt;F1: &lt;/span&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Help (this window)&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;&quot;&gt;&lt;/p&gt;
 &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:12pt; font-weight:600; text-decoration: underline;&quot;&gt;Slice Selection&lt;/span&gt;&lt;/p&gt;
 &lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt; font-weight:600;&quot;&gt;&lt;/p&gt;
 &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:12pt; font-weight:600;&quot;&gt;F2:&lt;/span&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt; Sagital&lt;/span&gt;&lt;/p&gt;
@@ -38,6 +38,10 @@ p, li { white-space: pre-wrap; }
 &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:12pt; font-weight:600;&quot;&gt;0,1,2,3,4,5&lt;/span&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt; : Windowing Preset Selection&lt;/span&gt;&lt;/p&gt;
 &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:12pt; font-weight:600;&quot;&gt;6,7,8,9&lt;/span&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;: Colormap Selection&lt;/span&gt;&lt;/p&gt;
 &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:12pt; font-weight:600;&quot;&gt;w&lt;/span&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;: Local &lt;/span&gt;&lt;span style=&quot; font-size:12pt; text-decoration: underline;&quot;&gt;w&lt;/span&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;indowing around mouse cursor&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:12pt; font-weight:600;&quot;&gt;Ctrl+w&lt;/span&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;: Idem for fusion or overlay&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:12pt; font-weight:600; text-decoration: underline;&quot;&gt;Miscellaneous&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;&quot;&gt;&lt;/p&gt;
 &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:12pt; font-weight:600;&quot;&gt;l&lt;/span&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;: Toggle &lt;/span&gt;&lt;span style=&quot; font-size:12pt; text-decoration: underline;&quot;&gt;l&lt;/span&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;inear interpolation&lt;/span&gt;&lt;/p&gt;
 &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:12pt; font-weight:600;&quot;&gt;c&lt;/span&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;: Toggle &lt;/span&gt;&lt;span style=&quot; font-size:12pt; text-decoration: underline;&quot;&gt;c&lt;/span&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;ontour superposition mode&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
        </property>
index af07fe8fd0f35a7a215193857ed36dad2ea0022f..eab2f23388823d0fc8e12a961cedc9d01dd2d8f8 100644 (file)
@@ -221,7 +221,7 @@ p, li { white-space: pre-wrap; }
      <property name="frameShadow">
       <enum>QFrame::Raised</enum>
      </property>
-     <layout class="QGridLayout">
+     <layout class="QGridLayout" name="compareGridLayout">
       <property name="margin">
        <number>2</number>
       </property>
@@ -267,7 +267,7 @@ p, li { white-space: pre-wrap; }
         </property>
        </widget>
       </item>
-      <item row="1" column="2">
+      <item row="1" column="1" colspan="5">
        <widget class="QSlider" name="colorHorizontalSlider">
         <property name="maximum">
          <number>359</number>
@@ -277,7 +277,7 @@ p, li { white-space: pre-wrap; }
         </property>
        </widget>
       </item>
-      <item row="2" column="0" colspan="3">
+      <item row="2" column="0" colspan="5">
        <widget class="QLabel" name="refValueLabel">
         <property name="sizePolicy">
          <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@@ -290,7 +290,7 @@ p, li { white-space: pre-wrap; }
         </property>
        </widget>
       </item>
-      <item row="3" column="0" colspan="3">
+      <item row="3" column="0" colspan="5">
        <widget class="QLabel" name="valueLabel">
         <property name="sizePolicy">
          <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@@ -303,7 +303,7 @@ p, li { white-space: pre-wrap; }
         </property>
        </widget>
       </item>
-      <item row="4" column="0" colspan="3">
+      <item row="4" column="0" colspan="5">
        <widget class="QLabel" name="diffValueLabel">
         <property name="sizePolicy">
          <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@@ -316,6 +316,81 @@ p, li { white-space: pre-wrap; }
         </property>
        </widget>
       </item>
+      <item row="5" column="0">
+       <widget class="QLabel" name="label_10">
+        <property name="text">
+         <string>Window :</string>
+        </property>
+       </widget>
+      </item>
+      <item row="5" column="1">
+       <widget class="QDoubleSpinBox" name="overlayWindowSpinBox">
+        <property name="decimals">
+         <number>4</number>
+        </property>
+        <property name="minimum">
+         <double>-999999.000000000000000</double>
+        </property>
+        <property name="maximum">
+         <double>999999.000000000000000</double>
+        </property>
+        <property name="singleStep">
+         <double>10.000000000000000</double>
+        </property>
+        <property name="value">
+         <double>100.000000000000000</double>
+        </property>
+       </widget>
+      </item>
+      <item row="5" column="2">
+       <widget class="QLabel" name="label_11">
+        <property name="text">
+         <string>Level :</string>
+        </property>
+       </widget>
+      </item>
+      <item row="5" column="3">
+       <widget class="QDoubleSpinBox" name="overlayLevelSpinBox">
+        <property name="decimals">
+         <number>4</number>
+        </property>
+        <property name="minimum">
+         <double>-999999.000000000000000</double>
+        </property>
+        <property name="maximum">
+         <double>999999.000000000000000</double>
+        </property>
+        <property name="singleStep">
+         <double>10.000000000000000</double>
+        </property>
+        <property name="value">
+         <double>1000.000000000000000</double>
+        </property>
+       </widget>
+      </item>
+      <item row="5" column="4">
+       <spacer name="horizontalSpacer">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>40</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item row="5" column="5">
+       <widget class="QCheckBox" name="overlayLinkCheckBox">
+        <property name="text">
+         <string>Link</string>
+        </property>
+        <property name="checked">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
      </layout>
     </widget>
    </item>
@@ -330,7 +405,7 @@ p, li { white-space: pre-wrap; }
      <property name="frameShadow">
       <enum>QFrame::Raised</enum>
      </property>
-     <layout class="QGridLayout" name="gridLayout">
+     <layout class="QGridLayout" name="fusionGridLayout">
       <item row="0" column="0">
        <widget class="QLabel" name="label_5">
         <property name="maximumSize">
@@ -462,7 +537,7 @@ p, li { white-space: pre-wrap; }
        </widget>
       </item>
       <item row="4" column="2" colspan="2">
-       <widget class="QDoubleSpinBox" name="windowSpinBox">
+       <widget class="QDoubleSpinBox" name="fusionWindowSpinBox">
         <property name="decimals">
          <number>4</number>
         </property>
@@ -488,7 +563,7 @@ p, li { white-space: pre-wrap; }
        </widget>
       </item>
       <item row="4" column="5">
-       <widget class="QDoubleSpinBox" name="levelSpinBox">
+       <widget class="QDoubleSpinBox" name="fusionLevelSpinBox">
         <property name="decimals">
          <number>4</number>
         </property>
@@ -538,7 +613,6 @@ p, li { white-space: pre-wrap; }
   </layout>
  </widget>
  <resources>
-  <include location="../vvIcons.qrc"/>
   <include location="../vvIcons.qrc"/>
   <include location="vvIcons.qrc"/>
  </resources>
index 93b708e753b40aad059ce6ac8d5481ce3c2b5b7d..981105095d68a80934280b6e332895cc1d42fa9a 100644 (file)
--- a/vv/vv.cxx
+++ b/vv/vv.cxx
@@ -62,7 +62,7 @@ std::string create_timed_string()
 }
 
 //------------------------------------------------------------------------------
-#ifdef _WIN32\r
+#ifdef _WIN32
 int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPSTR lpCmdLine, int nShowCmd)
 {
   int argc = __argc;
@@ -76,6 +76,23 @@ int main( int argc, char** argv )
 
   QApplication app( argc, argv );
   Q_INIT_RESOURCE(vvIcons);
+  
+  // 
+  // ATTENTION: Rômulo Pinho - 05/08/2011
+  // Forcing the locale of the application is necessary
+  // because QT initialization changes it to the locale
+  // of the language of the system. This can cause 
+  // inconsistencies when, e.g., reading float values
+  // from DICOM fields with gdcm, since the decimal
+  // point may be changed for a comma (as in French).
+  // In practice, functions such as scanf and its
+  // variations are directly affected.
+  // https://bugreports.qt.nokia.com//browse/QTBUG-15247?page=com.atlassian.jira.plugin.system.issuetabpanels%253Achangehistory-tabpanel
+  //
+#ifndef _WIN32
+  std::string old_locale = setlocale(LC_NUMERIC, NULL);
+  setlocale(LC_NUMERIC, "POSIX");
+#endif
 
   vvMainWindow window;
 
@@ -175,9 +192,14 @@ int main( int argc, char** argv )
   }
 
   if(win!="" && lev!="") {
-    window.WindowLevelChanged(atof(win.c_str()), atof(lev.c_str()), 6, 0);
+    window.SetWindowLevel(atof(win.c_str()), atof(lev.c_str()));
     window.ApplyWindowLevelToAllImages();
   }
 
+#ifndef _WIN32
+  // restoring the locale, just to be clean...
+  setlocale(LC_NUMERIC, old_locale.c_str());
+#endif
+
   return app.exec();
 }
index 3d8c51a5a78f2ed85a0e61bc293a9599b7f584c4..1c2230f57160a8aa43e904f4e40734ed6233211a 100644 (file)
@@ -294,7 +294,8 @@ vvMainWindow::vvMainWindow():vvMainWindowBase()
   connect(linkPanel,SIGNAL(addLink(QString,QString)),this,SLOT(AddLink(QString,QString)));
   connect(linkPanel,SIGNAL(removeLink(QString,QString)),this,SLOT(RemoveLink(QString,QString)));
   connect(overlayPanel,SIGNAL(VFPropertyUpdated(int,int,int,int,double,double,double)),this,SLOT(SetVFProperty(int,int,int,int,double,double,double)));
-  connect(overlayPanel,SIGNAL(OverlayPropertyUpdated(int)),this,SLOT(SetOverlayProperty(int)));
+  connect(overlayPanel,SIGNAL(OverlayPropertyUpdated(int,int,double,double)),
+          this,SLOT(SetOverlayProperty(int,int,double,double)));
   connect(overlayPanel,SIGNAL(FusionPropertyUpdated(int,int,int,double,double)),
           this,SLOT(SetFusionProperty(int,int,int,double,double)));
   connect(landmarksPanel,SIGNAL(UpdateRenderWindows()),this,SLOT(UpdateRenderWindows()));
@@ -915,8 +916,8 @@ void vvMainWindow::LoadImages(std::vector<std::string> files, vvImageReader::Loa
                 this, SLOT(OverlayChanged(int,double,double)));
         connect(mSlicerManagers.back(), SIGNAL(UpdateFusion(int, double)),
                 this, SLOT(FusionChanged(int,double)));
-        connect(mSlicerManagers.back(), SIGNAL(WindowLevelChanged(double, double,int, int)),
-                this,SLOT(WindowLevelChanged(double, double, int, int)));
+        connect(mSlicerManagers.back(), SIGNAL(WindowLevelChanged()),
+                this,SLOT(WindowLevelChanged()));
         connect(mSlicerManagers.back(), SIGNAL(UpdateSlice(int,int)),
                 this,SLOT(UpdateSlice(int,int)));
         connect(mSlicerManagers.back(), SIGNAL(UpdateTSlice(int, int)),
@@ -1122,10 +1123,6 @@ void vvMainWindow::ImageInfoChanged()
         break;
       }
     }
-    windowSpinBox->setValue(mSlicerManagers[index]->GetColorWindow());
-    levelSpinBox->setValue(mSlicerManagers[index]->GetColorLevel());
-    presetComboBox->setCurrentIndex(mSlicerManagers[index]->GetPreset());
-    colorMapComboBox->setCurrentIndex(mSlicerManagers[index]->GetColorMap());
 
     infoPanel->setFileName(image);
     infoPanel->setDimension(dim);
@@ -1147,10 +1144,7 @@ void vvMainWindow::ImageInfoChanged()
         break;
       }
     }
-    windowSpinBox->setValue(mSlicerManagers[index]->GetColorWindow());
-    levelSpinBox->setValue(mSlicerManagers[index]->GetColorLevel());
-    presetComboBox->setCurrentIndex(mSlicerManagers[index]->GetPreset());
-    colorMapComboBox->setCurrentIndex(mSlicerManagers[index]->GetColorMap());
+    WindowLevelChanged();
 
     if (mSlicerManagers[index]->GetSlicer(0)->GetVF()) {
       overlayPanel->getVFName(mSlicerManagers[index]->GetVFName().c_str());
@@ -1163,22 +1157,14 @@ void vvMainWindow::ImageInfoChanged()
     }
     if (mSlicerManagers[index]->GetSlicer(0)->GetOverlay()) {
       overlayPanel->getOverlayName(mSlicerManagers[index]->GetOverlayName().c_str());
-      overlayPanel->getOverlayProperty(mSlicerManagers[index]->GetOverlayColor());
     } else {
       overlayPanel->getOverlayName(mSlicerManagers[index]->GetOverlayName().c_str());
-      overlayPanel->getOverlayProperty(-1);
     }
     
     if (mSlicerManagers[index]->GetSlicer(0)->GetFusion()) {
       overlayPanel->getFusionName(mSlicerManagers[index]->GetFusionName().c_str());
-      overlayPanel->getFusionProperty(mSlicerManagers[index]->GetFusionOpacity(),
-                                      mSlicerManagers[index]->GetFusionThresholdOpacity(),
-                                      mSlicerManagers[index]->GetFusionColorMap(),
-                                      mSlicerManagers[index]->GetFusionWindow(),
-                                      mSlicerManagers[index]->GetFusionLevel());
     } else {
       overlayPanel->getFusionName(mSlicerManagers[index]->GetFusionName().c_str());
-      overlayPanel->getFusionProperty(-1, -1, -1, -1, -1);
     }
   }
 }
@@ -1629,12 +1615,34 @@ void vvMainWindow::FusionChanged(int visibility, double value)
 //------------------------------------------------------------------------------
 
 //------------------------------------------------------------------------------
-void vvMainWindow::WindowLevelChanged(double window, double level,int preset,int colormap)
+void vvMainWindow::WindowLevelChanged()
 {
-  windowSpinBox->setValue(window);
-  levelSpinBox->setValue(level);
-  colorMapComboBox->setCurrentIndex(colormap);
-  presetComboBox->setCurrentIndex(preset);
+  // Base image
+  int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
+  if(index==-1) return;
+  windowSpinBox->setValue(mSlicerManagers[index]->GetColorWindow());
+  levelSpinBox->setValue(mSlicerManagers[index]->GetColorLevel());
+  colorMapComboBox->setCurrentIndex(mSlicerManagers[index]->GetColorMap());
+  presetComboBox->setCurrentIndex(mSlicerManagers[index]->GetPreset());
+
+  // Overlay image
+  if (mSlicerManagers[index]->GetSlicer(0)->GetOverlay())
+    overlayPanel->getOverlayProperty(mSlicerManagers[index]->GetOverlayColor(),
+                                     mSlicerManagers[index]->GetLinkOverlayWindowLevel(),
+                                     mSlicerManagers[index]->GetOverlayColorWindow(),
+                                     mSlicerManagers[index]->GetOverlayColorLevel());
+  else
+    overlayPanel->getOverlayProperty(-1,0,0.,0.);
+
+  // Fusion image
+  if (mSlicerManagers[index]->GetSlicer(0)->GetFusion())
+    overlayPanel->getFusionProperty(mSlicerManagers[index]->GetFusionOpacity(),
+                                    mSlicerManagers[index]->GetFusionThresholdOpacity(),
+                                    mSlicerManagers[index]->GetFusionColorMap(),
+                                    mSlicerManagers[index]->GetFusionWindow(),
+                                    mSlicerManagers[index]->GetFusionLevel());
+  else
+    overlayPanel->getFusionProperty(-1, -1, -1, -1, -1);
 }
 //------------------------------------------------------------------------------
 
@@ -1646,6 +1654,17 @@ void vvMainWindow::WindowLevelEdited()
 }
 //------------------------------------------------------------------------------
 
+//------------------------------------------------------------------------------
+void vvMainWindow::SetWindowLevel(double w, double l)
+{
+  windowSpinBox->setValue(w);
+  levelSpinBox->setValue(l);
+  presetComboBox->setCurrentIndex(6);
+  colorMapComboBox->setCurrentIndex(0);
+  UpdateWindowLevel();
+}
+//------------------------------------------------------------------------------
+
 //------------------------------------------------------------------------------
 void vvMainWindow::UpdateWindowLevel()
 {
@@ -1657,8 +1676,7 @@ void vvMainWindow::UpdateWindowLevel()
     mSlicerManagers[index]->SetColorLevel(levelSpinBox->value());
     mSlicerManagers[index]->SetPreset(presetComboBox->currentIndex());
     mSlicerManagers[index]->Render();
-    windowSpinBox->setValue(mSlicerManagers[index]->GetColorWindow());
-    levelSpinBox->setValue(mSlicerManagers[index]->GetColorLevel());
+    WindowLevelChanged();
   }
 }
 //------------------------------------------------------------------------------
@@ -1854,6 +1872,7 @@ void vvMainWindow::AddOverlayImage(int index, QString file)
     error += mSlicerManagers[index]->GetLastError().c_str();
     QMessageBox::information(this,tr("Problem reading image !"),error);
   }
+  WindowLevelChanged();
 }
 //------------------------------------------------------------------------------
 
@@ -2137,12 +2156,15 @@ void vvMainWindow::SetVFProperty(int subsampling, int scale, int log, int width,
 
 
 //------------------------------------------------------------------------------
-void vvMainWindow::SetOverlayProperty(int color)
+void vvMainWindow::SetOverlayProperty(int color, int linked, double window, double level)
 {
   int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
   if (mSlicerManagers[index]->GetSlicer(0)->GetOverlay()) {
     mSlicerManagers[index]->SetOverlayColor(color);
     mSlicerManagers[index]->SetColorMap(0);
+    mSlicerManagers[index]->SetLinkOverlayWindowLevel(linked);
+    mSlicerManagers[index]->SetOverlayColorWindow(window);
+    mSlicerManagers[index]->SetOverlayColorLevel(level);
     mSlicerManagers[index]->Render();
   }
 }
@@ -2836,8 +2858,8 @@ vvSlicerManager* vvMainWindow::AddImage(vvImage::Pointer image,std::string filen
           this, SLOT(OverlayChanged(int,double,double)));
   connect(mSlicerManagers.back(), SIGNAL(UpdateFusion(int, double)),
           this, SLOT(FusionChanged(int,double)));
-  connect(mSlicerManagers.back(), SIGNAL(WindowLevelChanged(double, double,int, int)),
-          this,SLOT(WindowLevelChanged(double, double, int, int)));
+  connect(mSlicerManagers.back(), SIGNAL(WindowLevelChanged()),
+          this,SLOT(WindowLevelChanged()));
   connect(mSlicerManagers.back(), SIGNAL(UpdateSlice(int,int)),
           this,SLOT(UpdateSlice(int,int)));
   connect(mSlicerManagers.back(), SIGNAL(UpdateTSlice(int, int)),
index 7da8a9171ecc8e0018cdf5606daef1f947eb75ed..8ee5ab26178adf4d421514e1c9a8a147c79765b9 100644 (file)
@@ -101,11 +101,12 @@ public slots:
   void SegmentationOnCurrentImage();
   void SurfaceViewerLaunch();
 
-  void WindowLevelChanged(double window, double level,int preset, int colormap);
+  void WindowLevelChanged();
   void UpdateSlice(int slicer, int slice);
   void UpdateTSlice(int slicer, int slice);
   void UpdateSliceRange(int slicer, int min, int max, int tmin, int tmax);
   void WindowLevelEdited();
+  void SetWindowLevel(double w, double l);
   void UpdateColorMap();
   void UpdateWindowLevel();
   void SwitchWindowLevel();
@@ -142,7 +143,7 @@ public slots:
   void ResetTransformationToIdentity();
 
   void SetVFProperty(int subsampling,int scale,int lut, int width, double r, double g, double b);
-  void SetOverlayProperty(int color);
+  void SetOverlayProperty(int color, int linked, double window, double level);
   void SetFusionProperty(int opacity, int tresOpacity, int colormap,double window,double level);
 
   void GoToCursor();
index bc3a7d0180ffa93dcc024c5e14766fe5f3a7daa2..eb2eaa1c7b2d27950d27551ea8943884fb366f8d 100644 (file)
@@ -47,9 +47,12 @@ vvOverlayPanel::vvOverlayPanel(QWidget * parent):QWidget(parent)
   connect(opacityHorizontalSlider,SIGNAL(valueChanged(int)),this,SLOT(setFusionProperty()));
   connect(thresOpacityHorizontalSlider,SIGNAL(valueChanged(int)),this,SLOT(setFusionProperty()));
   connect(fusionColorMapComboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(setFusionProperty()));
-  connect(windowSpinBox,SIGNAL(valueChanged(double)),this,SLOT(setFusionProperty()));
-  connect(levelSpinBox,SIGNAL(valueChanged(double)),this,SLOT(setFusionProperty()));
-  
+  connect(fusionWindowSpinBox,SIGNAL(valueChanged(double)),this,SLOT(setFusionProperty()));
+  connect(fusionLevelSpinBox,SIGNAL(valueChanged(double)),this,SLOT(setFusionProperty()));
+  connect(overlayWindowSpinBox,SIGNAL(valueChanged(double)),this,SLOT(setOverlayProperty()));
+  connect(overlayLevelSpinBox,SIGNAL(valueChanged(double)),this,SLOT(setOverlayProperty()));
+  connect(overlayLinkCheckBox,SIGNAL(stateChanged(int)),this,SLOT(setOverlayProperty()));
+
   disableFusionSignals = false;
 }
 
@@ -125,13 +128,16 @@ void vvOverlayPanel::getOverlayName(QString name)
   imageComparedLabel->setText(filename.toStdString().c_str());
 }
 
-void vvOverlayPanel::getOverlayProperty(int value)
+void vvOverlayPanel::getOverlayProperty(int color, int linked, double window, double level)
 {
-  if (value > -1) {
+  if (color > -1) {
     compareFrame->show();
     compareFrame->setEnabled(1);
     colorHorizontalSlider->setEnabled(1);
-    colorHorizontalSlider->setValue(value);
+    colorHorizontalSlider->setValue(color);
+    overlayLinkCheckBox->setCheckState( (linked)?Qt::Checked:Qt::Unchecked );
+    overlayWindowSpinBox->setValue(window);
+    overlayLevelSpinBox->setValue(level);
   } else {
     compareFrame->hide();
     compareFrame->setEnabled(0);
@@ -142,7 +148,12 @@ void vvOverlayPanel::getOverlayProperty(int value)
 
 void vvOverlayPanel::setOverlayProperty()
 {
-  emit OverlayPropertyUpdated(colorHorizontalSlider->value());
+  overlayWindowSpinBox->setEnabled(!overlayLinkCheckBox->checkState());
+  overlayLevelSpinBox->setEnabled(!overlayLinkCheckBox->checkState());
+  emit OverlayPropertyUpdated(colorHorizontalSlider->value(),
+                              overlayLinkCheckBox->checkState(),
+                              overlayWindowSpinBox->value(),
+                              overlayLevelSpinBox->value());
 }
 
 void vvOverlayPanel::getCurrentOverlayInfo(int visibility,double valueOver, double valueRef)
@@ -179,10 +190,10 @@ void vvOverlayPanel::getFusionProperty(int opacity, int thresOpacity, int colorm
     opacityHorizontalSlider->setValue(opacity);
     thresOpacityHorizontalSlider->setEnabled(1);
     thresOpacityHorizontalSlider->setValue(thresOpacity);
-    windowSpinBox->setEnabled(1);
-    levelSpinBox->setEnabled(1);
-    windowSpinBox->setValue(window);
-    levelSpinBox->setValue(level);
+    fusionWindowSpinBox->setEnabled(1);
+    fusionLevelSpinBox->setEnabled(1);
+    fusionWindowSpinBox->setValue(window);
+    fusionLevelSpinBox->setValue(level);
     
     // re-enable signals and trigger slot function
     disableFusionSignals = false;
@@ -196,8 +207,8 @@ void vvOverlayPanel::getFusionProperty(int opacity, int thresOpacity, int colorm
     thresOpacityHorizontalSlider->setValue(0);
     fusionColorMapComboBox->setEnabled(0);
     fusionColorMapComboBox->setCurrentIndex(-1);
-    windowSpinBox->setEnabled(0);
-    levelSpinBox->setEnabled(0);
+    fusionWindowSpinBox->setEnabled(0);
+    fusionLevelSpinBox->setEnabled(0);
   }
 }
 
@@ -207,7 +218,7 @@ void vvOverlayPanel::setFusionProperty()
     return;
   
   emit FusionPropertyUpdated(opacityHorizontalSlider->value(), thresOpacityHorizontalSlider->value(), fusionColorMapComboBox->currentIndex(),
-                             windowSpinBox->value(), levelSpinBox->value());
+                             fusionWindowSpinBox->value(), fusionLevelSpinBox->value());
 }
 
 void vvOverlayPanel::getCurrentFusionInfo(int visibility,double value)
index 5000e6444b83ef3248c33b732a3044475b842022..63bad7bc633c3461ad19d39e1b3b5f51ab2342b5 100644 (file)
@@ -38,7 +38,7 @@ public:
     void getVFProperty(int subsampling, int scale, int log);
     void getVFName(QString name);
 
-    void getOverlayProperty(int color);
+    void getOverlayProperty(int color, int linked, double window, double level);
     void getOverlayName(QString name);
 
     void getFusionProperty(int opacity, int thresOpacity, int colormap, double window, double level);
@@ -56,7 +56,7 @@ public slots:
 
 signals:
     void VFPropertyUpdated(int subsampling, int scale, int log, int width, double r, double g, double b);
-    void OverlayPropertyUpdated(int color);
+    void OverlayPropertyUpdated(int color, int linked, double window, double level);
     void FusionPropertyUpdated(int opacity, int thresOpacity, int colormap, double window, double level);
 
     
index 302da7eae2689d6d7ef7d2657a6fa42e80babc4f..2473c87e27c3ca8dd84b33c047d199bea685f7b3 100644 (file)
@@ -135,6 +135,8 @@ vvSlicer::vvSlicer()
   this->WindowLevel = vvImageMapToWLColors::New();
 
   this->InstallPipeline();
+
+  mLinkOverlayWindowLevel = true;
 }
 //------------------------------------------------------------------------------
 
@@ -1111,7 +1113,6 @@ void vvSlicer::SetColorWindow(double window)
 }
 //----------------------------------------------------------------------------
 
-
 //----------------------------------------------------------------------------
 void vvSlicer::SetColorLevel(double level)
 {
@@ -1125,9 +1126,43 @@ void vvSlicer::SetColorLevel(double level)
 }
 //----------------------------------------------------------------------------
 
+//----------------------------------------------------------------------------
+double vvSlicer::GetOverlayColorWindow()
+{
+  if(mOverlayMapper)
+    return mOverlayMapper->GetWindow();
+  else
+    return 0.;
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+double vvSlicer::GetOverlayColorLevel()
+{
+  if(mOverlayMapper)
+    return mOverlayMapper->GetLevel();
+  else
+    return 0.;
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+void vvSlicer::SetOverlayColorWindow(double window)
+{
+  mOverlayMapper->SetWindow(window);
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+void vvSlicer::SetOverlayColorLevel(double level)
+{
+  mOverlayMapper->SetLevel(level);
+}
+//----------------------------------------------------------------------------
+
 //----------------------------------------------------------------------------
 // Returns the min an the max value in a 41x41 region around the mouse pointer
-void vvSlicer::GetExtremasAroundMousePointer(double & min, double & max)
+void vvSlicer::GetExtremasAroundMousePointer(double & min, double & max, vtkImageData *image)
 {
   //Get mouse pointer position in view coordinates
   double fLocalExtents[6];
@@ -1149,8 +1184,8 @@ void vvSlicer::GetExtremasAroundMousePointer(double & min, double & max)
   //Convert to image pixel coordinates (rounded)
   int iLocalExtents[6];
   for(int i=0; i<3; i++) {
-    fLocalExtents[i*2  ] = (fLocalExtents[i*2  ] - this->GetInput()->GetOrigin()[i])/this->GetInput()->GetSpacing()[i];
-    fLocalExtents[i*2+1] = (fLocalExtents[i*2+1] - this->GetInput()->GetOrigin()[i])/this->GetInput()->GetSpacing()[i];
+    fLocalExtents[i*2  ] = (fLocalExtents[i*2  ] - image->GetOrigin()[i])/image->GetSpacing()[i];
+    fLocalExtents[i*2+1] = (fLocalExtents[i*2+1] - image->GetOrigin()[i])/image->GetSpacing()[i];
 
     iLocalExtents[i*2  ] = lrint(fLocalExtents[i*2  ]);
     iLocalExtents[i*2+1] = lrint(fLocalExtents[i*2+1]);
@@ -1160,7 +1195,7 @@ void vvSlicer::GetExtremasAroundMousePointer(double & min, double & max)
   }
 
   vtkSmartPointer<vtkExtractVOI> voiFilter = vtkSmartPointer<vtkExtractVOI>::New();
-  voiFilter->SetInput(this->GetInput());
+  voiFilter->SetInput(image);
   voiFilter->SetVOI(iLocalExtents);
   voiFilter->Update();
   if (!voiFilter->GetOutput()->GetNumberOfPoints()) {
@@ -1275,8 +1310,10 @@ void vvSlicer::Render()
 
 
   if (mOverlay && mOverlayActor->GetVisibility()) {
-    mOverlayMapper->SetWindow(this->GetColorWindow());
-    mOverlayMapper->SetLevel(this->GetColorLevel());
+    if(mLinkOverlayWindowLevel) {
+      mOverlayMapper->SetWindow(this->GetColorWindow());
+      mOverlayMapper->SetLevel(this->GetColorLevel());
+    }
     mOverlayMapper->GetOutput()->SetUpdateExtent(mOverlayActor->GetDisplayExtent());
     mOverlayMapper->GetOutput()->Update();
     mOverlayMapper->Update();
index 0536bc1e7ef38995f20918af8d53d9b0c73b93be..a5156f28bc92e4f3c08e49db2c30b74c46d44ff9 100644 (file)
@@ -153,7 +153,7 @@ public:
   void SetCornerAnnotationVisibility(bool s);
   bool GetCornerAnnotationVisibility();
 
-  void GetExtremasAroundMousePointer(double & min, double & max);
+  void GetExtremasAroundMousePointer(double & min, double & max, vtkImageData *image);
 
   void UpdateLandmarks();
   void ForceUpdateDisplayExtent();
@@ -168,6 +168,14 @@ public:
   virtual void SetColorWindow(double s);
   virtual void SetColorLevel(double s);
 
+  double GetOverlayColorWindow();
+  double GetOverlayColorLevel();
+  bool GetLinkOverlayWindowLevel() { return mLinkOverlayWindowLevel; }
+
+  void SetOverlayColorWindow(double s);
+  void SetOverlayColorLevel(double s);
+  void SetLinkOverlayWindowLevel(bool b) { mLinkOverlayWindowLevel = b; }
+
   /**
    * When it is enabled, beware of a call to GetExtent.
    * we must have setted mReducedExtent otherwhise random values
@@ -235,6 +243,7 @@ protected:
   bool mUseReducedExtent;
   int * mReducedExtent;
   int * mInitialExtent;
+  bool mLinkOverlayWindowLevel;
 
 private:
   void UpdateOrientation();
index fd8f09fccc30b4667a6e271076ca5000f2839512..c38496e5ab50b2389311eb4788f8f8ee428a0178 100644 (file)
@@ -512,7 +512,6 @@ void vvSlicerManager::SetColorWindow(double s)
 }
 //----------------------------------------------------------------------------
 
-
 //----------------------------------------------------------------------------
 void vvSlicerManager::SetColorLevel(double s)
 {
@@ -522,6 +521,33 @@ void vvSlicerManager::SetColorLevel(double s)
 }
 //----------------------------------------------------------------------------
 
+//----------------------------------------------------------------------------
+void vvSlicerManager::SetOverlayColorWindow(double s)
+{
+  for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+    mSlicers[i]->SetOverlayColorWindow(s);
+  }
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::SetOverlayColorLevel(double s)
+{
+  for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+    mSlicers[i]->SetOverlayColorLevel(s);
+  }
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::SetLinkOverlayWindowLevel(bool b)
+{
+  for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+    mSlicers[i]->SetLinkOverlayWindowLevel(b);
+  }
+}
+//----------------------------------------------------------------------------
+
 //----------------------------------------------------------------------------
 void vvSlicerManager::SetCursorAndCornerAnnotationVisibility(int s)
 {
@@ -736,6 +762,33 @@ double vvSlicerManager::GetColorLevel()
 }
 //----------------------------------------------------------------------------
 
+//----------------------------------------------------------------------------
+double vvSlicerManager::GetOverlayColorWindow()
+{
+  if (mSlicers.size())
+    return mSlicers[0]->GetOverlayColorWindow();
+  return -1;
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+double vvSlicerManager::GetOverlayColorLevel()
+{
+  if (mSlicers.size())
+    return mSlicers[0]->GetOverlayColorLevel();
+  return -1;
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+bool vvSlicerManager::GetLinkOverlayWindowLevel()
+{
+  if (mSlicers.size())
+    return mSlicers[0]->GetLinkOverlayWindowLevel();
+  return -1;
+}
+//----------------------------------------------------------------------------
+
 //------------------------------------------------------------------------------
 void vvSlicerManager::ResetTransformationToIdentity(const std::string actorType)
 {
@@ -950,10 +1003,11 @@ void vvSlicerManager::Picked()
 }
 //----------------------------------------------------------------------------
 
+
 //----------------------------------------------------------------------------
 void vvSlicerManager::UpdateWindowLevel()
 {
-  emit WindowLevelChanged(mSlicers[0]->GetColorWindow(),mSlicers[0]->GetColorLevel(),mPreset,mColorMap);
+  emit WindowLevelChanged();
 }
 //----------------------------------------------------------------------------
 
@@ -1057,14 +1111,34 @@ void vvSlicerManager::SetPreset(int preset)
 
 
 //----------------------------------------------------------------------------
-void vvSlicerManager::SetLocalColorWindowing(const int slicer)
+void vvSlicerManager::SetLocalColorWindowing(const int slicer, const bool bCtrlKey)
 {
   double min, max;
-  this->mSlicers[slicer]->GetExtremasAroundMousePointer(min, max);
-  this->SetColorWindow(max-min);
-  this->SetColorLevel(0.5*(min+max));
-  this->UpdateWindowLevel();
+  int t = this->mSlicers[slicer]->GetTSlice();
+  if(bCtrlKey && this->mSlicers[slicer]->GetFusion()) {
+    this->mSlicers[slicer]->GetExtremasAroundMousePointer(min, max, this->mSlicers[slicer]->GetFusion()->GetVTKImages()[t]);
+    this->SetFusionWindow(max-min);
+    this->SetFusionLevel(0.5*(min+max));
+    this->SetColorMap(mColorMap);
+  }
+  else if(bCtrlKey && this->mSlicers[slicer]->GetOverlay()) {
+    this->mSlicers[slicer]->GetExtremasAroundMousePointer(min, max, this->mSlicers[slicer]->GetOverlay()->GetVTKImages()[t]);
+    if(this->mSlicers[slicer]->GetLinkOverlayWindowLevel()){
+      this->SetColorWindow(max-min);
+      this->SetColorLevel(0.5*(min+max));
+    } else {
+      this->SetOverlayColorWindow(max-min);
+      this->SetOverlayColorLevel(0.5*(min+max));
+    }
+  }
+  else {
+    this->mSlicers[slicer]->GetExtremasAroundMousePointer(min, max, this->mSlicers[slicer]->GetInput());
+    this->SetColorWindow(max-min);
+    this->SetColorLevel(0.5*(min+max));
+    this->SetPreset(6);
+  }
   this->Render();
+  this->UpdateWindowLevel();
 }
 //----------------------------------------------------------------------------
 
index 5e0ef60c24194669ebf78e5d30a4eb0aa2aca145..e8a229b877d8dc3e9d669c58d429742401e2753d 100644 (file)
@@ -111,7 +111,10 @@ class vvSlicerManager : public QObject {
   void GenerateDefaultLookupTable();
   void SetColorWindow(double s);
   void SetColorLevel(double s);
-  void SetLocalColorWindowing(const int slicer);
+  void SetOverlayColorWindow(double s);
+  void SetOverlayColorLevel(double s);
+  void SetLinkOverlayWindowLevel(bool b);
+  void SetLocalColorWindowing(const int slicer, const bool bCtrlKey);
   void SetOpacity(int i, double factor);
   void SetColorMap(int colormap);
   void SetPreset(int preset);
@@ -136,6 +139,9 @@ class vvSlicerManager : public QObject {
 
   double GetColorWindow();
   double GetColorLevel();
+  double GetOverlayColorWindow();
+  double GetOverlayColorLevel();
+  bool GetLinkOverlayWindowLevel();
   int GetColorMap() {
     return mColorMap;
   }
@@ -145,7 +151,6 @@ class vvSlicerManager : public QObject {
   int GetOverlayColor() {
     return mOverlayColor;
   }
-
   int GetFusionOpacity() {
     return mFusionOpacity;
   }
@@ -216,7 +221,7 @@ signals :
   void UpdateSlice(int slicer, int slice);
   void UpdateTSlice(int slicer, int slice);
   void UpdateSliceRange(int slice, int min, int max, int tmin, int tmax);
-  void WindowLevelChanged(double window, double level, int preset, int colormap);
+  void WindowLevelChanged();
   void UpdateLinkManager(std::string, int slicer, double x, double y, double z, int temps);
   void UpdateLinkedNavigation(std::string, vvSlicerManager*, vvSlicer*);
   void LandmarkAdded();
index 805f51bea4bd943a23abc0ed4399d007b8dd8b8e..1b7103301b7d9f0544c731c14ccca913a623657d 100644 (file)
@@ -109,7 +109,7 @@ void vvSlicerManagerCommand::Execute(vtkObject *caller,
           return;
         }
         if (KeyPress == "w") {
-          this->SM->SetLocalColorWindowing(VisibleInWindow);
+          this->SM->SetLocalColorWindowing(VisibleInWindow, bCtrlKey);
           return;
         }
         if (KeyPress == "0") {
@@ -186,7 +186,6 @@ void vvSlicerManagerCommand::Execute(vtkObject *caller,
           return;
         }
         if (KeyPress == "h") {
-          std::cout << "KeyPress == \"h\"\n";
           this->SM->SetCursorAndCornerAnnotationVisibility(0);
           this->SM->Render();
           return;
@@ -405,8 +404,8 @@ void vvSlicerManagerCommand::Execute(vtkObject *caller,
       this->SM->SetColorWindow(window*dx);
       this->SM->SetColorLevel(level-dy);
       this->SM->SetPreset(6);
-      this->SM->UpdateWindowLevel();
       this->SM->Render();
+      this->SM->UpdateWindowLevel();
       return;
     }
   }