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)
+
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
//--------------------------------------------------------------------
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;
}
m_FailOnImageTypeError = true;
m_ReadOnDisk = true;
m_WriteOnDisk = true;
+ m_WriteCompression = false;
// m_LastError = "";
// StopOnErrorOn();
SetFilterBase(NULL);
//--------------------------------------------------------------------
+//--------------------------------------------------------------------
+void clitk::ImageToImageGenericFilterBase::EnableWriteCompression(bool b)
+{
+ m_WriteCompression = b;
+}
+//--------------------------------------------------------------------
+
+
//--------------------------------------------------------------------
void clitk::ImageToImageGenericFilterBase::SetInputFilename(const std::string & filename)
{
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
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);
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);
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);
#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
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;
#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
/**
* 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
#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
{
+++ /dev/null
-#! /bin/sh
-
-
-MAX_THREADS=2
-
-check_threads()
-{
- while [[ $(jobs -p | wc -l) -ge $1 ]]; do
- jobs
- sleep 10
- done
-}
-
-
--- /dev/null
+#!/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}
+
+
--- /dev/null
+#!/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"
--- /dev/null
+#!/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"
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+#! /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
#! /bin/bash -x
-. common.sh
+source `dirname $0`/midp_common.sh
extract_patient()
{
#
# 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)
--- /dev/null
+#! /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
+}
--- /dev/null
+###############################################################################
+#
+# 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>"
--- /dev/null
+#! /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
--- /dev/null
+#! /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
#=========================================================
# 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)
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})
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 !
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
// 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;
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);
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) {
}
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;
{
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);
}
{
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);
}
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++) {
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"
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;">
+</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;">
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">F1: </span><span style=" font-size:12pt;">Help (this window)</span></p>
-<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
+<p style="-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;"></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">Slice Selection</span></p>
<p style="-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;"></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">F2:</span><span style=" font-size:12pt;"> Sagital</span></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">0,1,2,3,4,5</span><span style=" font-size:12pt;"> : Windowing Preset Selection</span></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">6,7,8,9</span><span style=" font-size:12pt;">: Colormap Selection</span></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">w</span><span style=" font-size:12pt;">: Local </span><span style=" font-size:12pt; text-decoration: underline;">w</span><span style=" font-size:12pt;">indowing around mouse cursor</span></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Ctrl+w</span><span style=" font-size:12pt;">: Idem for fusion or overlay</span></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">Miscellaneous</span></p>
+<p style="-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;"></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">l</span><span style=" font-size:12pt;">: Toggle </span><span style=" font-size:12pt; text-decoration: underline;">l</span><span style=" font-size:12pt;">inear interpolation</span></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">c</span><span style=" font-size:12pt;">: Toggle </span><span style=" font-size:12pt; text-decoration: underline;">c</span><span style=" font-size:12pt;">ontour superposition mode</span></p></body></html></string>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
- <layout class="QGridLayout">
+ <layout class="QGridLayout" name="compareGridLayout">
<property name="margin">
<number>2</number>
</property>
</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>
</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">
</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">
</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">
</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>
<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">
</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>
</widget>
</item>
<item row="4" column="5">
- <widget class="QDoubleSpinBox" name="levelSpinBox">
+ <widget class="QDoubleSpinBox" name="fusionLevelSpinBox">
<property name="decimals">
<number>4</number>
</property>
</layout>
</widget>
<resources>
- <include location="../vvIcons.qrc"/>
<include location="../vvIcons.qrc"/>
<include location="vvIcons.qrc"/>
</resources>
}
//------------------------------------------------------------------------------
-#ifdef _WIN32\r
+#ifdef _WIN32
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPSTR lpCmdLine, int nShowCmd)
{
int argc = __argc;
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;
}
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();
}
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()));
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)),
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);
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());
}
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);
}
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
-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);
}
//------------------------------------------------------------------------------
}
//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+void vvMainWindow::SetWindowLevel(double w, double l)
+{
+ windowSpinBox->setValue(w);
+ levelSpinBox->setValue(l);
+ presetComboBox->setCurrentIndex(6);
+ colorMapComboBox->setCurrentIndex(0);
+ UpdateWindowLevel();
+}
+//------------------------------------------------------------------------------
+
//------------------------------------------------------------------------------
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();
}
}
//------------------------------------------------------------------------------
error += mSlicerManagers[index]->GetLastError().c_str();
QMessageBox::information(this,tr("Problem reading image !"),error);
}
+ WindowLevelChanged();
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
-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();
}
}
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)),
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();
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();
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;
}
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);
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)
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;
thresOpacityHorizontalSlider->setValue(0);
fusionColorMapComboBox->setEnabled(0);
fusionColorMapComboBox->setCurrentIndex(-1);
- windowSpinBox->setEnabled(0);
- levelSpinBox->setEnabled(0);
+ fusionWindowSpinBox->setEnabled(0);
+ fusionLevelSpinBox->setEnabled(0);
}
}
return;
emit FusionPropertyUpdated(opacityHorizontalSlider->value(), thresOpacityHorizontalSlider->value(), fusionColorMapComboBox->currentIndex(),
- windowSpinBox->value(), levelSpinBox->value());
+ fusionWindowSpinBox->value(), fusionLevelSpinBox->value());
}
void vvOverlayPanel::getCurrentFusionInfo(int visibility,double value)
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);
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);
this->WindowLevel = vvImageMapToWLColors::New();
this->InstallPipeline();
+
+ mLinkOverlayWindowLevel = true;
}
//------------------------------------------------------------------------------
}
//----------------------------------------------------------------------------
-
//----------------------------------------------------------------------------
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];
//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]);
}
vtkSmartPointer<vtkExtractVOI> voiFilter = vtkSmartPointer<vtkExtractVOI>::New();
- voiFilter->SetInput(this->GetInput());
+ voiFilter->SetInput(image);
voiFilter->SetVOI(iLocalExtents);
voiFilter->Update();
if (!voiFilter->GetOutput()->GetNumberOfPoints()) {
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();
void SetCornerAnnotationVisibility(bool s);
bool GetCornerAnnotationVisibility();
- void GetExtremasAroundMousePointer(double & min, double & max);
+ void GetExtremasAroundMousePointer(double & min, double & max, vtkImageData *image);
void UpdateLandmarks();
void ForceUpdateDisplayExtent();
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
bool mUseReducedExtent;
int * mReducedExtent;
int * mInitialExtent;
+ bool mLinkOverlayWindowLevel;
private:
void UpdateOrientation();
}
//----------------------------------------------------------------------------
-
//----------------------------------------------------------------------------
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)
{
}
//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+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)
{
}
//----------------------------------------------------------------------------
+
//----------------------------------------------------------------------------
void vvSlicerManager::UpdateWindowLevel()
{
- emit WindowLevelChanged(mSlicers[0]->GetColorWindow(),mSlicers[0]->GetColorLevel(),mPreset,mColorMap);
+ emit WindowLevelChanged();
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
-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();
}
//----------------------------------------------------------------------------
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);
double GetColorWindow();
double GetColorLevel();
+ double GetOverlayColorWindow();
+ double GetOverlayColorLevel();
+ bool GetLinkOverlayWindowLevel();
int GetColorMap() {
return mColorMap;
}
int GetOverlayColor() {
return mOverlayColor;
}
-
int GetFusionOpacity() {
return mFusionOpacity;
}
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();
return;
}
if (KeyPress == "w") {
- this->SM->SetLocalColorWindowing(VisibleInWindow);
+ this->SM->SetLocalColorWindowing(VisibleInWindow, bCtrlKey);
return;
}
if (KeyPress == "0") {
return;
}
if (KeyPress == "h") {
- std::cout << "KeyPress == \"h\"\n";
this->SM->SetCursorAndCornerAnnotationVisibility(0);
this->SM->Render();
return;
this->SM->SetColorWindow(window*dx);
this->SM->SetColorLevel(level-dy);
this->SM->SetPreset(6);
- this->SM->UpdateWindowLevel();
this->SM->Render();
+ this->SM->UpdateWindowLevel();
return;
}
}