From: Benoît Presles Date: Fri, 1 Jun 2012 07:39:23 +0000 (+0200) Subject: Merge branch 'master' of git://git.creatis.insa-lyon.fr/clitk X-Git-Tag: v1.4.0~281^2~15^2~8 X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=commitdiff_plain;h=bacc49dae8fbb11fc2cf9d78fcefa94691f9ebfe;hp=42e16e21ac020e807f7656d570baec84d46e0579;p=clitk.git Merge branch 'master' of git://git.creatis.insa-lyon.fr/clitk --- diff --git a/common/clitkGateAsciiImageIO.cxx b/common/clitkGateAsciiImageIO.cxx index 589c30c..99520ee 100644 --- a/common/clitkGateAsciiImageIO.cxx +++ b/common/clitkGateAsciiImageIO.cxx @@ -252,9 +252,49 @@ void clitk::GateAsciiImageIO::Write(const void* abstract_buffer) stream << "# nbVal = " << nb_value << endl; stream << "######################" << endl; - const double* buffer = static_cast(abstract_buffer); - for (unsigned long kk=0; kkGetComponentType()==itk::ImageIOBase::UCHAR) { + const unsigned char* buffer = static_cast(abstract_buffer); + for (unsigned long kk=0; kkGetComponentType()==itk::ImageIOBase::CHAR) { + const char* buffer = static_cast(abstract_buffer); + for (unsigned long kk=0; kkGetComponentType()==itk::ImageIOBase::USHORT) { + const unsigned short* buffer = static_cast(abstract_buffer); + for (unsigned long kk=0; kkGetComponentType()==itk::ImageIOBase::SHORT) { + const short* buffer = static_cast(abstract_buffer); + for (unsigned long kk=0; kkGetComponentType()==itk::ImageIOBase::UINT) { + const unsigned int* buffer = static_cast(abstract_buffer); + for (unsigned long kk=0; kkGetComponentType()==itk::ImageIOBase::INT) { + const int* buffer = static_cast(abstract_buffer); + for (unsigned long kk=0; kkGetComponentType()==itk::ImageIOBase::ULONG) { + const unsigned long* buffer = static_cast(abstract_buffer); + for (unsigned long kk=0; kkGetComponentType()==itk::ImageIOBase::LONG) { + const long* buffer = static_cast(abstract_buffer); + for (unsigned long kk=0; kkGetComponentType()==itk::ImageIOBase::FLOAT) { + const float* buffer = static_cast(abstract_buffer); + for (unsigned long kk=0; kkGetComponentType()==itk::ImageIOBase::DOUBLE) { + const double* buffer = static_cast(abstract_buffer); + for (unsigned long kk=0; kkGetComponentTypeAsString(this->GetComponentType())); + return; } FILE* handle = fopen(m_FileName.c_str(),"w"); @@ -264,6 +304,5 @@ void clitk::GateAsciiImageIO::Write(const void* abstract_buffer) } fwrite(stream.str().c_str(),1,stream.str().size(),handle); - fclose(handle); } diff --git a/common/clitkGateAsciiImageIO.h b/common/clitkGateAsciiImageIO.h index 7d174f8..7d134de 100644 --- a/common/clitkGateAsciiImageIO.h +++ b/common/clitkGateAsciiImageIO.h @@ -42,7 +42,6 @@ public: typedef GateAsciiImageIO Self; typedef itk::ImageIOBase Superclass; typedef itk::SmartPointer Pointer; - typedef signed short int PixelType; struct GateAsciiHeader { double matrix_size[3]; diff --git a/common/clitkImageToImageGenericFilterBase.cxx b/common/clitkImageToImageGenericFilterBase.cxx index 8a713d2..9db15b0 100644 --- a/common/clitkImageToImageGenericFilterBase.cxx +++ b/common/clitkImageToImageGenericFilterBase.cxx @@ -306,6 +306,58 @@ DEF_SetNextOutput_And_GetInput(int, 3); DEF_SetNextOutput_And_GetInput(float, 3); DEF_SetNextOutput_And_GetInput(double, 3); +/* +DEF_SetNextOutput_And_GetInput_WithCompo(unsigned char, 2, 2); +DEF_SetNextOutput_And_GetInput_WithCompo(unsigned char, 2, 3); +DEF_SetNextOutput_And_GetInput_WithCompo(unsigned char, 2, 4); +DEF_SetNextOutput_And_GetInput_WithCompo(unsigned char, 3, 2); +DEF_SetNextOutput_And_GetInput_WithCompo(unsigned char, 3, 3); +DEF_SetNextOutput_And_GetInput_WithCompo(unsigned char, 3, 4); +DEF_SetNextOutput_And_GetInput_WithCompo(unsigned char, 4, 2); +DEF_SetNextOutput_And_GetInput_WithCompo(unsigned char, 4, 3); +DEF_SetNextOutput_And_GetInput_WithCompo(unsigned char, 4, 4); + +DEF_SetNextOutput_And_GetInput_WithCompo(char, 2, 2); +DEF_SetNextOutput_And_GetInput_WithCompo(char, 2, 3); +DEF_SetNextOutput_And_GetInput_WithCompo(char, 2, 4); +DEF_SetNextOutput_And_GetInput_WithCompo(char, 3, 2); +DEF_SetNextOutput_And_GetInput_WithCompo(char, 3, 3); +DEF_SetNextOutput_And_GetInput_WithCompo(char, 3, 4); +DEF_SetNextOutput_And_GetInput_WithCompo(char, 4, 2); +DEF_SetNextOutput_And_GetInput_WithCompo(char, 4, 3); +DEF_SetNextOutput_And_GetInput_WithCompo(char, 4, 4); + +DEF_SetNextOutput_And_GetInput_WithCompo(unsigned short, 2, 2); +DEF_SetNextOutput_And_GetInput_WithCompo(unsigned short, 2, 3); +DEF_SetNextOutput_And_GetInput_WithCompo(unsigned short, 2, 4); +DEF_SetNextOutput_And_GetInput_WithCompo(unsigned short, 3, 2); +DEF_SetNextOutput_And_GetInput_WithCompo(unsigned short, 3, 3); +DEF_SetNextOutput_And_GetInput_WithCompo(unsigned short, 3, 4); +DEF_SetNextOutput_And_GetInput_WithCompo(unsigned short, 4, 2); +DEF_SetNextOutput_And_GetInput_WithCompo(unsigned short, 4, 3); +DEF_SetNextOutput_And_GetInput_WithCompo(unsigned short, 4, 4); + +DEF_SetNextOutput_And_GetInput_WithCompo(short, 2, 2); +DEF_SetNextOutput_And_GetInput_WithCompo(short, 2, 3); +DEF_SetNextOutput_And_GetInput_WithCompo(short, 2, 4); +DEF_SetNextOutput_And_GetInput_WithCompo(short, 3, 2); +DEF_SetNextOutput_And_GetInput_WithCompo(short, 3, 3); +DEF_SetNextOutput_And_GetInput_WithCompo(short, 3, 4); +DEF_SetNextOutput_And_GetInput_WithCompo(short, 4, 2); +DEF_SetNextOutput_And_GetInput_WithCompo(short, 4, 3); +DEF_SetNextOutput_And_GetInput_WithCompo(short, 4, 4); + +DEF_SetNextOutput_And_GetInput_WithCompo(int, 2, 2); +DEF_SetNextOutput_And_GetInput_WithCompo(int, 2, 3); +DEF_SetNextOutput_And_GetInput_WithCompo(int, 2, 4); +DEF_SetNextOutput_And_GetInput_WithCompo(int, 3, 2); +DEF_SetNextOutput_And_GetInput_WithCompo(int, 3, 3); +DEF_SetNextOutput_And_GetInput_WithCompo(int, 3, 4); +DEF_SetNextOutput_And_GetInput_WithCompo(int, 4, 2); +DEF_SetNextOutput_And_GetInput_WithCompo(int, 4, 3); +DEF_SetNextOutput_And_GetInput_WithCompo(int, 4, 4); +*/ + DEF_SetNextOutput_And_GetInput_WithCompo(float, 2, 2); DEF_SetNextOutput_And_GetInput_WithCompo(float, 2, 3); DEF_SetNextOutput_And_GetInput_WithCompo(float, 2, 4); diff --git a/common/clitkMemoryUsage.cxx b/common/clitkMemoryUsage.cxx index c0b78ce..e2a095d 100644 --- a/common/clitkMemoryUsage.cxx +++ b/common/clitkMemoryUsage.cxx @@ -19,7 +19,9 @@ // clitk include #include "clitkCommon.h" #include "clitkMemoryUsage.h" -#include +#ifndef _WIN32 +# include +#endif void clitk::PrintMemory(bool verbose, std::string s) { diff --git a/common/clitkXdrImageIOWriter.cxx b/common/clitkXdrImageIOWriter.cxx index 1e826db..af50b0e 100644 --- a/common/clitkXdrImageIOWriter.cxx +++ b/common/clitkXdrImageIOWriter.cxx @@ -97,7 +97,9 @@ void clitk::XdrImageIO::Write(const void* buffer) #include #include #include -#include +#ifndef _WIN32 +# include +#endif #if !defined(unix) && !defined(__APPLE__) #include #endif diff --git a/itk/clitkBackProjectImageFilter.h b/itk/clitkBackProjectImageFilter.h index 7de71a1..689e678 100644 --- a/itk/clitkBackProjectImageFilter.h +++ b/itk/clitkBackProjectImageFilter.h @@ -242,7 +242,11 @@ namespace clitk void BeforeThreadedGenerateData(void ); // Threaded Generate Data +#if ITK_VERSION_MAJOR >= 4 + void ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread, itk::ThreadIdType threadId ); +#else void ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread, int threadId ); +#endif //------------------------------------------------ diff --git a/itk/clitkBackProjectImageFilter.txx b/itk/clitkBackProjectImageFilter.txx index c070336..b1f84e2 100644 --- a/itk/clitkBackProjectImageFilter.txx +++ b/itk/clitkBackProjectImageFilter.txx @@ -303,7 +303,11 @@ namespace clitk template void BackProjectImageFilter +#if ITK_VERSION_MAJOR >= 4 + ::ThreadedGenerateData( const OutputImageRegionType & outputRegionForThread, itk::ThreadIdType threadId ) +#else ::ThreadedGenerateData( const OutputImageRegionType & outputRegionForThread, int threadId ) +#endif { //Projection pointer InputImageConstPointer inputPtr=this->GetInput(); diff --git a/itk/clitkExtractImageFilter.h b/itk/clitkExtractImageFilter.h index 7ea101a..ce31fd9 100644 --- a/itk/clitkExtractImageFilter.h +++ b/itk/clitkExtractImageFilter.h @@ -94,8 +94,12 @@ protected: const OutputImageRegionType &srcRegion); - void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, - int threadId ); +#if ITK_VERSION_MAJOR >= 4 + void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId ); +#else + void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, int threadId ); +#endif + InputImageRegionType m_ExtractionRegion; OutputImageRegionType m_OutputImageRegion; diff --git a/itk/clitkExtractImageFilter.txx b/itk/clitkExtractImageFilter.txx index 236a7cb..90fee3b 100644 --- a/itk/clitkExtractImageFilter.txx +++ b/itk/clitkExtractImageFilter.txx @@ -236,8 +236,11 @@ ExtractImageFilter template void ExtractImageFilter -::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, - int threadId) +#if ITK_VERSION_MAJOR >= 4 +::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) +#else +::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, int threadId) +#endif { itkDebugMacro(<<"Actually executing"); diff --git a/registration/clitkExtractImageFilter.h b/registration/clitkExtractImageFilter.h deleted file mode 100644 index 1e797bc..0000000 --- a/registration/clitkExtractImageFilter.h +++ /dev/null @@ -1,113 +0,0 @@ -/*========================================================================= - Program: vv http://www.creatis.insa-lyon.fr/rio/vv - - Authors belong to: - - University of LYON http://www.universite-lyon.fr/ - - Léon Bérard cancer center http://www.centreleonberard.fr - - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the copyright notices for more information. - - It is distributed under dual licence - - - BSD See included LICENSE.txt file - - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html -===========================================================================**/ -#ifndef __clitkExtractImageFilter_h -#define __clitkExtractImageFilter_h -#include "itkImageToImageFilter.h" -#include "itkSmartPointer.h" -#include "itkExtractImageFilterRegionCopier.h" - -namespace clitk -{ - -template -class ITK_EXPORT ExtractImageFilter: - public itk::ImageToImageFilter -{ -public: - /** Standard class typedefs. */ - typedef ExtractImageFilter Self; - typedef itk::ImageToImageFilter Superclass; - typedef itk::SmartPointer Pointer; - typedef itk::SmartPointer ConstPointer; - - /** Method for creation through the object factory. */ - itkNewMacro(Self); - - /** Run-time type information (and related methods). */ - itkTypeMacro(ExtractImageFilter, ImageToImageFilter); - - /** Image type information. */ - typedef TInputImage InputImageType; - typedef TOutputImage OutputImageType; - - /** Typedef to describe the output and input image region types. */ - typedef typename TOutputImage::RegionType OutputImageRegionType; - typedef typename TInputImage::RegionType InputImageRegionType; - - /** Typedef to describe the type of pixel. */ - typedef typename TOutputImage::PixelType OutputImagePixelType; - typedef typename TInputImage::PixelType InputImagePixelType; - - /** Typedef to describe the output and input image index and size types. */ - typedef typename TOutputImage::IndexType OutputImageIndexType; - typedef typename TInputImage::IndexType InputImageIndexType; - typedef typename TOutputImage::SizeType OutputImageSizeType; - typedef typename TInputImage::SizeType InputImageSizeType; - - /** ImageDimension enumeration */ - itkStaticConstMacro(InputImageDimension, unsigned int, - TInputImage::ImageDimension); - itkStaticConstMacro(OutputImageDimension, unsigned int, - TOutputImage::ImageDimension); - - typedef itk::ImageToImageFilterDetail::ExtractImageFilterRegionCopier< - itkGetStaticConstMacro(InputImageDimension), - itkGetStaticConstMacro(OutputImageDimension)> ExtractImageFilterRegionCopierType; - - void SetExtractionRegion(InputImageRegionType extractRegion); - itkGetMacro(ExtractionRegion, InputImageRegionType); - -#ifdef ITK_USE_CONCEPT_CHECKING - /** Begin concept checking */ - itkConceptMacro(InputCovertibleToOutputCheck, - (itk::Concept::Convertible)); - /** End concept checking */ -#endif - -protected: - ExtractImageFilter(); - ~ExtractImageFilter() {}; - void PrintSelf(std::ostream& os, itk::Indent indent) const; - - - virtual void GenerateOutputInformation(); - - - virtual void CallCopyOutputRegionToInputRegion(InputImageRegionType &destRegion, - const OutputImageRegionType &srcRegion); - - - void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, - int threadId ); - InputImageRegionType m_ExtractionRegion; - OutputImageRegionType m_OutputImageRegion; - -private: - ExtractImageFilter(const Self&); //purposely not implemented - void operator=(const Self&); //purposely not implemented - -}; - - -} // end namespace itk - -#ifndef ITK_MANUAL_INSTANTIATION -#include "clitkExtractImageFilter.txx" -#endif - -#endif diff --git a/registration/clitkExtractImageFilter.txx b/registration/clitkExtractImageFilter.txx deleted file mode 100644 index d321f9e..0000000 --- a/registration/clitkExtractImageFilter.txx +++ /dev/null @@ -1,274 +0,0 @@ -/*========================================================================= - Program: vv http://www.creatis.insa-lyon.fr/rio/vv - - Authors belong to: - - University of LYON http://www.universite-lyon.fr/ - - Léon Bérard cancer center http://www.centreleonberard.fr - - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the copyright notices for more information. - - It is distributed under dual licence - - - BSD See included LICENSE.txt file - - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html -===========================================================================**/ -#ifndef _clitkExtractImageFilter_txx -#define _clitkExtractImageFilter_txx -#include "clitkExtractImageFilter.h" -#include "itkImageRegionIterator.h" -#include "itkImageRegionConstIterator.h" -#include "itkObjectFactory.h" -#include "itkExtractImageFilterRegionCopier.h" -#include "itkProgressReporter.h" - - -namespace clitk -{ - -/** - * - */ -template -ExtractImageFilter -::ExtractImageFilter() -{ -} - - -/** - * - */ -template -void -ExtractImageFilter -::PrintSelf(std::ostream& os, itk::Indent indent) const -{ - Superclass::PrintSelf(os,indent); - - os << indent << "ExtractionRegion: " << m_ExtractionRegion << std::endl; - os << indent << "OutputImageRegion: " << m_OutputImageRegion << std::endl; -} - - -template -void -ExtractImageFilter -::CallCopyOutputRegionToInputRegion(InputImageRegionType &destRegion, - const OutputImageRegionType &srcRegion) -{ - ExtractImageFilterRegionCopierType extractImageRegionCopier; - extractImageRegionCopier(destRegion, srcRegion, m_ExtractionRegion); -} - - -template -void -ExtractImageFilter -::SetExtractionRegion(InputImageRegionType extractRegion) -{ - m_ExtractionRegion = extractRegion; - - unsigned int nonzeroSizeCount = 0; - InputImageSizeType inputSize = extractRegion.GetSize(); - OutputImageSizeType outputSize; - OutputImageIndexType outputIndex; - - /** - * check to see if the number of non-zero entries in the extraction region - * matches the number of dimensions in the output image. - **/ - for (unsigned int i = 0; i < InputImageDimension; ++i) - { - if (inputSize[i]) - { - outputSize[nonzeroSizeCount] = inputSize[i]; - outputIndex[nonzeroSizeCount] = extractRegion.GetIndex()[i]; - nonzeroSizeCount++; - } - } - - if (nonzeroSizeCount != OutputImageDimension) - { - itkExceptionMacro("Extraction Region not consistent with output image"); - } - - m_OutputImageRegion.SetSize(outputSize); - m_OutputImageRegion.SetIndex(outputIndex); - this->Modified(); -} - - - -/** - * ExtractImageFilter can produce an image which is a different resolution - * than its input image. As such, ExtractImageFilter needs to provide an - * implementation for GenerateOutputInformation() in order to inform - * the pipeline execution model. The original documentation of this - * method is below. - * - * \sa ProcessObject::GenerateOutputInformaton() - */ -template -void -ExtractImageFilter -::GenerateOutputInformation() -{ - // do not call the superclass' implementation of this method since - // this filter allows the input and the output to be of different dimensions - - // get pointers to the input and output - typename Superclass::OutputImagePointer outputPtr = this->GetOutput(); - typename Superclass::InputImageConstPointer inputPtr = this->GetInput(); - - if ( !outputPtr || !inputPtr) - { - return; - } - - // Set the output image size to the same value as the extraction region. - outputPtr->SetLargestPossibleRegion( m_OutputImageRegion ); - - // Set the output spacing and origin - const itk::ImageBase *phyData; - - phyData - = dynamic_cast*>(this->GetInput()); - - if (phyData) - { - // Copy what we can from the image from spacing and origin of the input - // This logic needs to be augmented with logic that select which - // dimensions to copy - - unsigned int i; - const typename InputImageType::SpacingType& - inputSpacing = inputPtr->GetSpacing(); - const typename InputImageType::DirectionType& - inputDirection = inputPtr->GetDirection(); - const typename InputImageType::PointType& - inputOrigin = inputPtr->GetOrigin(); - - typename OutputImageType::SpacingType outputSpacing; - typename OutputImageType::DirectionType outputDirection; - typename OutputImageType::PointType outputOrigin; - - if ( static_cast(OutputImageDimension) > - static_cast(InputImageDimension ) ) - { - // copy the input to the output and fill the rest of the - // output with zeros. - for (i=0; i < InputImageDimension; ++i) - { - outputSpacing[i] = inputSpacing[i]; - outputOrigin[i] = inputOrigin[i]; - for (unsigned int dim = 0; dim < InputImageDimension; ++dim) - { - outputDirection[i][dim] = inputDirection[i][dim]; - } - } - for (; i < OutputImageDimension; ++i) - { - outputSpacing[i] = 1.0; - outputOrigin[i] = 0.0; - for (unsigned int dim = 0; dim < InputImageDimension; ++dim) - { - outputDirection[i][dim] = 0.0; - } - outputDirection[i][i] = 1.0; - } - } - else - { - // copy the non-collapsed part of the input spacing and origing to the output - int nonZeroCount = 0; - for (i=0; i < InputImageDimension; ++i) - { - if (m_ExtractionRegion.GetSize()[i]) - { - outputSpacing[nonZeroCount] = inputSpacing[i]; - outputOrigin[nonZeroCount] = inputOrigin[i]; - int nonZeroCount2 = 0; - for (unsigned int dim = 0; dim < InputImageDimension; ++dim) - { - if (m_ExtractionRegion.GetSize()[dim]) - { - outputDirection[nonZeroCount][nonZeroCount2] = - inputDirection[i][dim]; - ++nonZeroCount2; - } - } - nonZeroCount++; - } - } - } - - // set the spacing and origin - outputPtr->SetSpacing( outputSpacing ); - outputPtr->SetDirection( outputDirection ); - outputPtr->SetOrigin( outputOrigin ); - outputPtr->SetNumberOfComponentsPerPixel(inputPtr->GetNumberOfComponentsPerPixel() ); - } - else - { - // pointer could not be cast back down - itkExceptionMacro(<< "itk::ExtractImageFilter::GenerateOutputInformation " - << "cannot cast input to " - << typeid(itk::ImageBase*).name() ); - } -} - -/** - * ExtractImageFilter can be implemented as a multithreaded filter. - * Therefore, this implementation provides a ThreadedGenerateData() - * routine which is called for each processing thread. The output - * image data is allocated automatically by the superclass prior to - * calling ThreadedGenerateData(). ThreadedGenerateData can only - * write to the portion of the output image specified by the - * parameter "outputRegionForThread" - * - * \sa ImageToImageFilter::ThreadedGenerateData(), - * ImageToImageFilter::GenerateData() - */ -template -void -ExtractImageFilter -::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, - int threadId) -{ - itkDebugMacro(<<"Actually executing"); - - // Get the input and output pointers - typename Superclass::InputImageConstPointer inputPtr = this->GetInput(); - typename Superclass::OutputImagePointer outputPtr = this->GetOutput(); - - // support progress methods/callbacks - itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels()); - - // Define the portion of the input to walk for this thread - InputImageRegionType inputRegionForThread; - this->CallCopyOutputRegionToInputRegion(inputRegionForThread, outputRegionForThread); - - // Define the iterators. - typedef itk::ImageRegionIterator OutputIterator; - typedef itk::ImageRegionConstIterator InputIterator; - - OutputIterator outIt(outputPtr, outputRegionForThread); - InputIterator inIt(inputPtr, inputRegionForThread); - - // walk the output region, and sample the input image - while( !outIt.IsAtEnd() ) - { - // copy the input pixel to the output - outIt.Set( static_cast(inIt.Get())); - ++outIt; - ++inIt; - progress.CompletedPixel(); - } -} - -} // end namespace clitk - -#endif diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index 41ace96..6c444dc 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -5,6 +5,7 @@ SET(SCRIPTS ${CLITK_SOURCE_DIR}/scripts/calculate_contour_stats.sh ${CLITK_SOURCE_DIR}/scripts/midp_common.sh ${CLITK_SOURCE_DIR}/scripts/registration.sh + ${CLITK_SOURCE_DIR}/scripts/compress_mhd.sh ${CLITK_SOURCE_DIR}/scripts/create_midP.sh ${CLITK_SOURCE_DIR}/scripts/create_midP-2.0.sh ${CLITK_SOURCE_DIR}/scripts/create_mhd_4D.sh diff --git a/scripts/calculate_contour_stats.sh b/scripts/calculate_contour_stats.sh index b15caa8..be10e9d 100755 --- a/scripts/calculate_contour_stats.sh +++ b/scripts/calculate_contour_stats.sh @@ -1,94 +1,51 @@ #! /bin/bash +x -select_contour_gui() -{ - local roi_list=$@ - roi=`zenity --list --title="Available Contours" --column="Please choose a contour:" $roi_list` - case $? in - 0) - if [ -z $roi ] - then - zenity --warning --text="You must choose one contour." - select_contour $roi_list - else - rtstruct_roi_name=$roi - fi;; - 1) - if zenity --question --text="Do you really wish to quit?" - then - exit - else - select_contour $roi_list - fi;; - -1) - zenity --error --text="Unexpected error. Please relaunch the application." - exit;; - esac -} +source `dirname $0`/midp_common.sh -select_contour() -{ - local roi_list=$@ - echo "Available Contours:" - for r in $roi_list; do - echo $r - done - - echo "Please choose a contour number:" - read rtstruct_roi_number -} - -select_roi() -{ - rtstruct_roi_name_list=( `clitkDicomInfo ${rtstruct_file} | grep "3006|0026" | cut -d '[' -f 4 | sed 's/| V 3006|0026[LO] [ROI Name] \|]//'` ) - rtstruct_roi_number_list=( `clitkDicomInfo ${rtstruct_file} | grep "3006|0022" | cut -d '[' -f 4 | sed 's/| V 3006|0026[LO] [ROI Number] \|]//'` ) - rtstruct_roi_list=( ) - for i in $(seq 0 1 $(( ${#rtstruct_roi_name_list[@]} - 1 ))); do - rtstruct_roi_list[$i]=${rtstruct_roi_number_list[$i]}:${rtstruct_roi_name_list[$i]} - done - - if [ $gui_mode = 1 ]; then - select_contour_gui ${rtstruct_roi_list[@]} - rtstruct_roi=`echo ${rtstruct_roi_name} | cut -d ':' -f 1` - rtstruct_roi_name=`echo ${rtstruct_roi_name} | cut -d ':' -f 2` - else - select_contour ${rtstruct_roi_list[@]} - rtstruct_roi=$rtstruct_roi_number - rtstruct_roi_name=${rtstruct_roi_name_list[$(( $rtstruct_roi_number - 1))]} - fi -} ############# main if echo $* | grep "\-h"; then - echo Usage: calculate_motion_amplitude.sh { RTSTRUCT_FILE REFERENCE_IMAGE | --gui } - + echo Usage: calculate_motion_amplitude.sh { REFERENCE_IMAGE RTSTRUCT_FILE [ RTSTRUCT_ROI | --gui ] } | --gui + echo " RTSTRUCT_REF_IMAGE: mhd of the reference image used in the contour delineation" + echo " RTSTRUCT_FILE: dicom with contours" + echo " RTSTRUCT_ROI: number of the contour whose motion to analyze" + echo " --gui: use GUI to select files" exit 0 fi -rtstruct_roi=0 +rtstruct_roi= if echo $* | grep "\-\-gui" > /dev/null 2>&1; then - if [ $# != 1 ]; then + gui_mode=1 + if [ $# = 1 ]; then + rtstruct_ref_image=`zenity --file-selection --title="Select Reference Image."` + rtstruct_file=`zenity --file-selection --title="Select RT Struct file."` + select_roi + elif [ $# = 3 ]; then + rtstruct_ref_image=$1 + rtstruct_file=$2 + select_roi + else echo Invalid arguments. Type \'`basename $0` -h\' for help exit -1 fi - gui_mode=1 - rtstruct_file=`zenity --file-selection --title="Select RT Struct file."` - select_roi - rtstruct_ref_image=`zenity --file-selection --title="Select Reference Image."` else - if [ $# != 2 ]; then + gui_mode=0 + rtstruct_ref_image=$1 + rtstruct_file=$2 + if [ $# = 2 ]; then + select_roi + elif [ $# = 3 ]; then + rtstruct_roi=$3 + rtstruct_roi_name=$rtstruct_roi + else echo Invalid arguments. Type \'`basename $0` -h\' for help exit -1 fi - gui_mode=0 - rtstruct_file=$1 - rtstruct_ref_image=$2 - select_roi fi diff --git a/scripts/calculate_motion_amplitude.sh b/scripts/calculate_motion_amplitude.sh index b40c766..c1128b0 100755 --- a/scripts/calculate_motion_amplitude.sh +++ b/scripts/calculate_motion_amplitude.sh @@ -1,27 +1,76 @@ #! /bin/bash +x +source `dirname $0`/midp_common.sh + + +calculate_motion() +{ + # calculate motion amplitudes along the 3 image axes + rm /tmp/result.txt 2> /dev/null + dir=( "\"left-right\"" "\"anterior-posterior\"" "\"cranio-caudal\"" ) + pct=( 0 33 67 ) + for i in 0 1 2; do + if [ $gui_mode = 1 ]; then + echo "${pct[$i]}"; echo "# Calculating motion along ${dir[$i]} direction.." + else + echo "Calculating motion along ${dir[$i]} direction.." + fi + + echo "Motion along ${dir[$i]} direction" >> /tmp/result.txt + clitkImageStatistics -i ${vector_file} -m ${roi_mask2} -c $i --verbose 2> /dev/null | tail -n 8 | head -n 6 >> /tmp/result.txt + min=`tail -n 2 /tmp/result.txt | head -n 1 | cut -f 2 -d ':'` + max=`tail -n 1 /tmp/result.txt | cut -f 2 -d ':'` + amp=`echo $max-$min | bc` + + echo "Amplitude: $amp" >> /tmp/result.txt + echo "" >> /tmp/result.txt + done +} + ############# main if echo $* | grep "\-h"; then - echo Usage: calculate_motion_amplitude.sh VECTOR_FILE RTSTRUCT_FILE RTSTRUCT_ROI_NUMBER RTSTRUCT_REF_IMAGE + echo "Usage: calculate_motion_amplitude.sh { VECTOR_FILE RTSTRUCT_REF_IMAGE RTSTRUCT_FILE [ RTSTRUCT_ROI_NUMBER | --gui ] } | --gui " echo " VECTOR_FILE: mhd of the vector field from where to extract motion information (may also be 4D)" + echo " RTSTRUCT_REF_IMAGE: mhd of the reference image used in the contour delineation" echo " RTSTRUCT_FILE: dicom with contours" echo " RTSTRUCT_ROI: number of the contour whose motion to analyze" - echo " RTSTRUCT_REF_IMAGE: mhd of the reference image used in the contour delineation" - + echo " --gui: use GUI to select files" exit 0 fi -if [ $# != 4 ]; then - echo Invalid arguments. Type \'`basename $0` -h\' for help - exit -1 +if echo $* | grep "\-\-gui" > /dev/null 2>&1; then + gui_mode=1 + if [ $# = 1 ]; then + vector_file=`zenity --file-selection --title="Select 4D Vector Field file."` + rtstruct_ref_image=`zenity --file-selection --title="Select Reference Image."` + rtstruct_file=`zenity --file-selection --title="Select RT Struct file."` + select_roi + elif [ $# = 4 ]; then + vector_file=$1 + rtstruct_ref_image=$2 + rtstruct_file=$3 + select_roi + else + echo Invalid arguments. Type \'`basename $0` -h\' for help + exit -1 + fi +else + gui_mode=0 + vector_file=$1 + rtstruct_ref_image=$2 + rtstruct_file=$3 + if [ $# = 4 ]; then + rtstruct_roi=$4 + rtstruct_roi_name=$rtstruct_roi + elif [ $# = 3 ]; then + select_roi + else + echo Invalid arguments. Type \'`basename $0` -h\' for help + exit -1 + fi fi -vector_file=$1 -rtstruct_file=$2 -rtstruct_roi=$3 -rtstruct_ref_image=$4 - if ! cat $vector_file | grep -q "Channels = 3"; then echo Vector file must have 3 channels. exit -2 @@ -29,7 +78,7 @@ fi # create ROI mask from rtstruct roi_mask=roi_${rtstruct_roi}.mhd -clitkDicomRTStruct2BinaryImage -i ${rtstruct_file} -o ${roi_mask} -j ${rtstruct_ref_image} -r ${rtstruct_roi} 2> /tmp/err.txt +clitkDicomRTStruct2Image -i ${rtstruct_file} -o ${roi_mask} -j ${rtstruct_ref_image} -r ${rtstruct_roi} 2> /tmp/err.txt if cat /tmp/err.txt | grep -q "No ROI"; then echo Invalid contour number. exit -3 @@ -39,20 +88,20 @@ fi roi_mask2=resampled_${roi_mask} clitkResampleImage -i ${roi_mask} -o ${roi_mask2} --like ${vector_file} -# calculate motion amplitudes along the 3 image axes -dir=( sagittal coronal axial ) -for i in 0 1 2; do - echo Motion along ${dir[$i]} direction - clitkImageStatistics -i ${vector_file} -m ${roi_mask2} -c $i --verbose 2> /dev/null | tail -n 8 | head -n 6 > /tmp/res.txt - min=`tail -n 2 /tmp/res.txt | head -n 1 | cut -f 2 -d ':'` - max=`tail -n 1 /tmp/res.txt | cut -f 2 -d ':'` - amp=`echo $max-$min | bc` - cat /tmp/res.txt - echo "Amplitude: $amp" - echo -done +if [ $gui_mode = 1 ]; then + calculate_motion | zenity --progress --auto-close --percentage=0 --text="" +else + calculate_motion +fi + +if [ $gui_mode = 1 ]; then + cat /tmp/result.txt | zenity --text-info --title "Restuls for \"${rtstruct_roi_name}\"" +else + echo "Restuls for \"${rtstruct_roi_name}\"" + cat /tmp/result.txt +fi rm `basename $roi_mask .mhd`.{mhd,raw} rm `basename $roi_mask2 .mhd`.{mhd,raw} rm /tmp/err.txt -rm /tmp/res.txt +rm /tmp/result.txt diff --git a/scripts/compress_mhd.sh b/scripts/compress_mhd.sh new file mode 100755 index 0000000..f2e8912 --- /dev/null +++ b/scripts/compress_mhd.sh @@ -0,0 +1,69 @@ +#! /bin/bash + +compress_file() +{ + local f=$1 + if [ "$verbose" = "1" ]; then + echo "Compressing $f..." + fi + + local msg=`clitkImageConvert -i $f -o $f -c` + if [ -z "$msg" ]; then + raw=`echo $f | sed 's/\.mhd/\.raw/'` + if test -e $raw; then + rm $raw + fi + fi +} + +compress_directory() +{ + local input=$1 + + files=$(find $input -name "*.mhd" | sort) + for f in $files; do + if ! grep -iq 'LIST' $f; then + # process all except 4D files + compress_file $f + else + # process only 4D files (just update pointers to new zraw files) + # assumes each .RAW in the list has a corresponding .MHD, which + # must be compressed separately + sed -i 's/\.raw/\.zraw/g' $f + if grep -q "CompressedData" $f; then + sed -i 's/CompressedData.*/CompressedData = True/' $f + else + tmp=/tmp/$RANDOM.mhd + echo "CompressedData = True" > $tmp + cat $f >> $tmp + mv $tmp $f + fi + fi + done +} + +# main program + +if [ $# -lt 1 -o $# -gt 2 ]; then + echo "Invalid params. `basename $0` [-h | --help] for help" 1>&2 + exit -1 +fi + +if [ -n "`echo $@ | grep '\-h\|--help'`" ]; then + echo "Usage: `basename $0` {FILE | DIRECTORY | -h | --help | -v}" + exit 0 +fi + +if [ -n "`echo $@ | grep '\-v'`" ]; then + echo Verbose mode : ON + verbose=1 +fi + +input=$1 +if test -d $input; then + compress_directory $input +elif test -f $input; then + compress_file $input +else + echo "Unknow input file type." 1>&2 +fi diff --git a/scripts/create_mhd_4D.sh b/scripts/create_mhd_4D.sh index b363f7e..24d3fd1 100755 --- a/scripts/create_mhd_4D.sh +++ b/scripts/create_mhd_4D.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/sh +x write_mhd_4D() @@ -12,11 +12,12 @@ write_mhd_4D() /DimSize/ s/.*/& $nbph/ s/ElementDataFile = .*/ElementDataFile = LIST/" > "$1/$file_name_4D" - for ph in $listph + for ph in ${listph[@]} do ph=`basename $ph` echo "$ph" >> "$1/$file_name_4D" done + echo $1/$file_name_4D } ################################################# @@ -40,25 +41,41 @@ list_prefix="" list_phase_file=`find $1 -maxdepth 1 -iname "*[0-9]*.mhd"` for phase_file in $list_phase_file do - phase_file_name=`basename $phase_file` - if [[ ! -z `echo "$phase_file_name" | grep "__[0-9]"` ]] + if grep -q "NDims = 4" $phase_file 2> /dev/null then - prefix=`echo $phase_file_name | sed "s/__[0-9].*/__/"` - else - if [[ ! -z `echo "$phase_file_name" | grep "[0-9]-.*\]"` ]] - then - if [[ ! -z `echo "$phase_file_name" | grep "[0-9][0-9]-.*\]"` ]] - then - prefix=`echo $phase_file_name | sed "s/[0-9][0-9]-.*//"` - else - prefix=`echo $phase_file_name | sed "s/[0-9]-.*//"` - fi - else - prefix="NONE" - fi + #echo $phase_file is 4D + continue; + fi; + + phase_file_name=`basename $phase_file .mhd` +# if [[ ! -z `echo "$phase_file_name" | grep "__[0-9]"` ]] +# then +# prefix=`echo $phase_file_name | sed "s/__[0-9].*/__/"` +# else +# if [[ ! -z `echo "$phase_file_name" | grep "[0-9]-.*\]"` ]] +# then +# if [[ ! -z `echo "$phase_file_name" | grep "[0-9][0-9]-.*\]"` ]] +# then +# prefix=`echo $phase_file_name | sed "s/[0-9][0-9]-.*//"` +# else +# prefix=`echo $phase_file_name | sed "s/[0-9]-.*//"` +# fi +# else +# prefix="NONE" +# fi +# fi + + # preffix: grep sequence of characters followed by sequence of numbers and remove sequence of numbers + # prefix=`echo $phase_file_name | grep -o "\(^[[:alpha:][:punct:]]*\)\([[:digit:]\.\_\-]\+\)" | sed 's/\(^[[:alpha:][:punct:]]*\)\([[:digit:]\.\_\-]\+\)/\1/'` + prefix=`echo $phase_file_name | grep -o "\(^[[:alpha:][:punct:]]*\)\([[:digit:]]\+\)\([\.\_\-]*\)"` + prefix=`echo $prefix | sed 's/^\-\+//' | sed 's/\(^[[:alpha:][:punct:]]*\)\([[:digit:]]\+\)\([\.\_\-]*\)/\1/'` + if [[ -z $prefix ]] + then + prefix="NONE" fi - if [[ -z `echo "$list_prefix" | grep "$prefix"` ]] + # register new preffix if not yet done + if [[ -z `echo "$list_prefix" | grep -w -- "$prefix"` ]] then list_prefix="$list_prefix $prefix" fi @@ -76,38 +93,60 @@ do list_phase_file_prefix=`find $1 -maxdepth 1 -iname "${prefix}[0-9]*.mhd"` for phase_file_prefix in $list_phase_file_prefix do - phase_file_prefix_name=`basename $phase_file_prefix` - if [[ ! -z `echo "$phase_file_prefix_name" | grep "__[0-9]"` ]] + if grep -q "NDims = 4" $phase_file_prefix 2> /dev/null then + #echo $phase_file_prefix is 4D + continue; + fi; + phase_file_prefix_name=`basename $phase_file_prefix .mhd` +# if [[ ! -z `echo "$phase_file_prefix_name" | grep "__[0-9]"` ]] +# then +# suffix="NONE" +# else +# if [[ ! -z `echo "$phase_file_prefix_name" | grep "[0-9]-.*\]"` ]] +# then +# suffix=`echo $phase_file_prefix_name | sed "s/.*[0-9]-//;s/_\.mhd//;s/\.mhd//"` +# else +# suffix="NONE" +# fi +# fi +# + + # suffix: grep sequence of numbers followed by sequence of characters and remove sequence of numbers + # suffix=`echo $phase_file_prefix_name | grep -o "\([[:digit:]\.\_\-]\+\)\([[:alpha:][:punct:]]*$\)" | sed 's/\([[:digit:]\.\_\-]\+\)\([[:alpha:][:punct:]]*$\)/\2/'` + suffix=`echo $phase_file_prefix_name | grep -o "\([\.\_\-]*\)\([[:digit:]]\+\)\([[:alpha:][:punct:]]*$\)"` + if ! echo $suffix | grep -qo "^\-\+"; then + suffix=`echo $suffix | sed 's/\([\.\_\-]*\)\([[:digit:]]\+\)\([[:alpha:][:punct:]]*$\)/\3/'` + fi + suffix=`echo $suffix | sed 's/[\.\_\-]\+$//'` + if [[ -z $suffix ]] + then suffix="NONE" - else - if [[ ! -z `echo "$phase_file_prefix_name" | grep "[0-9]-.*\]"` ]] - then - suffix=`echo $phase_file_prefix_name | sed "s/.*[0-9]-//;s/_\.mhd//;s/\.mhd//"` - else - suffix="NONE" - fi fi - if [[ -z `echo "$list_suffix" | grep "$suffix"` ]] + # register new suffix if not yet done + if [[ -z `echo "$list_suffix" | grep -w -- "$suffix"` ]] then list_suffix="$list_suffix $suffix" fi done + for suffix in $list_suffix do if [ "$suffix" = "NONE" ] then suffix="" fi - nbph=`find $1 -maxdepth 1 -iname "*${prefix}*[0-9]*${suffix}*.mhd" | wc -l` - orig=`find $1 -maxdepth 1 -iname "*${prefix}*[0-9]*${suffix}*.mhd" | sort | head -n 1` - listph=`find $1 -maxdepth 1 -iname "*${prefix}*[0-9]*${suffix}*.raw" | sort` - - file_name_4D="${prefix}4D${suffix}.mhd" - - write_mhd_4D $1 + orig=`find $1 -maxdepth 1 -iname "${prefix}[0-9]*${suffix}*.mhd" | grep "${prefix}[[:digit:][:punct:]]\+${suffix}[\.\_\-]*.mhd" | sort | head -n 1` + listph=( `find $1 -maxdepth 1 -iname "${prefix}[0-9]*${suffix}*.*raw" | grep "${prefix}[[:digit:][:punct:]]\+${suffix}[\.\_\-]*.z*raw" | sort` ) + nbph=${#listph[@]} + + # only create 4D file if potential number of phases is > 1 + if [ $nbph -gt 1 ]; then + file_name_4D="${prefix}4D${suffix}.mhd" + write_mhd_4D $1 + fi done diff --git a/scripts/create_midP_masks-2.0.sh b/scripts/create_midP_masks-2.0.sh index 6fa7476..10cd52a 100755 --- a/scripts/create_midP_masks-2.0.sh +++ b/scripts/create_midP_masks-2.0.sh @@ -53,8 +53,12 @@ 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/patient_mask_$phase_nb.mhd -o $mask_dir_tmp/patient_mask_$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 - clitkResampleImage -i $mask_dir_tmp/bones_$phase_nb.mhd -o $mask_dir_tmp/bones_$phase_nb.mhd --like $mask_dir_tmp/patient_$phase_nb.mhd + if [ "$mask_type" != "patient" ]; then + 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 + fi + if [ "$mask_type" == "mm" ]; then + clitkResampleImage -i $mask_dir_tmp/bones_$phase_nb.mhd -o $mask_dir_tmp/bones_$phase_nb.mhd --like $mask_dir_tmp/patient_$phase_nb.mhd + fi } compute_motion_mask() @@ -66,7 +70,6 @@ compute_motion_mask() 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 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 --featureBones $mask_dir_tmp/bones_$phase_nb.mhd --fillingLevel $FillingLevel --offsetDetect $MotionMaskOffsetDetect --pad --writeFeature $mask_dir_tmp/feature_$phase_nb.mhd $MotionMaskExtra #--monitor=$mask_dir_tmp/monitor_$phase_nb.mhd } @@ -130,55 +133,18 @@ create_registration_masks() create_banded_mask $mask_dir_tmp/outside_$phase_nb.mhd $mask_dir_tmp/${mask_type}_outside_$phase_nb.mhd $mask_dir_tmp/banded_outside_$phase_nb.mhd $mask_dir_tmp/banded_mask_outside_$phase_nb.mhd 4 } -create_registration_motion_masks() +mm_preprocessing() { - # extract inside and outside 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 - clitkMorphoMath -i $mask_dir_tmp/mm_$phase_nb.mhd -o $mask_dir_tmp/mask_inside_$phase_nb.mhd --type 1 --radius 8 - 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/banded_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 - clitkMorphoMath -i $mask_dir_tmp/mm_outside_$phase_nb.mhd -o $mask_dir_tmp/mask_outside_$phase_nb.mhd --type 1 --radius 8 - 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/banded_mask_outside_$phase_nb.mhd 4 -} + extract_patient -create_registration_lung_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/lungs_$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/lungs_$phase_nb.mhd --outsideValue -1200 --fg + if [ "$mask_type" != "patient" ]; then + extract_lungs + fi - # 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 - clitkMorphoMath -i $mask_dir_tmp/lungs_$phase_nb.mhd -o $mask_dir_tmp/mask_inside_$phase_nb.mhd --type 1 --radius 8 - create_banded_mask $mask_dir_tmp/inside_$phase_nb.mhd $mask_dir_tmp/lungs_$phase_nb.mhd $mask_dir_tmp/banded_inside_$phase_nb.mhd $mask_dir_tmp/banded_mask_inside_$phase_nb.mhd 4 - # outside - clitkBinarizeImage -i $mask_dir_tmp/outside_$phase_nb.mhd -o $mask_dir_tmp/lungs_outside_$phase_nb.mhd -l -999 -u 4000 --mode both - clitkMorphoMath -i $mask_dir_tmp/lungs_outside_$phase_nb.mhd -o $mask_dir_tmp/mask_outside_$phase_nb.mhd --type 1 --radius 8 - create_banded_mask $mask_dir_tmp/outside_$phase_nb.mhd $mask_dir_tmp/lungs_outside_$phase_nb.mhd $mask_dir_tmp/banded_outside_$phase_nb.mhd $mask_dir_tmp/banded_mask_outside_$phase_nb.mhd 4 -} + if [ "$mask_type" == "mm" ]; then + extract_bones + fi -mm_preprocessing() -{ - extract_patient - extract_bones - extract_lungs # remove_tmp_masks 1 if [ $resample_spacing -ne 0 ] ; then resample @@ -233,25 +199,6 @@ wait_mm_creation() do_mm=1 fi fi -# elif [ "$mask_type" == "lungs" ]; then -# nb_mm_masks=`ls $mask_dir/lungs_outside*.mhd | wc -l` -# nb_in_masks=`ls $mask_dir/mask_in*.mhd | wc -l` -# nb_out_masks=`ls $mask_dir/mask_out*.mhd | wc -l` -# if [ $nb_mm_masks != $nb_phases -o $nb_in_masks != $nb_phases -o $nb_out_masks != $nb_phases ]; then -# # if the mask dir is invalid, remove it and recreate all masks, just in case. -# rm -fr $mask_dir 2> /dev/null -# do_mm=1 -# fi -# elif [ "$mask_type" == "mm" ]; then -# nb_mm_masks=`ls $mask_dir/mm_outside*.mhd | wc -l` -# nb_in_masks=`ls $mask_dir/mask_in*.mhd | wc -l` -# nb_out_masks=`ls $mask_dir/mask_out*.mhd | wc -l` -# if [ $nb_mm_masks != $nb_phases -o $nb_in_masks != $nb_phases -o $nb_out_masks != $nb_phases ]; then -# # if the mask dir is invalid, remove it and recreate all masks, just in case. -# rm -fr $mask_dir 2> /dev/null -# do_mm=1 -# fi -# fi fi if [ $do_mm = 1 ]; then @@ -401,7 +348,7 @@ motion_mask() if [ $# -ne 4 -a $# -ne 2 -a $# -ne 1 ]; then echo "Usage: $0 CT_4D TYPE [RESAMPLE_SPACING RESAMPLE_ALGORITHM]" - echo " TYPE: \"motion\" (traditional motion masks); \"lungs\" (lung masks); \"patient\" (patient mask only)" + echo " TYPE: \"mm\" (traditional motion masks); \"lungs\" (lung masks); \"patient\" (patient mask only)" exit -1 fi diff --git a/scripts/midp_common.sh b/scripts/midp_common.sh index 1ac9529..a5d0baf 100755 --- a/scripts/midp_common.sh +++ b/scripts/midp_common.sh @@ -98,28 +98,28 @@ extract_4d_phase_numbers() 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 + cat $mhd4d | grep ".z*raw" | sed 's:.z*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]\+"` ) + phase_nbs=( `cat $mhd4d | grep ".z*raw" | sed 's:.z*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` + nb_phases_found=`cat $mhd4d | grep ".z*raw" | sed 's:.z*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]\+"` ) + phase_nbs=( `cat $mhd4d | grep ".z*raw" | sed 's:.z*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` + nb_phases_found=`cat $mhd4d | grep ".z*raw" | sed 's:.z*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]\+"` ) + phase_nbs=( `cat $mhd4d | grep ".z*raw" | sed 's:.z*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 @@ -142,7 +142,7 @@ extract_4d_phases() echo "4D file is $mhd4d" # array of phase files - phase_files=( `cat $mhd4d | grep ".raw" | sed 's:.raw:.mhd:'` ) + phase_files=( `cat $mhd4d | grep ".z*raw" | sed 's:.z*raw:.mhd:'` ) echo "Phase files are ${phase_files[@]}" extract_4d_phase_numbers $mhd4d @@ -161,7 +161,7 @@ extract_4d_phases_ref() extract_4d_phases $1 # reference phase file - ref_phase_file=`cat $mhd4d | grep ".raw" | sed 's:.raw:.mhd:' | grep $2` + ref_phase_file=`cat $mhd4d | grep ".z*raw" | sed 's:.z*raw:.mhd:' | grep $2` echo "Reference phase is $ref_phase_file" # reference phase number @@ -198,14 +198,81 @@ average_temporal_dimension() local tot=$tmp.mhd local dir=`dirname $1` - local first=`grep raw $1 | sed 's/raw/mhd/g' | head -n 1` + local first=`grep z*raw $1 | sed 's/z*raw/mhd/g' | head -n 1` clitkImageArithm -i $dir/$first -o $tot -t 1 -s 0 - local nbphases=`grep raw $1 | sed 's/raw/mhd/g' | wc -l` - for i in $(grep raw $1 | sed 's/raw/mhd/g'); do + local nbphases=`grep z*raw $1 | sed 's/z*raw/mhd/g' | wc -l` + for i in $(grep z*raw $1 | sed 's/z*raw/mhd/g'); do clitkImageArithm -i $dir/$i -j $tot -o $tot done clitkImageArithm -i $tot -o $2 -t 11 -s $nbphases rm $tmp.* } + +select_contour_gui() +{ + local roi_list=$@ + roi=`zenity --list --title="Available Contours" --column="Please choose a contour:" $roi_list` + case $? in + 0) + if [ -z $roi ] + then + zenity --warning --text="You must choose one contour." + select_contour $roi_list + else + rtstruct_roi_name=$roi + fi;; + 1) + if zenity --question --text="Do you really wish to quit?" + then + exit + else + select_contour $roi_list + fi;; + -1) + zenity --error --text="Unexpected error. Please relaunch the application." + exit;; + esac +} + +select_contour() +{ + local roi_list=$@ + echo "Available Contours:" + for r in $roi_list; do + echo $r + done + + echo "Please choose a contour number:" + read rtstruct_roi_index + let i=0 + for r in $roi_list; do + if [ $rtstruct_roi_index = `echo $r | cut -d ':' -f 1` ]; then + rtstruct_roi_index=$i + break; + fi + let i=i+1 + done + +} + +select_roi() +{ + rtstruct_roi_name_list=( `clitkDicomInfo ${rtstruct_file} | grep "3006|0026" | cut -d '[' -f 4 | sed 's/| V 3006|0026[LO] [ROI Name] \|]//'` ) + rtstruct_roi_number_list=( `clitkDicomInfo ${rtstruct_file} | grep "3006|0022" | cut -d '[' -f 4 | sed 's/| V 3006|0026[LO] [ROI Number] \|]//'` ) + rtstruct_roi_list=( ) + for i in $(seq 0 1 $(( ${#rtstruct_roi_name_list[@]} - 1 ))); do + rtstruct_roi_list[$i]=${rtstruct_roi_number_list[$i]}:${rtstruct_roi_name_list[$i]} + done + + if [ $gui_mode = 1 ]; then + select_contour_gui ${rtstruct_roi_list[@]} + rtstruct_roi=`echo ${rtstruct_roi_name} | cut -d ':' -f 1` + rtstruct_roi_name=`echo ${rtstruct_roi_name} | cut -d ':' -f 2` + else + select_contour ${rtstruct_roi_list[@]} + rtstruct_roi=${rtstruct_roi_number_list[$(( $rtstruct_roi_index ))]} + rtstruct_roi_name=${rtstruct_roi_name_list[$(( $rtstruct_roi_index ))]} + fi +} \ No newline at end of file diff --git a/segmentation/clitkMotionMask.ggo b/segmentation/clitkMotionMask.ggo index f879a36..b9e9d1c 100644 --- a/segmentation/clitkMotionMask.ggo +++ b/segmentation/clitkMotionMask.ggo @@ -32,10 +32,12 @@ option "writeFeature" - "Write the combined feature image" string no section "Ellipsoide initialization" option "ellips" - "Input ellipsoide image (=1, at half resolution)" string no -option "offset" - "Offset for ellips center from body center of gravity (default= 0,-50,0 mm)" double no multiple -option "axes" - "Half axes of the ellips (default= 100,30,150)" double no multiple option "writeEllips" - "Write the initial ellipsoide image" string no option "writeDistMap" - "Write the distance map" string no +#defgroup "EllipseParams" groupdesc="an option of this group is required" required +option "ellipseAutoDetect" - "Auto-detect offset and axes of initial ellipse" flag off +option "offset" - "Offset for ellips center from body center of gravity (default= 0,-50,0 mm)" double no multiple +option "axes" - "Half axes of the ellips (default= 100,30,150)" double no multiple section "Ellipsoide growing" diff --git a/segmentation/clitkMotionMaskGenericFilter.h b/segmentation/clitkMotionMaskGenericFilter.h index dfab428..2a89fc7 100644 --- a/segmentation/clitkMotionMaskGenericFilter.h +++ b/segmentation/clitkMotionMaskGenericFilter.h @@ -118,7 +118,7 @@ protected: template typename itk::Image::Pointer Resample(typename itk::Image::Pointer input ); template - typename itk::Image::Pointer InitializeEllips( typename itk::Vector center, typename itk::Image::Pointer bones_low); + typename itk::Image::Pointer InitializeEllips( typename itk::Vector center, typename itk::Image::Pointer bones_low, typename itk::Image::Pointer lungs_low); template void UpdateWithDim(std::string PixelType); diff --git a/segmentation/clitkMotionMaskGenericFilter.txx b/segmentation/clitkMotionMaskGenericFilter.txx index 56fadac..c6476c2 100644 --- a/segmentation/clitkMotionMaskGenericFilter.txx +++ b/segmentation/clitkMotionMaskGenericFilter.txx @@ -27,6 +27,8 @@ * ===================================================*/ +#include "itkLabelImageToShapeLabelMapFilter.h" +#include "itkShapeLabelObject.h" namespace clitk { @@ -480,7 +482,7 @@ MotionMaskGenericFilter::Resample( typename itk::Image typename itk::Image::Pointer -MotionMaskGenericFilter::InitializeEllips( typename itk::Vector center, typename itk::Image::Pointer bones_low ) +MotionMaskGenericFilter::InitializeEllips( typename itk::Vector center, typename itk::Image::Pointer bones_low, typename itk::Image::Pointer lungs_low ) { // ImageTypes @@ -511,24 +513,88 @@ MotionMaskGenericFilter::InitializeEllips( typename itk::Vector offset; - if(m_ArgsInfo.offset_given== Dimension) { - for(unsigned int i=0; i centerEllips; + typename itk::Vector axes; + if (m_ArgsInfo.ellipseAutoDetect_flag) { + if(m_Verbose) { + std::cout<<"Auto-detecting intial ellipse..."<GetLargestPossibleRegion(); + typename InternalImageType::SizeType size = region_before.GetSize(); + size[2] /= 2; + region.SetSize(size); + lungs_low->SetRegions(region); + + // compute statistics of the (mirroed) lung region in order to guess the params of the ellipse + typedef itk::LabelImageToShapeLabelMapFilter LabelImageToShapeLabelMapFilter; + typename LabelImageToShapeLabelMapFilter::Pointer label_filter = LabelImageToShapeLabelMapFilter::New(); + label_filter->SetInput(lungs_low); + label_filter->Update(); + + typename InternalImageType::SpacingType spacing = lungs_low->GetSpacing(); + typedef typename LabelImageToShapeLabelMapFilter::OutputImageType::LabelObjectType LabelType; + const LabelType* label = dynamic_cast(label_filter->GetOutput()->GetNthLabelObject(0)); + + // lungs' barycenter + typename LabelType::CentroidType lung_centroid = label->GetCentroid(); + + // try to guess ideal ellipse axes from the lungs' bounding box and centroid + // with some hard-coded "magic" constants... +#if ITK_VERSION_MAJOR >= 4 + typename LabelType::RegionType lung_bbox = label->GetBoundingBox(); +#else + typename LabelType::RegionType lung_bbox = label->GetRegion(); +#endif + axes[0] = 0.95*lung_bbox.GetSize()[0]*spacing[0]/2; + axes[1] = 0.3*lung_bbox.GetSize()[1]*spacing[1]/2; + axes[2] = 1.25*fabs(lung_centroid[2] - center[2]); + + // ellipse's center in XY is the center of the lungs' bounding box + typename InternalImageType::PointType origin = lungs_low->GetOrigin(); + centerEllips[0] = origin[0] + (lung_bbox.GetIndex()[0] + lung_bbox.GetSize()[0]/2)*spacing[0]; + centerEllips[1] = origin[1] + (lung_bbox.GetIndex()[1] + lung_bbox.GetSize()[1]/2)*spacing[1]; + centerEllips[2] = center[2]; + + lungs_low->SetRegions(region_before); + + if(m_Verbose) { + std::cout << "Lungs'centroid at " << lung_centroid << std::endl; + std::cout << "Ellipse center at " << centerEllips << std::endl; + std::cout << "Ellipse axes as " << axes << std::endl; + std::cout << "Lung's bounding box (index,size) " << lung_bbox.GetIndex() << lung_bbox.GetSize() << std::endl; + } } - itk::Vector centerEllips=center+offset; - if (m_Verbose) { - std::cout<<"Placing the center of the initial ellipsoide at (mm) "< offset; + if(m_ArgsInfo.offset_given== Dimension) { + for(unsigned int i=0; iAllocate(); ellips->FillBuffer(0); - // Axes - typename itk::Vector axes; - if (m_ArgsInfo.axes_given==Dimension) - for(unsigned int i=0; iGetLargestPossibleRegion()); itEllips.GoToBegin(); @@ -727,7 +782,7 @@ MotionMaskGenericFilter::UpdateWithDimAndPixelType() //---------------------------------------------------------------------------------------------------- // Ellipsoide initialization //---------------------------------------------------------------------------------------------------- - typename InternalImageType::Pointer m_Ellips= InitializeEllips(center,bones_low); + typename InternalImageType::Pointer m_Ellips= InitializeEllips(center,bones_low,lungs_low); //---------------------------------------------------------------------------------------------------- // Grow ellips @@ -1075,6 +1130,10 @@ MotionMaskGenericFilter::UpdateWithDimAndPixelType() distanceMapImageFilter->SetInsideIsPositive(false); if (m_Verbose) std::cout<<"Calculating distance map..."<Update(); + if (m_ArgsInfo.writeDistMap_given) { + writeImage(distanceMapImageFilter->GetOutput(), m_ArgsInfo.writeDistMap_arg, m_Verbose); + + } //--------------------------------- // Grow while monitoring lung volume coverage diff --git a/tools/clitkBackProjectImage.ggo b/tools/clitkBackProjectImage.ggo index 24e1de1..995c14c 100644 --- a/tools/clitkBackProjectImage.ggo +++ b/tools/clitkBackProjectImage.ggo @@ -29,6 +29,7 @@ option "axis" - "Specify the source to axis distance in mm" float no d option "angle" - "Specify the projection angle" float no default="0.0" option "matrix" - "Rigid tranform prior to projection (4x4)" string no option "pad" - "Padding value" float no default="0.0" +option "panel_shift" - "Precise position of the panel in mm" double multiple no section "Output Image" diff --git a/tools/clitkBackProjectImageGenericFilter.txx b/tools/clitkBackProjectImageGenericFilter.txx index 01dfe6a..52dd428 100644 --- a/tools/clitkBackProjectImageGenericFilter.txx +++ b/tools/clitkBackProjectImageGenericFilter.txx @@ -72,6 +72,8 @@ namespace clitk iso[i]=m_ArgsInfo.iso_arg[i]; filter->SetIsoCenter(iso); } + if (m_ArgsInfo.panel_shift_given) + filter->SetPanelShift(m_ArgsInfo.panel_shift_arg[0], m_ArgsInfo.panel_shift_arg[1]); filter->SetSourceToScreen(m_ArgsInfo.screen_arg); filter->SetSourceToAxis(m_ArgsInfo.axis_arg); filter->SetProjectionAngle(m_ArgsInfo.angle_arg); diff --git a/tools/clitkImageConvertGenericFilter.cxx b/tools/clitkImageConvertGenericFilter.cxx index b7702cc..e8d8efb 100644 --- a/tools/clitkImageConvertGenericFilter.cxx +++ b/tools/clitkImageConvertGenericFilter.cxx @@ -25,9 +25,10 @@ clitk::ImageConvertGenericFilter::ImageConvertGenericFilter(): clitk::ImageToImageGenericFilter("ImageConvert") { mOutputPixelTypeName = "NotSpecified"; - mWarningOccur = false; - mWarning = ""; mDisplayWarning = true; + mWarning = ""; + mWarningOccur = false; + InitializeImageType<2>(); InitializeImageType<3>(); InitializeImageType<4>(); @@ -40,6 +41,10 @@ template void clitk::ImageConvertGenericFilter::InitializeImageType() { ADD_DEFAULT_IMAGE_TYPES(Dim); + ADD_VEC_IMAGE_TYPE(Dim, 2, float); + ADD_VEC_IMAGE_TYPE(Dim, 3, float); + ADD_VEC_IMAGE_TYPE(Dim, 2, double); + ADD_VEC_IMAGE_TYPE(Dim, 3, double); } //-------------------------------------------------------------------- @@ -48,7 +53,6 @@ void clitk::ImageConvertGenericFilter::InitializeImageType() template void clitk::ImageConvertGenericFilter::UpdateWithInputImageType() { - // Verbose stuff if (m_IOVerbose) { if (m_InputFilenames.size() == 1) { @@ -66,91 +70,57 @@ void clitk::ImageConvertGenericFilter::UpdateWithInputImageType() } } - if ((m_PixelTypeName == mOutputPixelTypeName) || (mOutputPixelTypeName == "NotSpecified")) { - // typename InputImageType::Pointer input = clitk::readImage(m_InputFilenames); typename InputImageType::Pointer input = this->template GetInput(0); - //clitk::writeImage(input, mOutputFilename, m_IOVerbose); this->SetNextOutput(input); } else { -#define TRY_TYPE(TYPE) \ - if (IsSameType(mOutputPixelTypeName)) { UpdateWithOutputType(); return; } - TRY_TYPE(char); - // TRY_TYPE(signed char); - TRY_TYPE(uchar); - TRY_TYPE(short); - TRY_TYPE(ushort); - TRY_TYPE(int); // no uint ... - TRY_TYPE(float); - TRY_TYPE(double); -#undef TRY_TYPE - - std::string list = CreateListOfTypes(); - std::cerr << "Error, I don't know the output type '" << mOutputPixelTypeName - << "'. " << std::endl << "Known types are " << list << "." << std::endl; - exit(0); + // "trick" to call independent versions of update according to the + // pixel type (vector or scalar), using partial specializations + if (!UpdateWithSelectiveOutputType::IS_VECTOR>::Run(*this, mOutputPixelTypeName)) + exit(-1); } } //==================================================================== //==================================================================== -template -void clitk::ImageConvertGenericFilter::UpdateWithOutputType() -{ - // Read - typename InputImageType::Pointer input =this->template GetInput(0); - - // Typedef - typedef typename InputImageType::PixelType PixelType; - // Warning +template +void clitk::ImageConvertGenericFilter::CheckTypes( + std::string inType, std::string outType +) +{ std::ostringstream osstream; if (std::numeric_limits::is_signed) { if (!std::numeric_limits::is_signed) { - osstream << "Warning, input type is signed (" << m_PixelTypeName << ") while output type is not (" - << mOutputPixelTypeName << "), use at your own responsability." << std::endl; - mWarningOccur = true; + osstream << "Warning, input type is signed ("; } } if (!std::numeric_limits::is_integer) { if (std::numeric_limits::is_integer) { - osstream << "Warning, input type is not integer (" << m_PixelTypeName << ") while output type is (" - << mOutputPixelTypeName << "), use at your own responsability." << std::endl; - mWarningOccur = true; + osstream << "Warning, input type is not integer ("; } } // DD(std::numeric_limits::digits10); // DD(std::numeric_limits::digits10); if (!std::numeric_limits::is_integer) { if (std::numeric_limits::is_integer) { - osstream << "Warning, input type is not integer (" << m_PixelTypeName << ") while output type is (" - << mOutputPixelTypeName << "), use at your own responsability." << std::endl; - mWarningOccur = true; + osstream << "Warning, input type is not integer ("; } } if (std::numeric_limits::digits10 > std::numeric_limits::digits10) { - osstream << "Warning, possible loss of precision : input type is (" << m_PixelTypeName << ") while output type is (" - << mOutputPixelTypeName << "), use at your own responsability." << std::endl; - mWarningOccur = true; + osstream << "Warning, possible loss of precision : input type is (" ; } - mWarning = osstream.str(); - if (mDisplayWarning) { - std::cerr << mWarning; + if (!osstream.str().empty()) + { + mWarningOccur = true; + osstream << inType << ") while output type is (" << outType << "), use at your own responsability." << std::endl; + mWarning = osstream.str(); + if (mDisplayWarning) { + std::cerr << mWarning; + } } - - // Cast - typedef itk::Image OutputImageType; - typedef itk::CastImageFilter FilterType; - typename FilterType::Pointer filter = FilterType::New(); - filter->SetInput(input); - filter->Update(); - - // Write - SetNextOutput(filter->GetOutput()); - //clitk::writeImage(filter->GetOutput(), mOutputFilename, m_IOVerbose); } -//==================================================================== #endif /* end #define CLITKIMAGECONVERTGENERICFILTER_CXX */ diff --git a/tools/clitkImageConvertGenericFilter.h b/tools/clitkImageConvertGenericFilter.h index 6064b18..2071714 100644 --- a/tools/clitkImageConvertGenericFilter.h +++ b/tools/clitkImageConvertGenericFilter.h @@ -32,9 +32,28 @@ // itk include #include "itkCastImageFilter.h" +#include "itkVectorCastImageFilter.h" + namespace clitk { + template + class ImageConvertTraits + { + public: + enum { IS_VECTOR = false }; + ImageConvertTraits() { + TPixel p = "SCALAR"; + } + }; + + template < class TPixel, unsigned int Comp > + class ImageConvertTraits< itk::Vector > + { + public: + enum { IS_VECTOR = true }; + }; + class ImageConvertGenericFilter: public clitk::ImageToImageGenericFilter { @@ -51,6 +70,8 @@ namespace clitk { itkNewMacro(Self); // Members functions + std::string GetInputPixelTypeName() { return m_PixelTypeName; } + std::string GetOutputPixelTypeName() { return mOutputPixelTypeName; } void SetOutputPixelType(std::string p) { mOutputPixelTypeName = p; } bool IsWarningOccur() { return mWarningOccur; } std::string & GetWarning() { return mWarning; } @@ -61,18 +82,138 @@ namespace clitk { template void UpdateWithInputImageType(); + template + void CheckTypes(std::string inType, std::string outType); + protected: + template void InitializeImageType(); std::string mOutputPixelTypeName; std::string mWarning; bool mWarningOccur; bool mDisplayWarning; - template void UpdateWithOutputType(); - + private: + template + class UpdateWithSelectiveOutputType + { + public: + static bool Run(ImageConvertGenericFilter& filter, std::string outputPixelType) + { + if (IsSameType(outputPixelType)) + UpdateWithOutputType(filter); + else if (IsSameType(outputPixelType)) + UpdateWithOutputType(filter); + else if (IsSameType(outputPixelType)) + UpdateWithOutputType(filter); + else if (IsSameType(outputPixelType)) + UpdateWithOutputType(filter); + else if (IsSameType(outputPixelType)) + UpdateWithOutputType(filter); + else if (IsSameType(outputPixelType)) + UpdateWithOutputType(filter); + else if (IsSameType(outputPixelType)) + UpdateWithOutputType(filter); + else + { + std::string list = CreateListOfTypes(); + std::cerr << "Error, I don't know the vector output type '" << outputPixelType + << "'. " << std::endl << "Known types are " << list << "." << std::endl; + return false; + } + + return true; + } + + private: + + template + static void UpdateWithOutputType(ImageConvertGenericFilter& filter) + { + // Read + typename InputImageType::Pointer input =filter.template GetInput(0); + + // Typedef + typedef typename InputImageType::PixelType PixelType; + + // Warning + filter.CheckTypes(filter.GetInputPixelTypeName(), filter.GetOutputPixelTypeName()); + + // Cast + typedef itk::Image OutputImageType; + typedef itk::CastImageFilter FilterType; + typename FilterType::Pointer cast_filter = FilterType::New(); + cast_filter->SetInput(input); + cast_filter->Update(); + + // Write + filter.SetNextOutput(cast_filter->GetOutput()); + } + }; + + template + class UpdateWithSelectiveOutputType + { + public: + static bool Run(ImageConvertGenericFilter& filter, std::string outputPixelType) + { + /* + // RP: future conversions? + if (IsSameType(outputPixelType)) + UpdateWithOutputVectorType(); + else if (IsSameType(outputPixelType)) + UpdateWithOutputVectorType(); + else if (IsSameType(outputPixelType)) + UpdateWithOutputVectorType(); + else if (IsSameType(outputPixelType)) + UpdateWithOutputVectorType(); + else if (IsSameType(outputPixelType)) + UpdateWithOutputVectorType(); + else + */ + if (IsSameType(outputPixelType)) + UpdateWithOutputVectorType(filter); + else if (IsSameType(outputPixelType)) + UpdateWithOutputVectorType(filter); + else + { + std::string list = CreateListOfTypes(); + std::cerr << "Error, I don't know the vector output type '" << outputPixelType + << "'. " << std::endl << "Known types are " << list << "." << std::endl; + return false; + } + + return true; + } + + private: + + template + static void UpdateWithOutputVectorType(ImageConvertGenericFilter& filter) + { + // Read + typename InputImageType::Pointer input =filter.template GetInput(0); + + // Typedef + typedef typename InputImageType::PixelType::ValueType PixelType; + + // Warning + filter.CheckTypes(filter.GetInputPixelTypeName(), filter.GetOutputPixelTypeName()); + + // Cast + typedef itk::Image, InputImageType::ImageDimension> OutputImageType; + typedef itk::VectorCastImageFilter FilterType; + typename FilterType::Pointer cast_filter = FilterType::New(); + cast_filter->SetInput(input); + cast_filter->Update(); + + // Write + filter.SetNextOutput(cast_filter->GetOutput()); + } + }; }; // end class ImageConvertGenericFilter - //#include "clitkImageConvertGenericFilter.txx" +//#include "clitkImageConvertGenericFilter.txx" } // end namespace diff --git a/vv/vvSlicer.cxx b/vv/vvSlicer.cxx index 5f86337..2224a9a 100644 --- a/vv/vvSlicer.cxx +++ b/vv/vvSlicer.cxx @@ -1168,33 +1168,38 @@ void vvSlicer::SetOverlayColorLevel(double level) //---------------------------------------------------------------------------- // Returns the min an the max value in a 41x41 region around the mouse pointer -void vvSlicer::GetExtremasAroundMousePointer(double & min, double & max, vtkImageData *image) +void vvSlicer::GetExtremasAroundMousePointer(double & min, double & max, vtkImageData *image, vtkTransform *transform) { //Get mouse pointer position in view coordinates - double fLocalExtents[6]; + double corner1[3]; + double corner2[3]; for(int i=0; i<3; i++) { - fLocalExtents[i*2 ] = mCurrent[i]; - fLocalExtents[i*2+1] = mCurrent[i]; + corner1[i] = mCurrent[i]; + corner2[i] = mCurrent[i]; } - this->Renderer->WorldToView(fLocalExtents[0], fLocalExtents[2], fLocalExtents[4]); - this->Renderer->WorldToView(fLocalExtents[1], fLocalExtents[3], fLocalExtents[5]); - for(int i=0; i<3; i++) { - if (i!=SliceOrientation) { //SR: assumes that SliceOrientation is valid in ViewCoordinates (???) - fLocalExtents[i*2 ] -= 0.2; - fLocalExtents[i*2+1] += 0.2; - } - } - this->Renderer->ViewToWorld(fLocalExtents[0], fLocalExtents[2], fLocalExtents[4]); - this->Renderer->ViewToWorld(fLocalExtents[1], fLocalExtents[3], fLocalExtents[5]); + this->Renderer->WorldToView(corner1[0], corner1[1], corner1[2]); + this->Renderer->WorldToView(corner2[0], corner2[1], corner2[2]); + + // In view coordinates, x is the slicer width and y is the slicer height are the in-plane axis + int w, h; + this->Renderer->GetTiledSize(&w, &h); + corner1[0] -= 0.2*h/(double)w; + corner2[0] += 0.2*h/(double)w; + corner1[1] -= 0.2; + corner2[1] += 0.2; + this->Renderer->ViewToWorld(corner1[0], corner1[1], corner1[2]); + this->Renderer->ViewToWorld(corner2[0], corner2[1], corner2[2]); //Convert to image pixel coordinates (rounded) + transform->TransformPoint(corner1, corner1); + transform->TransformPoint(corner2, corner2); int iLocalExtents[6]; for(int i=0; i<3; 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]; + corner1[i] = (corner1[i] - image->GetOrigin()[i])/image->GetSpacing()[i]; + corner2[i] = (corner2[i] - image->GetOrigin()[i])/image->GetSpacing()[i]; - iLocalExtents[i*2 ] = lrint(fLocalExtents[i*2 ]); - iLocalExtents[i*2+1] = lrint(fLocalExtents[i*2+1]); + iLocalExtents[i*2 ] = lrint(corner1[i]); + iLocalExtents[i*2+1] = lrint(corner2[i]); if(iLocalExtents[i*2 ]>iLocalExtents[i*2+1]) std::swap(iLocalExtents[i*2], iLocalExtents[i*2+1]); diff --git a/vv/vvSlicer.h b/vv/vvSlicer.h index b9cc334..c09001d 100644 --- a/vv/vvSlicer.h +++ b/vv/vvSlicer.h @@ -154,7 +154,7 @@ public: void SetCornerAnnotationVisibility(bool s); bool GetCornerAnnotationVisibility(); - void GetExtremasAroundMousePointer(double & min, double & max, vtkImageData *image); + void GetExtremasAroundMousePointer(double & min, double & max, vtkImageData *image, vtkTransform *transform); void UpdateLandmarks(); void ForceUpdateDisplayExtent(); diff --git a/vv/vvSlicerManager.cxx b/vv/vvSlicerManager.cxx index a787370..3f6f913 100644 --- a/vv/vvSlicerManager.cxx +++ b/vv/vvSlicerManager.cxx @@ -1117,13 +1117,17 @@ void vvSlicerManager::SetLocalColorWindowing(const int slicer, const bool bCtrlK double min, max; 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->mSlicers[slicer]->GetExtremasAroundMousePointer(min, max, + this->mSlicers[slicer]->GetFusion()->GetVTKImages()[t], + this->mSlicers[slicer]->GetFusion()->GetTransform()); 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]); + this->mSlicers[slicer]->GetExtremasAroundMousePointer(min, max, + this->mSlicers[slicer]->GetOverlay()->GetVTKImages()[t], + this->mSlicers[slicer]->GetOverlay()->GetTransform()); if(this->mSlicers[slicer]->GetLinkOverlayWindowLevel()){ this->SetColorWindow(max-min); this->SetColorLevel(0.5*(min+max)); @@ -1133,7 +1137,9 @@ void vvSlicerManager::SetLocalColorWindowing(const int slicer, const bool bCtrlK } } else { - this->mSlicers[slicer]->GetExtremasAroundMousePointer(min, max, this->mSlicers[slicer]->GetInput()); + this->mSlicers[slicer]->GetExtremasAroundMousePointer(min, max, + this->mSlicers[slicer]->GetImage()->GetVTKImages()[t], + this->mSlicers[slicer]->GetImage()->GetTransform()); this->SetColorWindow(max-min); this->SetColorLevel(0.5*(min+max)); this->SetPreset(6);