From: Simon Rit Date: Wed, 4 Sep 2013 12:31:41 +0000 (+0200) Subject: Merge branch 'master' of git.creatis.insa-lyon.fr:clitk X-Git-Tag: v1.4.0~164 X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=commitdiff_plain;h=97a3a9ed3f33ab0316bd4613c8aae404de40dad1;hp=ad9b42c9456495f663d30a07cacb33a9dd6c452f;p=clitk.git Merge branch 'master' of git.creatis.insa-lyon.fr:clitk --- diff --git a/cluster_tools/CMakeLists.txt b/cluster_tools/CMakeLists.txt new file mode 100644 index 0000000..ed8288b --- /dev/null +++ b/cluster_tools/CMakeLists.txt @@ -0,0 +1,15 @@ +#========================================================= +# Install scripts when running make install +SET(SCRIPTS + gate_job_cluster.job + gate_make_merge_release.sh + gate_make_release.sh + gate_power_merge.sh + gate_run_submit_cluster.sh + gate_upload_release.sh + mergeDosePerEnergyFile.sh + mergeStatFile.py + mergeStatFile.sh +) + +INSTALL (FILES ${SCRIPTS} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_EXECUTE WORLD_EXECUTE) diff --git a/cluster_tools/gate_make_merge_release.sh b/cluster_tools/gate_make_merge_release.sh new file mode 100755 index 0000000..e506728 --- /dev/null +++ b/cluster_tools/gate_make_merge_release.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +set -u +set -e + +function error { +echo "ERROR: $1" +echo "$(basename $0)" +exit 1 +} + +function get_deps { +targetbinary=${1} +targetdir=${2} +test -d ${targetdir} || error "${targetdir} isn't a directory" +ldd ${targetbinary} | while read library; do + libfile="$(echo ${library} | awk -F' ' '/=> \// {print $3}')" + test $libfile || continue # didn't macht regex + test -f "${targetdir}/$(basename ${libfile})" && continue # already exists + cp "${libfile}" "${targetdir}" + get_deps "${libfile}" "${targetdir}" +done +} + +function package_target { +targetname="${1}" +which "${targetname}" > /dev/null || error "cant locate ${targetname}" +targetbin="$(which ${targetname})" +echo "${targetname} executable is ${targetbin}" + +echo "Getting libraries" +targetdir="$(mktemp -d)" +get_deps "${targetbin}" "${targetdir}" + +echo "Removing unused libraries" +rm -f ${targetdir}/libdl.so* +rm -f ${targetdir}/libm.so* +rm -f ${targetdir}/libstdc++.so* +rm -f ${targetdir}/libgcc_s.so* +rm -f ${targetdir}/libpthread.so* +rm -f ${targetdir}/libc.so* + +echo "Copying binary" +cp "${targetbin}" . +for filename in $(find ${targetdir} -name '*.so*'); do cp ${filename} . ; done + +echo "Cleaning up" +rm -r "${targetdir}" +} + +filenames=("clitkImageArithm" "clitkMergeRootFiles" "clitkMergeAsciiDoseActor" "clitkImageUncertainty" "mergeStatFile.sh" "gate_power_merge.sh") + +for input in "${filenames[@]}"; do + package_target "${input}" || error "error while packaging ${input}" +done + +echo "Making release" +tar -czvf merge_release.tar.gz ** \ + || usage "can't create release zip" + + + diff --git a/cluster_tools/gate_power_merge.sh b/cluster_tools/gate_power_merge.sh index 4b5f184..e35a683 100755 --- a/cluster_tools/gate_power_merge.sh +++ b/cluster_tools/gate_power_merge.sh @@ -1,41 +1,41 @@ #!/usr/bin/env bash -set -u +set -u function error { -echo "ERROR: $1" -exit 1 + echo "ERROR: $1" + exit 1 } warning_count=0 function warning { -let "warning_count++" -echo "MERGE_WARNING: $1" + let "warning_count++" + echo "MERGE_WARNING: $1" } function start_bar { -count_max="${1:?"provide count max"}" + count_max="${1:?"provide count max"}" } function update_bar { -local count="${1:?"provide count"}" -local message="${2:?"provide message"}" -local percent=$(echo "100*${count}/${count_max}" | bc) -#printf "[%03d/%03d] %3d%% %-80.80s\r" ${count} ${count_max} ${percent} "${message}" -printf "[%03d/%03d] %3d%% %-80.80s\n" ${count} ${count_max} ${percent} "${message}" + local count="${1:?"provide count"}" + local message="${2:?"provide message"}" + local percent=$(echo "100*${count}/${count_max}" | bc) + #printf "[%03d/%03d] %3d%% %-80.80s\r" ${count} ${count_max} ${percent} "${message}" + printf "[%03d/%03d] %3d%% %-80.80s\n" ${count} ${count_max} ${percent} "${message}" } function end_bar { -unset count_max -#echo -ne '\n' + unset count_max + #echo -ne '\n' } function check_interfile { -local input_interfile="${1:?"provide input interfile"}" + local input_interfile="${1:?"provide input interfile"}" -grep -qs '!INTERFILE :=' "${input_interfile}" || return 1 + grep -qs '!INTERFILE :=' "${input_interfile}" || return 1 -local header_byte_size=$(awk -F' ' ' + local header_byte_size=$(awk -F' ' ' BEGIN { zsize = 0; } /matrix size/ && $3 == "[1]" { xsize = $5; } /matrix size/ && $3 == "[2]" { ysize = $5; } @@ -43,19 +43,19 @@ BEGIN { zsize = 0; } /number of bytes per pixel/ { byte_per_pixel = $7; } END { print xsize * ysize * zsize * byte_per_pixel; }' "${input_interfile}") -local raw_interfile="$(dirname "${input_interfile}")/$(awk -F' := ' '/name of data file/ { print $2; }' "${input_interfile}")" + local raw_interfile="$(dirname "${input_interfile}")/$(awk -F' := ' '/name of data file/ { print $2; }' "${input_interfile}")" -test -f "${raw_interfile}" || return 1 -test $(stat -c%s "${raw_interfile}") -eq ${header_byte_size} || return 1 + test -f "${raw_interfile}" || return 1 + test $(stat -c%s "${raw_interfile}") -eq ${header_byte_size} || return 1 } function write_mhd_header { -local input_interfile="${1:?"provide input interfile"}" -local output_mhd="$(dirname "${input_interfile}")/$(basename "${input_interfile}" ".hdr").mhd" + local input_interfile="${1:?"provide input interfile"}" + local output_mhd="$(dirname "${input_interfile}")/$(basename "${input_interfile}" ".hdr").mhd" -check_interfile "${input_interfile}" || error "${input_interfile} isn't an interfile image" + check_interfile "${input_interfile}" || error "${input_interfile} isn't an interfile image" -local header_start='ObjectType = Image + local header_start='ObjectType = Image NDims = 3 AcquisitionDate = none BinaryData = True @@ -67,21 +67,21 @@ CenterOfRotation = 0 0 0 DistanceUnits = mm AnatomicalOrientation = RIP' -echo "${header_start}" > "${output_mhd}" + echo "${header_start}" > "${output_mhd}" -awk -F' ' ' + awk -F' ' ' /scaling factor/ && $4 == "[1]" { xspacing = $6; } /scaling factor/ && $4 == "[2]" { yspacing = $6; } END { print "ElementSpacing = " xspacing " " yspacing " 1"; }' "${input_interfile}" >> "${output_mhd}" -awk -F' ' ' + awk -F' ' ' BEGIN { zsize = 0; } /matrix size/ && $3 == "[1]" { xsize = $5; } /matrix size/ && $3 == "[2]" { ysize = $5; } /number of projections/ { zsize += $5; } END { print "DimSize = " xsize " " ysize " " zsize; }' "${input_interfile}" >> "${output_mhd}" -awk -F' := ' ' + awk -F' := ' ' /number format/ { format = $2; } /number of bytes per pixel/ { byte_per_pixel = $2 } END { @@ -98,7 +98,7 @@ if (format == "float" && byte_per_pixel == 4) { print "ElementType = MET_DOUBLE" print "ElementType = MET_INT"; }' "${input_interfile}" >> "${output_mhd}" -awk -F' := ' ' + awk -F' := ' ' /name of data file/ { print "ElementDataFile = " $2; }' "${input_interfile}" >> "${output_mhd}" } @@ -106,200 +106,200 @@ rootMerger="clitkMergeRootFiles" test -x "./clitkMergeRootFiles" && rootMerger="./clitkMergeRootFiles" function merge_root { -local merged="$1" -shift -echo " ${indent}entering root merger" -echo " ${indent}merger is ${rootMerger}" -echo " ${indent}creating ${merged}" -#echo "######## $#" -#echo "######## $*" - -if test $# -eq 1 -then - echo " ${indent}just one partial file => just copy it" - cp "$1" "${merged}" - return -fi - -local count=0 -local arguments=" -o ${merged}" -while test $# -gt 0 -do - local partial="$1" + local merged="$1" shift - let count++ - local arguments=" -i ${partial} ${arguments}" -done -${rootMerger} ${arguments} > /dev/null || error "error while calling ${rootMerger}" -echo " ${indent}merged ${count} files" + echo " ${indent}entering root merger" + echo " ${indent}merger is ${rootMerger}" + echo " ${indent}creating ${merged}" + #echo "######## $#" + #echo "######## $*" + + if test $# -eq 1 + then + echo " ${indent}just one partial file => just copy it" + cp "$1" "${merged}" + return + fi + + local count=0 + local arguments=" -o ${merged}" + while test $# -gt 0 + do + local partial="$1" + shift + let count++ + local arguments=" -i ${partial} ${arguments}" + done + ${rootMerger} ${arguments} > /dev/null || error "error while calling ${rootMerger}" + echo " ${indent}merged ${count} files" } statMerger="mergeStatFile.py" test -x "./mergeStatFile.sh" && statMerger="./mergeStatFile.sh" function merge_stat { -local merged="$1" -shift -echo " ${indent}entering stat merger" -echo " ${indent}merger is ${statMerger}" -echo " ${indent}creating ${merged}" -local count=0 -start_bar $# -while test $# -gt 0 -do - local partial="$1" + local merged="$1" shift - let count++ - - if test ! -f "${merged}" - then - update_bar ${count} "copying first partial result ${partial}" - cp "${partial}" "${merged}" - continue - fi + echo " ${indent}entering stat merger" + echo " ${indent}merger is ${statMerger}" + echo " ${indent}creating ${merged}" + local count=0 + start_bar $# + while test $# -gt 0 + do + local partial="$1" + shift + let count++ + + if test ! -f "${merged}" + then + update_bar ${count} "copying first partial result ${partial}" + cp "${partial}" "${merged}" + continue + fi - update_bar ${count} "adding ${partial}" - ${statMerger} -i "${merged}" -j "${partial}" -o "${merged}" 2> /dev/null > /dev/null || warning "error while calling ${statMerger}" -done -end_bar -echo " ${indent}merged ${count} files" + update_bar ${count} "adding ${partial}" + ${statMerger} -i "${merged}" -j "${partial}" -o "${merged}" 2> /dev/null > /dev/null || warning "error while calling ${statMerger}" + done + end_bar + echo " ${indent}merged ${count} files" } doseMerger="mergeDosePerEnegryFile.sh" test -x "./mergeDosePerEnergyFile.sh" && doseMerger="./mergeDosePerEnergyFile.sh" function merge_dose { -local merged="$1" -shift -echo " ${indent}entering dose merger" -echo " ${indent}merger is ${doseMerger}" -echo " ${indent}creating ${merged}" -local count=0 -start_bar $# -while test $# -gt 0 -do - local partial="$1" + local merged="$1" shift - let count++ - - if test ! -f "${merged}" - then - update_bar ${count} "copying first partial result ${partial}" - cp "${partial}" "${merged}" - continue - fi + echo " ${indent}entering dose merger" + echo " ${indent}merger is ${doseMerger}" + echo " ${indent}creating ${merged}" + local count=0 + start_bar $# + while test $# -gt 0 + do + local partial="$1" + shift + let count++ + + if test ! -f "${merged}" + then + update_bar ${count} "copying first partial result ${partial}" + cp "${partial}" "${merged}" + continue + fi - update_bar ${count} "adding ${partial}" - ${doseMerger} -i "${merged}" -j "${partial}" -o "${merged}" 2> /dev/null > /dev/null || warning "error while calling ${doseMerger}" -done -end_bar -echo " ${indent}merged ${count} files" + update_bar ${count} "adding ${partial}" + ${doseMerger} -i "${merged}" -j "${partial}" -o "${merged}" 2> /dev/null > /dev/null || warning "error while calling ${doseMerger}" + done + end_bar + echo " ${indent}merged ${count} files" } txtImageMerger="clitkMergeAsciiDoseActor" test -f "./clitkMergeAsciiDoseActor" && txtImageMerger="./clitkMergeAsciiDoseActor" function merge_txt_image { -local merged="$1" -shift -echo " ${indent}entering text image merger" -echo " ${indent}merger is ${txtImageMerger}" -echo " ${indent}creating ${merged}" -local count=0 -start_bar $# -while test $# -gt 0 -do - local partial="$1" + local merged="$1" shift - let count++ - - if test ! -f "${merged}" - then - update_bar ${count} "copying first partial result ${partial}" - cp "${partial}" "${merged}" - continue - fi + echo " ${indent}entering text image merger" + echo " ${indent}merger is ${txtImageMerger}" + echo " ${indent}creating ${merged}" + local count=0 + start_bar $# + while test $# -gt 0 + do + local partial="$1" + shift + let count++ + + if test ! -f "${merged}" + then + update_bar ${count} "copying first partial result ${partial}" + cp "${partial}" "${merged}" + continue + fi - update_bar ${count} "adding ${partial}" - local header="$(cat "${merged}" | head -n 6)" - local tmp="$(mktemp)" - ${txtImageMerger} -i "${partial}" -j "${merged}" -o "${tmp}" 2> /dev/null > /dev/null || warning "error while calling ${txtImageMerger}" - echo "${header}" > "${merged}" - grep -v '## Merge' "${tmp}" >> "${merged}" - rm "${tmp}" -done -end_bar -echo " ${indent}merged ${count} files" + update_bar ${count} "adding ${partial}" + local header="$(cat "${merged}" | head -n 6)" + local tmp="$(mktemp)" + ${txtImageMerger} -i "${partial}" -j "${merged}" -o "${tmp}" 2> /dev/null > /dev/null || warning "error while calling ${txtImageMerger}" + echo "${header}" > "${merged}" + grep -v '## Merge' "${tmp}" >> "${merged}" + rm "${tmp}" + done + end_bar + echo " ${indent}merged ${count} files" } hdrImageMerger="clitkImageArithm" test -x "./clitkImageArithm" && hdrImageMerger="./clitkImageArithm" function merge_hdr_image { -local merged="$1" -local merged_bin="${merged%.*}.img" -shift -echo " ${indent}entering hdr image merger" -echo " ${indent}merger is ${hdrImageMerger}" -echo " ${indent}creating ${merged}" -local count=0 -start_bar $# -while test $# -gt 0 -do - local partial="$1" - local partial_bin="${partial%.*}.img" + local merged="$1" + local merged_bin="${merged%.*}.img" shift - let count++ - - if test ! -f "${merged}" - then - update_bar ${count} "copying first partial result ${partial}" - cp "${partial}" "${merged}" - cp "${partial_bin}" "${merged_bin}" - continue - fi + echo " ${indent}entering hdr image merger" + echo " ${indent}merger is ${hdrImageMerger}" + echo " ${indent}creating ${merged}" + local count=0 + start_bar $# + while test $# -gt 0 + do + local partial="$1" + local partial_bin="${partial%.*}.img" + shift + let count++ + + if test ! -f "${merged}" + then + update_bar ${count} "copying first partial result ${partial}" + cp "${partial}" "${merged}" + cp "${partial_bin}" "${merged_bin}" + continue + fi - update_bar ${count} "adding ${partial}" - ${hdrImageMerger} -t 0 -i "${partial}" -j "${merged}" -o "${merged}" 2> /dev/null > /dev/null || warning "error while calling ${hdrImageMerger}" -done -end_bar -echo " ${indent}merged ${count} files" + update_bar ${count} "adding ${partial}" + ${hdrImageMerger} -t 0 -i "${partial}" -j "${merged}" -o "${merged}" 2> /dev/null > /dev/null || warning "error while calling ${hdrImageMerger}" + done + end_bar + echo " ${indent}merged ${count} files" } mhdImageMerger="clitkImageArithm" test -x "./clitkImageArithm" && mhdImageMerger="./clitkImageArithm" function merge_mhd_image { -local merged="$1" -local merged_bin="${merged%.*}.raw" -shift -echo " ${indent}entering mhd image merger" -echo " ${indent}merger is ${mhdImageMerger}" -echo " ${indent}creating ${merged}" -local count=0 -start_bar $# -while test $# -gt 0 -do - local partial="$1" - local partial_bin="$(dirname "${partial}")/$(awk -F' = ' '/ElementDataFile/ { print $2; }' "${partial}")" + local merged="$1" + local merged_bin="${merged%.*}.raw" shift - let count++ - - if test ! -f "${merged}" - then - update_bar ${count} "copying first partial result ${partial}" - cp "${partial}" "${merged}" - cp "${partial_bin}" "${merged_bin%.*}.${partial_bin##*.}" - continue - fi + echo " ${indent}entering mhd image merger" + echo " ${indent}merger is ${mhdImageMerger}" + echo " ${indent}creating ${merged}" + local count=0 + start_bar $# + while test $# -gt 0 + do + local partial="$1" + local partial_bin="$(dirname "${partial}")/$(awk -F' = ' '/ElementDataFile/ { print $2; }' "${partial}")" + shift + let count++ + + if test ! -f "${merged}" + then + update_bar ${count} "copying first partial result ${partial}" + cp "${partial}" "${merged}" + cp "${partial_bin}" "${merged_bin%.*}.${partial_bin##*.}" + continue + fi - update_bar ${count} "adding ${partial}" - ${mhdImageMerger} -t 0 -i "${partial}" -j "${merged}" -o "${merged}" 2> /dev/null > /dev/null || warning "error while calling ${mhdImageMerger}" - mv "${merged_bin}" "${merged_bin%.*}.${partial_bin##*.}" - sed -i "s/$(basename "${merged_bin}")/$(basename "${merged_bin%.*}.${partial_bin##*.}")/" "${merged}" -done -end_bar -echo " ${indent}merged ${count} files" + update_bar ${count} "adding ${partial}" + ${mhdImageMerger} -t 0 -i "${partial}" -j "${merged}" -o "${merged}" 2> /dev/null > /dev/null || warning "error while calling ${mhdImageMerger}" + mv "${merged_bin}" "${merged_bin%.*}.${partial_bin##*.}" + sed -i "s/$(basename "${merged_bin}")/$(basename "${merged_bin%.*}.${partial_bin##*.}")/" "${merged}" + done + end_bar + echo " ${indent}merged ${count} files" } function merge_dispatcher { @@ -420,6 +420,69 @@ function merge_dispatcher { error "unknown file type" } +function merge_dispatcher_uncertainty { + local indent=" ** " + local outputfile="${1:?"provide output filename"}" + + local partialoutputfiles="$(find "${rundir}" -mindepth 2 -type f -name "${outputfile}")" + local nboutputfiles="$(echo "${partialoutputfiles}" | wc -l)" + if test ${nboutputdirs} -ne ${nboutputfiles} + then + warning "missing files" + return + fi + + local firstpartialoutputfile="$(echo "${partialoutputfiles}" | head -n 1)" + local firstpartialoutputextension="${firstpartialoutputfile##*.}" + + if [[ "${firstpartialoutputfile}" == *Uncertainty* ]] + then + if test "${firstpartialoutputextension}" == "mhd" + then + echo "${indent}Uncertainty file found: ${firstpartialoutputfile}" + ## search for sum + local mergedfile="${outputdir}/$(basename "${firstpartialoutputfile}")" + summed_merged_file=${mergedfile//-Uncertainty/} + if [ ! -f ${summed_merged_file} ]; + then + warning "${summed_merged_file} does not exist. Error, no uncertainty computed" + return; + fi + echo "${indent}${summed_merged_file} found" + ## search for Squared + squared_merged_file=${mergedfile//-Uncertainty/-Squared} + if [ ! -f ${squared_merged_file} ]; + then + warning "${squared_merged_file} does not exist. Error, no uncertainty computed" + return; + fi + echo "${indent}${squared_merged_file} found" + ## search for NumberOfEvent + totalEvents=0; + for outputfile in $(find "${rundir}" -regextype 'posix-extended' -type f -regex "${rundir}/output.*\.(hdr|mhd|root|txt)" | awk -F '/' '{ print $NF; }' | sort | uniq) + do + #echo $outputfile + if grep -q 'NumberOfEvent' "${outputdir}/${outputfile}" + then + totalEvents="$(grep "NumberOfEvents" "${outputdir}/${outputfile}" | cut -d' ' -f4)" + echo "${indent}Find the NumberOfEvent in $outputfile: ${totalEvents}" + fi + done + + if test ${totalEvents} -gt 0 + then + uncerImageMerger="clitkImageUncertainty" + test -x "./clitkImageUncertainty" && uncerImageMerger="./clitkImageUncertainty" + ${uncerImageMerger} -i ${summed_merged_file} -s ${squared_merged_file} -o ${mergedfile} -n ${totalEvents} + else + warning "${totalEvents} not positive. A at least one stat file (SimulationStatisticActor) must be provided. Error, no uncertainty computed" + return; + fi + fi + fi + +} + echo "!!!! this is $0 v0.3k !!!!" rundir="${1?"provide run dir"}" @@ -436,6 +499,7 @@ then fi outputdir="$(basename "${outputdir}")" echo "output dir is ${outputdir}" + test -d "${outputdir}" && rm -r "${outputdir}" mkdir "${outputdir}" @@ -444,10 +508,17 @@ do merge_dispatcher "${outputfile}" done +echo "" +echo "Merging done. Special case for statistical uncertainty" +for outputfile in $(find "${outputdir}" -regextype 'posix-extended' -type f -regex "${outputdir}/output.*\.(hdr|mhd|root|txt)" | awk -F '/' '{ print $NF; }' | sort | uniq) +do + merge_dispatcher_uncertainty "${outputfile}" +done + if [ -f "${rundir}/params.txt" ] then - echo "copying params file" - cp "${rundir}/params.txt" "${outputdir}/params.txt" + echo "copying params file" + cp "${rundir}/params.txt" "${outputdir}/params.txt" fi echo "these was ${warning_count} warning(s)" diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 95a1023..bef0f36 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -39,6 +39,7 @@ SET(clitkCommon_SRC clitkExceptionObject.cxx clitkFilterBase.cxx clitkMemoryUsage.cxx + clitkMatrix.cxx vvImage.cxx vvImageReader.cxx vvImageWriter.cxx diff --git a/common/clitkCommon.h b/common/clitkCommon.h index 8cd82fb..2f5b26f 100644 --- a/common/clitkCommon.h +++ b/common/clitkCommon.h @@ -43,6 +43,8 @@ # include #endif +#define VTK_EXCLUDE_STRSTREAM_HEADERS + //-------------------------------------------------------------------- namespace clitk { diff --git a/common/clitkElastix.h b/common/clitkElastix.h new file mode 100644 index 0000000..738181f --- /dev/null +++ b/common/clitkElastix.h @@ -0,0 +1,167 @@ +/*========================================================================= + 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 clitkElastix_h +#define clitkElastix_h + +#include +#include + +//-------------------------------------------------------------------- +namespace clitk { + +//------------------------------------------------------------------- +bool +GetElastixValueFromTag(std::ifstream & is, + std::string tag, + std::string & value) +{ + std::string line; + is.seekg (0, is.beg); + while(std::getline(is, line)) { + unsigned pos = line.find(tag); + if (pos & values) +{ + std::stringstream strstr(s); + std::istream_iterator it(strstr); + std::istream_iterator end; + std::vector results(it, end); + values.clear(); + values.resize(results.size()); + for(uint i=0; i +typename itk::Matrix +createMatrixFromElastixFile(std::vector & filename, bool verbose=true) { + if (Dimension != 3) { + FATAL("Only 3D yet" << std::endl); + } + typename itk::Matrix matrix; + + itk::Euler3DTransform::Pointer mat = itk::Euler3DTransform::New(); + itk::Euler3DTransform::Pointer previous; + for(uint j=0; j cor; + GetValuesFromValue(s, cor); + itk::Euler3DTransform::CenterType c; + for(uint i=0; i<3; i++) + c[i] = atof(cor[i].c_str()); + mat->SetCenter(c); + + // Get Transformparameters + GetElastixValueFromTag(is, "ComputeZYX ", s); // space is needed + mat->SetComputeZYX( s==std::string("true") ); + + // Get Transformparameters + GetElastixValueFromTag(is, "TransformParameters ", s); // space is needed + if (!b) { + FATAL("Error must read 'TransformParameters' in " << filename[j] << std::endl); + } + std::vector results; + GetValuesFromValue(s, results); + + // construct a stream from the string + itk::Euler3DTransform::ParametersType p; + p.SetSize(6); + for(uint i=0; i<3; i++) + p[i] = atof(results[i].c_str()); // Rotation + for(uint i=0; i<3; i++) + p[i+3] = atof(results[i+3].c_str()); // Translation + mat->SetParameters(p); + + if (verbose) { + std::cout << "Rotation (deg) : " << rad2deg(p[0]) << " " << rad2deg(p[1]) << " " << rad2deg(p[2]) << std::endl; + std::cout << "Center of rot (phy) : " << c[0] << " " << c[1] << " " << c[2] << std::endl; + std::cout << "Translation (phy) : " << p[3] << " " << p[4] << " " << p[5] << std::endl; + } + + // Compose with previous if needed + if (j!=0) { + mat->Compose(previous); + if (verbose) { + std::cout << "Composed rotation (deg) : " << rad2deg(mat->GetAngleX()) << " " << rad2deg(mat->GetAngleY()) << " " << rad2deg(mat->GetAngleZ()) << std::endl; + std::cout << "Composed center of rot (phy) : " << mat->GetCenter() << std::endl; + std::cout << "Compsoed translation (phy) : " << mat->GetTranslation() << std::endl; + } + } + // previous = mat->Clone(); // ITK4 + previous = itk::Euler3DTransform::New(); + previous->SetParameters(mat->GetParameters()); + previous->SetCenter(c); + previous->SetComputeZYX(mat->GetComputeZYX()); + } + + mat = previous; + for(uint i=0; i<3; i++) + for(uint j=0; j<3; j++) + matrix[i][j] = mat->GetMatrix()[i][j]; + // Offset is -Rc + t + c + matrix[0][3] = mat->GetOffset()[0]; + matrix[1][3] = mat->GetOffset()[1]; + matrix[2][3] = mat->GetOffset()[2]; + matrix[3][3] = 1; + + return matrix; +} +} +//------------------------------------------------------------------- + +#endif diff --git a/common/clitkMatrix.cxx b/common/clitkMatrix.cxx new file mode 100644 index 0000000..c911f55 --- /dev/null +++ b/common/clitkMatrix.cxx @@ -0,0 +1,71 @@ +/*========================================================================= + 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 +===========================================================================**/ + +#include "clitkMatrix.h" + +//-------------------------------------------------------------------- +namespace clitk { + +//------------------------------------------------------------------- +std::string +Get4x4MatrixDoubleAsString(vtkMatrix4x4 *matrix, + const int precision) +{ + std::ostringstream strmatrix; + + // Figure out the number of digits of the integer part of the largest absolute value + // for each column + unsigned width[4]; + for (unsigned int j = 0; j < 4; j++){ + double absmax = 0.; + for (unsigned int i = 0; i < 4; i++) + absmax = std::max(absmax, vnl_math_abs(matrix->GetElement(i, j))); + unsigned ndigits = (unsigned)std::max(0.,std::log10(absmax))+1; + width[j] = precision+ndigits+3; + } + + // Output with correct width, aligned to the right + for (unsigned int i = 0; i < 4; i++) { + for (unsigned int j = 0; j < 4; j++) { + strmatrix.setf(ios::fixed,ios::floatfield); + strmatrix.precision(precision); + strmatrix.fill(' '); + strmatrix.width(width[j]); + strmatrix << std::right << matrix->GetElement(i, j); + } + strmatrix << std::endl; + } + std::string result = strmatrix.str().c_str(); + return result; +} +//------------------------------------------------------------------- + +//------------------------------------------------------------------- +std::string +Get4x4MatrixDoubleAsString(itk::Matrix m, + const int precision) +{ + vtkSmartPointer matrix = vtkSmartPointer::New(); + for (unsigned int j = 0; j < 4; j++) + for (unsigned int i = 0; i < 4; i++) + matrix->SetElement(j,i,m[j][i]); + return Get4x4MatrixDoubleAsString(matrix, precision); +} +//------------------------------------------------------------------- +} +//------------------------------------------------------------------- diff --git a/common/clitkMatrix.h b/common/clitkMatrix.h new file mode 100644 index 0000000..25b0fa1 --- /dev/null +++ b/common/clitkMatrix.h @@ -0,0 +1,39 @@ +/*========================================================================= + 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 clitkMatrix_h +#define clitkMatrix_h + +#include +#define VTK_EXCLUDE_STRSTREAM_HEADERS +#include +#include + +//-------------------------------------------------------------------- +namespace clitk { +std::string +Get4x4MatrixDoubleAsString(vtkMatrix4x4 *matrix, + const int precision=3); + +std::string +Get4x4MatrixDoubleAsString(itk::Matrix m, + const int precision=3); +} +//------------------------------------------------------------------- + +#endif diff --git a/common/clitkTransformUtilities.h b/common/clitkTransformUtilities.h index d3644b1..562ed63 100644 --- a/common/clitkTransformUtilities.h +++ b/common/clitkTransformUtilities.h @@ -23,6 +23,7 @@ #include "itkPoint.h" #include "clitkImageCommon.h" #include "clitkCommon.h" +#define VTK_EXCLUDE_STRSTREAM_HEADERS #include #include diff --git a/common/vvImage.h b/common/vvImage.h index 7240be8..10ffc86 100644 --- a/common/vvImage.h +++ b/common/vvImage.h @@ -23,6 +23,7 @@ #include #include +#define VTK_EXCLUDE_STRSTREAM_HEADERS #include #include diff --git a/common/vvImageReader.cxx b/common/vvImageReader.cxx index ddc4ad3..23c78f1 100644 --- a/common/vvImageReader.cxx +++ b/common/vvImageReader.cxx @@ -22,6 +22,7 @@ #include "vvImageReader.h" #include "vvImageReader.txx" #include "clitkTransformUtilities.h" +#include "clitkElastix.h" //------------------------------------------------------------------------------ vvImageReader::vvImageReader() @@ -150,18 +151,20 @@ void vvImageReader::ReadMatImageTransform() { std::string filename(mInputFilenames[0]); std::string ext(itksys::SystemTools::GetFilenameLastExtension(filename)); + + // Try a ".mat" extension if (ext.length() > 0) { size_t pos = filename.rfind(ext); filename.replace(pos, ext.length(), ".mat"); } else filename += ".mat"; - std::ifstream f(filename.c_str()); + itk::Matrix itkMat; + bool itkMatRead = false; if(f.is_open()) { - f.close(); + itkMatRead = true; - itk::Matrix itkMat; itkMat.SetIdentity(); try { itkMat = clitk::ReadMatrix3D(filename); @@ -169,8 +172,29 @@ void vvImageReader::ReadMatImageTransform() catch (itk::ExceptionObject & err) { itkWarningMacro(<< "Found " << filename << " but this is not a 4x4 matrix so it is ignored."); + itkMatRead = false; } + } + f.close(); + + // Try a ".elx" extension + filename = mInputFilenames[0]; + if (ext.length() > 0) { + size_t pos = filename.rfind(ext); + filename.replace(pos, ext.length(), ".elx"); + } + else + filename += ".elx"; + f.open(filename.c_str()); + if(!itkMatRead && f.is_open()) { + itkMatRead = true; + std::vector l; + l.push_back(filename); + itkMat = clitk::createMatrixFromElastixFile<3>(l, true); + } + f.close(); + if(itkMatRead) { vtkSmartPointer matrix = vtkSmartPointer::New(); matrix->Identity(); for(int j=0; j<4; j++) @@ -208,12 +232,12 @@ void vvImageReader::ReadMatImageTransform() //for image sequences, apply the transform to each images of the sequence if (mImage->IsTimeSequence()) { - for (unsigned i = 1 ; iGetTransform().size() ; i++) - { - mImage->GetTransform()[i]->PreMultiply(); - mImage->GetTransform()[i]->Concatenate(matrix); - mImage->GetTransform()[i]->Update(); - } + for (unsigned i = 1 ; iGetTransform().size() ; i++) + { + mImage->GetTransform()[i]->PreMultiply(); + mImage->GetTransform()[i]->Concatenate(matrix); + mImage->GetTransform()[i]->Update(); + } } } diff --git a/itk/clitkLabelImageOverlapMeasureFilter.h b/itk/clitkLabelImageOverlapMeasureFilter.h index 17b7c21..cf0645f 100644 --- a/itk/clitkLabelImageOverlapMeasureFilter.h +++ b/itk/clitkLabelImageOverlapMeasureFilter.h @@ -1,7 +1,7 @@ /*========================================================================= Program: vv http://www.creatis.insa-lyon.fr/rio/vv - Authors belong to: + 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 @@ -23,24 +23,24 @@ #include "clitkFilterBase.h" #include "clitkCropLikeImageFilter.h" #include "clitkSegmentationUtils.h" -// #include "itkLabelOverlapMeasuresImageFilter.h" // itk #include #include +#include #include namespace clitk { - + //-------------------------------------------------------------------- /* Analyze the relative position of a Target (mask image) according to some Object, in a given Support. Indicate the main important - position of this Target according the Object. + position of this Target according the Object. */ //-------------------------------------------------------------------- - + template class LabelImageOverlapMeasureFilter: public virtual FilterBase, @@ -53,30 +53,30 @@ namespace clitk { typedef LabelImageOverlapMeasureFilter Self; 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(LabelImageOverlapMeasureFilter, ImageToImageFilter); /** Some convenient typedefs. */ typedef typename ImageType::ConstPointer ImageConstPointer; typedef typename ImageType::Pointer ImagePointer; - typedef typename ImageType::RegionType RegionType; + typedef typename ImageType::RegionType RegionType; typedef typename ImageType::PixelType PixelType; typedef typename ImageType::SpacingType SpacingType; typedef typename ImageType::SizeType SizeType; typedef typename ImageType::IndexType IndexType; typedef typename ImageType::PointType PointType; - + /** ImageDimension constants */ itkStaticConstMacro(ImageDimension, unsigned int, ImageType::ImageDimension); FILTERBASE_INIT; - + // Options itkGetConstMacro(BackgroundValue, PixelType); - itkSetMacro(BackgroundValue, PixelType); + //itkSetMacro(BackgroundValue, PixelType); itkGetConstMacro(Label1, PixelType); itkSetMacro(Label1, PixelType); @@ -84,18 +84,28 @@ namespace clitk { itkGetConstMacro(Label2, PixelType); itkSetMacro(Label2, PixelType); + itkSetMacro(VerboseFlag, bool); + itkGetConstMacro(VerboseFlag, bool); + itkBooleanMacro(VerboseFlag); + + itkSetMacro(LongFlag, bool); + itkGetConstMacro(LongFlag, bool); + itkBooleanMacro(LongFlag); + // I dont want to verify inputs information virtual void VerifyInputInformation() { } - + protected: LabelImageOverlapMeasureFilter(); virtual ~LabelImageOverlapMeasureFilter() {} - + PixelType m_BackgroundValue; PixelType m_Label1; PixelType m_Label2; ImagePointer m_Input1; ImagePointer m_Input2; + bool m_VerboseFlag; + bool m_LongFlag; virtual void GenerateOutputInformation(); virtual void GenerateInputRequestedRegion(); @@ -104,7 +114,7 @@ namespace clitk { private: LabelImageOverlapMeasureFilter(const Self&); //purposely not implemented void operator=(const Self&); //purposely not implemented - + }; // end class //-------------------------------------------------------------------- diff --git a/itk/clitkLabelImageOverlapMeasureFilter.txx b/itk/clitkLabelImageOverlapMeasureFilter.txx index 0375709..e62a1a9 100644 --- a/itk/clitkLabelImageOverlapMeasureFilter.txx +++ b/itk/clitkLabelImageOverlapMeasureFilter.txx @@ -1,7 +1,7 @@ /*========================================================================= Program: vv http://www.creatis.insa-lyon.fr/rio/vv - Authors belong to: + 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 @@ -26,17 +26,19 @@ LabelImageOverlapMeasureFilter(): this->SetNumberOfRequiredInputs(2); SetLabel1(1); SetLabel2(1); - SetBackgroundValue(0); + m_BackgroundValue = 0; + SetVerboseFlag(false); + SetLongFlag(false); } //-------------------------------------------------------------------- //-------------------------------------------------------------------- template -void +void clitk::LabelImageOverlapMeasureFilter:: -GenerateOutputInformation() -{ +GenerateOutputInformation() +{ // DD("GenerateOutputInformation"); //ImagePointer input = dynamic_cast(itk::ProcessObject::GetInput(0)); // ImagePointer outputImage = this->GetOutput(0); @@ -47,9 +49,9 @@ GenerateOutputInformation() //-------------------------------------------------------------------- template -void +void clitk::LabelImageOverlapMeasureFilter:: -GenerateInputRequestedRegion() +GenerateInputRequestedRegion() { // Call default itk::ImageToImageFilter::GenerateInputRequestedRegion(); @@ -63,12 +65,10 @@ GenerateInputRequestedRegion() //-------------------------------------------------------------------- template -void +void clitk::LabelImageOverlapMeasureFilter:: -GenerateData() +GenerateData() { - // DD("GenerateData"); - // Get input pointer m_Input1 = dynamic_cast(itk::ProcessObject::GetInput(0)); m_Input2 = dynamic_cast(itk::ProcessObject::GetInput(1)); @@ -86,60 +86,14 @@ GenerateData() // Resize like the union ImagePointer input1 = clitk::ResizeImageLike(m_Input1, bbo, GetBackgroundValue()); ImagePointer input2 = clitk::ResizeImageLike(m_Input2, bbo, GetBackgroundValue()); - //DD(input1->GetLargestPossibleRegion()); - //DD(input2->GetLargestPossibleRegion()); - - // Compute overlap image - ImagePointer image_union = clitk::Clone(input1); - ImagePointer image_intersection = clitk::Clone(input1); - clitk::Or(image_union, input2, GetBackgroundValue()); - clitk::And(image_intersection, input2, GetBackgroundValue()); - - ImagePointer image_1NotIn2 = clitk::Clone(input1); - clitk::AndNot(image_1NotIn2, input2, GetBackgroundValue()); - - ImagePointer image_2NotIn1 = clitk::Clone(input2); - clitk::AndNot(image_2NotIn1, input1, GetBackgroundValue()); - - //writeImage(image_union, "union.mha"); - //writeImage(image_intersection, "intersection.mha"); - //writeImage(image_1NotIn2, "image_1NotIn2.mha"); - //writeImage(image_2NotIn1, "image_2NotIn1.mha"); - - // Compute size - typedef itk::LabelStatisticsImageFilter StatFilterType; - typename StatFilterType::Pointer statFilter = StatFilterType::New(); - statFilter->SetInput(image_union); - statFilter->SetLabelInput(image_union); - statFilter->Update(); - int u = statFilter->GetCount(GetLabel1()); - - statFilter->SetInput(image_intersection); - statFilter->SetLabelInput(image_intersection); - statFilter->Update(); - int inter = statFilter->GetCount(GetLabel1()); - - statFilter->SetInput(m_Input1); - statFilter->SetLabelInput(m_Input1); - statFilter->Update(); - int in1 = statFilter->GetCount(GetLabel1()); - - statFilter->SetInput(m_Input2); - statFilter->SetLabelInput(m_Input2); - statFilter->Update(); - int in2 = statFilter->GetCount(GetLabel1()); - - statFilter->SetInput(image_1NotIn2); - statFilter->SetLabelInput(image_1NotIn2); - statFilter->Update(); - int l1notIn2 = statFilter->GetCount(GetLabel1()); - - statFilter->SetInput(image_2NotIn1); - statFilter->SetLabelInput(image_2NotIn1); - statFilter->Update(); - int l2notIn1 = statFilter->GetCount(GetLabel1()); - - double dice = 2.0*(double)inter/(double)(in1+in2); + /* + if (GetVerboseFlag()) { + std::cout << "Resize images to the union of bounding boxes: " + << input1->GetLargestPossibleRegion().GetSize() << std::endl; + } + */ + + /* int width = 6; std::cout << std::setw(width) << in1 << " " << std::setw(width) << in2 << " " @@ -148,6 +102,38 @@ GenerateData() << std::setw(width) << l1notIn2 << " " << std::setw(width) << l2notIn1 << " " << std::setw(width) << dice << " "; //std::endl; + */ + + // Compute overlap, dice + typedef itk::LabelOverlapMeasuresImageFilter FilterType; + typename FilterType::Pointer diceFilter = FilterType::New(); + diceFilter->SetSourceImage(input1); + diceFilter->SetTargetImage(input2); + diceFilter->Update(); + + // Display information + if (!GetLongFlag()) { + if (GetVerboseFlag()) { + std::cout << "Dice : "; + } + std::cout << diceFilter->GetDiceCoefficient() << std::endl; + } + else { // long options + if (GetVerboseFlag()) { + std::cout << "Dice Jaccard Source Target Inter Union SrComp TarComp" << std::endl; + } + typename FilterType::MapType m = diceFilter->GetLabelSetMeasures(); + int width = 6; + std::cout << std::setw(width) << diceFilter->GetDiceCoefficient() << " " + << std::setw(width) << diceFilter->GetJaccardCoefficient() << " " + << std::setw(width) << m[m_Label1].m_Source << " " + << std::setw(width) << m[m_Label2].m_Target << " " + << std::setw(width) << m[m_Label1].m_Intersection << " " + << std::setw(width) << m[m_Label1].m_Union << " " + << std::setw(width) << m[m_Label1].m_SourceComplement << " " + << std::setw(width) << m[m_Label2].m_TargetComplement << " " + << std::endl; + } + } //-------------------------------------------------------------------- - diff --git a/itk/clitkResampleImageWithOptionsFilter.txx b/itk/clitkResampleImageWithOptionsFilter.txx index a3f88be..ddaa8a0 100644 --- a/itk/clitkResampleImageWithOptionsFilter.txx +++ b/itk/clitkResampleImageWithOptionsFilter.txx @@ -222,12 +222,19 @@ GenerateData() std::cout << "LastDimIsTime = " << m_LastDimensionIsTime << std::endl; } + // Compute origin based on image corner + typename FilterType::OriginPointType origin = input->GetOrigin(); + for(unsigned int i=0; iGetSpacing()[i]; + origin[i] += 0.5 * m_OutputSpacing[i]; + } + // Instance of the transform object to be passed to the resample // filter. By default, identity transform is applied filter->SetTransform(m_Transform); filter->SetSize(m_OutputSize); filter->SetOutputSpacing(m_OutputSpacing); - filter->SetOutputOrigin(input->GetOrigin()); + filter->SetOutputOrigin(origin); filter->SetDefaultPixelValue(m_DefaultPixelValue); filter->SetNumberOfThreads(this->GetNumberOfThreads()); filter->SetOutputDirection(input->GetDirection()); // <-- NEEDED if we want to keep orientation (in case of PermutAxes for example) diff --git a/itk/itkLabelOverlapMeasuresImageFilter.h b/itk/itkLabelOverlapMeasuresImageFilter.h deleted file mode 100644 index 978fed3..0000000 --- a/itk/itkLabelOverlapMeasuresImageFilter.h +++ /dev/null @@ -1,212 +0,0 @@ -/*========================================================================= - - Program: Insight Segmentation & Registration Toolkit - Module: $RCSfile: itkLabelOverlapMeasuresImageFilter.h,v $ - Language: C++ - Date: $Date: $ - Version: $Revision: $ - - Copyright (c) Insight Software Consortium. All rights reserved. - See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the above copyright notices for more information. - -=========================================================================*/ -#ifndef __itkLabelOverlapMeasuresImageFilter_h -#define __itkLabelOverlapMeasuresImageFilter_h - -#include "itkImageToImageFilter.h" -#include "itkFastMutexLock.h" -#include "itkNumericTraits.h" - -//#include "itk_hash_map.h" -#include "itksys/hash_map.hxx" - -namespace itk { - -/** \class LabelOverlapMeasuresImageFilter - * \brief Computes overlap measures between the set same set of labels of - * pixels of two images. Background is assumed to be 0. - * - * \sa LabelOverlapMeasuresImageFilter - * - * \ingroup MultiThreaded - */ -template -class ITK_EXPORT LabelOverlapMeasuresImageFilter : - public ImageToImageFilter -{ -public: - /** Standard Self typedef */ - typedef LabelOverlapMeasuresImageFilter Self; - typedef ImageToImageFilter Superclass; - typedef SmartPointer Pointer; - typedef SmartPointer ConstPointer; - - /** Method for creation through the object factory. */ - itkNewMacro( Self ); - - /** Runtime information support. */ - itkTypeMacro( LabelOverlapMeasuresImageFilter, ImageToImageFilter ); - - virtual void VerifyInputInformation() { } - - - /** Image related typedefs. */ - typedef TLabelImage LabelImageType; - typedef typename TLabelImage::Pointer LabelImagePointer; - typedef typename TLabelImage::ConstPointer LabelImageConstPointer; - - typedef typename TLabelImage::RegionType RegionType; - typedef typename TLabelImage::SizeType SizeType; - typedef typename TLabelImage::IndexType IndexType; - - typedef typename TLabelImage::PixelType LabelType; - - /** Type to use form computations. */ - typedef typename NumericTraits::RealType RealType; - - /** \class LabelLabelOverlapMeasuress - * \brief Metrics stored per label */ - class LabelSetMeasures - { - public: - // default constructor - LabelSetMeasures() - { - m_Source = 0; - m_Target = 0; - m_Union = 0; - m_Intersection = 0; - m_SourceComplement = 0; - m_TargetComplement = 0; - } - - // added for completeness - LabelSetMeasures& operator=( const LabelSetMeasures& l ) - { - m_Source = l.m_Source; - m_Target = l.m_Target; - m_Union = l.m_Union; - m_Intersection = l.m_Intersection; - m_SourceComplement = l.m_SourceComplement; - m_TargetComplement = l.m_TargetComplement; - } - - unsigned long m_Source; - unsigned long m_Target; - unsigned long m_Union; - unsigned long m_Intersection; - unsigned long m_SourceComplement; - unsigned long m_TargetComplement; - }; - - /** Type of the map used to store data per label */ - typedef itksys::hash_map MapType; - typedef typename MapType::iterator MapIterator; - typedef typename MapType::const_iterator MapConstIterator; - - /** Image related typedefs. */ - itkStaticConstMacro( ImageDimension, unsigned int, - TLabelImage::ImageDimension ); - - /** Set the source image. */ - void SetSourceImage( const LabelImageType * image ) - { this->SetNthInput( 0, const_cast( image ) ); } - - /** Set the target image. */ - void SetTargetImage( const LabelImageType * image ) - { this->SetNthInput( 1, const_cast( image ) ); } - - /** Get the source image. */ - const LabelImageType * GetSourceImage( void ) - { return this->GetInput( 0 ); } - - /** Get the target image. */ - const LabelImageType * GetTargetImage( void ) - { return this->GetInput( 1 ); } - - /** Get the label set measures */ - MapType GetLabelSetMeasures() - { return this->m_LabelSetMeasures; } - - /** - * tric overlap measures - */ - /** measures over all labels */ - RealType GetTotalOverlap(); - RealType GetUnionOverlap(); - RealType GetMeanOverlap(); - RealType GetVolumeSimilarity(); - RealType GetFalseNegativeError(); - RealType GetFalsePositiveError(); - /** measures over individual labels */ - RealType GetTargetOverlap( LabelType ); - RealType GetUnionOverlap( LabelType ); - RealType GetMeanOverlap( LabelType ); - RealType GetVolumeSimilarity( LabelType ); - RealType GetFalseNegativeError( LabelType ); - RealType GetFalsePositiveError( LabelType ); - /** alternative names */ - RealType GetJaccardCoefficient() - { return this->GetUnionOverlap(); } - RealType GetJaccardCoefficient( LabelType label ) - { return this->GetUnionOverlap( label ); } - RealType GetDiceCoefficient() - { return this->GetMeanOverlap(); } - RealType GetDiceCoefficient( LabelType label ) - { return this->GetMeanOverlap( label ); } - - -#ifdef ITK_USE_CONCEPT_CHECKING - /** Begin concept checking */ - itkConceptMacro( Input1HasNumericTraitsCheck, - ( Concept::HasNumericTraits ) ); - /** End concept checking */ -#endif - -protected: - LabelOverlapMeasuresImageFilter(); - ~LabelOverlapMeasuresImageFilter(){}; - void PrintSelf( std::ostream& os, Indent indent ) const; - - /** - * Pass the input through unmodified. Do this by setting the output to the - * source this by setting the output to the source image in the - * AllocateOutputs() method. - */ - void AllocateOutputs(); - - void BeforeThreadedGenerateData(); - - void AfterThreadedGenerateData(); - - /** Multi-thread version GenerateData. */ - void ThreadedGenerateData( const RegionType&, int ); - - // Override since the filter needs all the data for the algorithm - void GenerateInputRequestedRegion(); - - // Override since the filter produces all of its output - void EnlargeOutputRequestedRegion( DataObject *data ); - -private: - LabelOverlapMeasuresImageFilter( const Self& ); //purposely not implemented - void operator=( const Self& ); //purposely not implemented - - std::vector m_LabelSetMeasuresPerThread; - MapType m_LabelSetMeasures; - - SimpleFastMutexLock m_Mutex; - -}; // end of class - -} // end namespace itk - -#ifndef ITK_MANUAL_INSTANTIATION -#include "itkLabelOverlapMeasuresImageFilter.txx" -#endif - -#endif diff --git a/itk/itkLabelOverlapMeasuresImageFilter.txx b/itk/itkLabelOverlapMeasuresImageFilter.txx deleted file mode 100644 index ced277b..0000000 --- a/itk/itkLabelOverlapMeasuresImageFilter.txx +++ /dev/null @@ -1,437 +0,0 @@ -/*========================================================================= - - Program: Insight Segmentation & Registration Toolkit - Module: $RCSfile: itkLabelOverlapMeasuresImageFilter.txx,v $ - Language: C++ - Date: $Date: $ - Version: $Revision: $ - - Copyright (c) Insight Software Consortium. All rights reserved. - See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the above copyright notices for more information. - -=========================================================================*/ -#ifndef _itkLabelOverlapMeasuresImageFilter_txx -#define _itkLabelOverlapMeasuresImageFilter_txx - -#include "itkLabelOverlapMeasuresImageFilter.h" - -#include "itkImageRegionConstIterator.h" -#include "itkProgressReporter.h" - -namespace itk { - -#if defined(__GNUC__) && (__GNUC__ <= 2) //NOTE: This class needs a mutex for gnu 2.95 -/** Used for mutex locking */ -#define LOCK_HASHMAP this->m_Mutex.Lock() -#define UNLOCK_HASHMAP this->m_Mutex.Unlock() -#else -#define LOCK_HASHMAP -#define UNLOCK_HASHMAP -#endif - -template -LabelOverlapMeasuresImageFilter -::LabelOverlapMeasuresImageFilter() -{ - // this filter requires two input images - this->SetNumberOfRequiredInputs( 2 ); -} - -template -void -LabelOverlapMeasuresImageFilter -::GenerateInputRequestedRegion() -{ - Superclass::GenerateInputRequestedRegion(); - if( this->GetSourceImage() ) - { - LabelImagePointer source = const_cast - ( this->GetSourceImage() ); - source->SetRequestedRegionToLargestPossibleRegion(); - } - if( this->GetTargetImage() ) - { - LabelImagePointer target = const_cast - ( this->GetTargetImage() ); - target->SetRequestedRegionToLargestPossibleRegion(); - } -} - -template -void -LabelOverlapMeasuresImageFilter -::EnlargeOutputRequestedRegion( DataObject *data ) -{ - Superclass::EnlargeOutputRequestedRegion( data ); - data->SetRequestedRegionToLargestPossibleRegion(); -} - - -template -void -LabelOverlapMeasuresImageFilter -::AllocateOutputs() -{ - // Pass the source through as the output - LabelImagePointer image = - const_cast( this->GetSourceImage() ); - this->SetNthOutput( 0, image ); - - // Nothing that needs to be allocated for the remaining outputs -} - -template -void -LabelOverlapMeasuresImageFilter -::BeforeThreadedGenerateData() -{ - int numberOfThreads = this->GetNumberOfThreads(); - - // Resize the thread temporaries - this->m_LabelSetMeasuresPerThread.resize( numberOfThreads ); - - // Initialize the temporaries - for( int n = 0; n < numberOfThreads; n++ ) - { - this->m_LabelSetMeasuresPerThread[n].clear(); - } - - // Initialize the final map - this->m_LabelSetMeasures.clear(); -} - -template -void -LabelOverlapMeasuresImageFilter -::AfterThreadedGenerateData() -{ - // Run through the map for each thread and accumulate the set measures. - for( int n = 0; n < this->GetNumberOfThreads(); n++ ) - { - // iterate over the map for this thread - for( MapConstIterator threadIt = this->m_LabelSetMeasuresPerThread[n].begin(); - threadIt != this->m_LabelSetMeasuresPerThread[n].end(); - ++threadIt ) - { - // does this label exist in the cumulative stucture yet? - MapIterator mapIt = this->m_LabelSetMeasures.find( ( *threadIt ).first ); - if( mapIt == this->m_LabelSetMeasures.end() ) - { - // create a new entry - typedef typename MapType::value_type MapValueType; - mapIt = this->m_LabelSetMeasures.insert( MapValueType( - (*threadIt).first, LabelSetMeasures() ) ).first; - } - - // accumulate the information from this thread - (*mapIt).second.m_Source += (*threadIt).second.m_Source; - (*mapIt).second.m_Target += (*threadIt).second.m_Target; - (*mapIt).second.m_Union += (*threadIt).second.m_Union; - (*mapIt).second.m_Intersection += - (*threadIt).second.m_Intersection; - (*mapIt).second.m_SourceComplement += - (*threadIt).second.m_SourceComplement; - (*mapIt).second.m_TargetComplement += - (*threadIt).second.m_TargetComplement; - } // end of thread map iterator loop - } // end of thread loop -} - -template -void -LabelOverlapMeasuresImageFilter -::ThreadedGenerateData( const RegionType& outputRegionForThread, - int threadId ) -{ - ImageRegionConstIterator ItS( this->GetSourceImage(), - outputRegionForThread ); - ImageRegionConstIterator ItT( this->GetTargetImage(), - outputRegionForThread ); - - // support progress methods/callbacks - ProgressReporter progress( this, threadId, - 2*outputRegionForThread.GetNumberOfPixels() ); - - for( ItS.GoToBegin(), ItT.GoToBegin(); !ItS.IsAtEnd(); ++ItS, ++ItT ) - { - LabelType sourceLabel = ItS.Get(); - LabelType targetLabel = ItT.Get(); - - // is the label already in this thread? - MapIterator mapItS = - this->m_LabelSetMeasuresPerThread[threadId].find( sourceLabel ); - MapIterator mapItT = - this->m_LabelSetMeasuresPerThread[threadId].find( targetLabel ); - - if( mapItS == this->m_LabelSetMeasuresPerThread[threadId].end() ) - { - // create a new label set measures object - typedef typename MapType::value_type MapValueType; - LOCK_HASHMAP; - mapItS = this->m_LabelSetMeasuresPerThread[threadId].insert( - MapValueType( sourceLabel, LabelSetMeasures() ) ).first; - UNLOCK_HASHMAP; - } - - if( mapItT == this->m_LabelSetMeasuresPerThread[threadId].end() ) - { - // create a new label set measures object - typedef typename MapType::value_type MapValueType; - LOCK_HASHMAP; - mapItT = this->m_LabelSetMeasuresPerThread[threadId].insert( - MapValueType( targetLabel, LabelSetMeasures() ) ).first; - UNLOCK_HASHMAP; - } - - (*mapItS).second.m_Source++; - (*mapItT).second.m_Target++; - - if( sourceLabel == targetLabel ) - { - (*mapItS).second.m_Intersection++; - (*mapItS).second.m_Union++; - } - else - { - (*mapItS).second.m_Union++; - (*mapItT).second.m_Union++; - - (*mapItS).second.m_SourceComplement++; - (*mapItT).second.m_TargetComplement++; - } - - progress.CompletedPixel(); - } -} - -/** - * measures - */ -template -typename LabelOverlapMeasuresImageFilter::RealType -LabelOverlapMeasuresImageFilter -::GetTotalOverlap() -{ - RealType numerator = 0.0; - RealType denominator = 0.0; - for( MapIterator mapIt = this->m_LabelSetMeasures.begin(); - mapIt != this->m_LabelSetMeasures.end(); ++mapIt ) - { - // Do not include the background in the final value. - if( (*mapIt).first == NumericTraits::Zero ) - { - continue; - } - numerator += static_cast( (*mapIt).second.m_Intersection ); - denominator += static_cast( (*mapIt).second.m_Target ); - } - return ( numerator / denominator ); -} - -template -typename LabelOverlapMeasuresImageFilter::RealType -LabelOverlapMeasuresImageFilter -::GetTargetOverlap( LabelType label ) -{ - MapIterator mapIt = this->m_LabelSetMeasures.find( label ); - if( mapIt == this->m_LabelSetMeasures.end() ) - { - itkWarningMacro( "Label " << label << " not found." ); - return 0.0; - } - RealType value = - static_cast( (*mapIt).second.m_Intersection ) / - static_cast( (*mapIt).second.m_Target ); - return value; -} - -template -typename LabelOverlapMeasuresImageFilter::RealType -LabelOverlapMeasuresImageFilter -::GetUnionOverlap() -{ - RealType numerator = 0.0; - RealType denominator = 0.0; - for( MapIterator mapIt = this->m_LabelSetMeasures.begin(); - mapIt != this->m_LabelSetMeasures.end(); ++mapIt ) - { - // Do not include the background in the final value. - if( (*mapIt).first == NumericTraits::Zero ) - { - continue; - } - numerator += static_cast( (*mapIt).second.m_Intersection ); - denominator += static_cast( (*mapIt).second.m_Union ); - } - return ( numerator / denominator ); -} - -template -typename LabelOverlapMeasuresImageFilter::RealType -LabelOverlapMeasuresImageFilter -::GetUnionOverlap( LabelType label ) -{ - MapIterator mapIt = this->m_LabelSetMeasures.find( label ); - if( mapIt == this->m_LabelSetMeasures.end() ) - { - itkWarningMacro( "Label " << label << " not found." ); - return 0.0; - } - RealType value = - static_cast( (*mapIt).second.m_Intersection ) / - static_cast( (*mapIt).second.m_Union ); - return value; -} - -template -typename LabelOverlapMeasuresImageFilter::RealType -LabelOverlapMeasuresImageFilter -::GetMeanOverlap() -{ - RealType uo = this->GetUnionOverlap(); - return ( 2.0 * uo / ( 1.0 + uo ) ); -} - -template -typename LabelOverlapMeasuresImageFilter::RealType -LabelOverlapMeasuresImageFilter -::GetMeanOverlap( LabelType label ) -{ - RealType uo = this->GetUnionOverlap( label ); - return ( 2.0 * uo / ( 1.0 + uo ) ); -} - -template -typename LabelOverlapMeasuresImageFilter::RealType -LabelOverlapMeasuresImageFilter -::GetVolumeSimilarity() -{ - RealType numerator = 0.0; - RealType denominator = 0.0; - for( MapIterator mapIt = this->m_LabelSetMeasures.begin(); - mapIt != this->m_LabelSetMeasures.end(); ++mapIt ) - { - // Do not include the background in the final value. - if( (*mapIt).first == NumericTraits::Zero ) - { - continue; - } - numerator += ( ( static_cast( (*mapIt).second.m_Source ) - - static_cast( (*mapIt).second.m_Target ) ) ); - denominator += ( ( static_cast( (*mapIt).second.m_Source ) + - static_cast( (*mapIt).second.m_Target ) ) ); - } - return ( 2.0 * numerator / denominator ); -} - -template -typename LabelOverlapMeasuresImageFilter::RealType -LabelOverlapMeasuresImageFilter -::GetVolumeSimilarity( LabelType label ) -{ - MapIterator mapIt = this->m_LabelSetMeasures.find( label ); - if( mapIt == this->m_LabelSetMeasures.end() ) - { - itkWarningMacro( "Label " << label << " not found." ); - return 0.0; - } - RealType value = 2.0 * - ( static_cast( (*mapIt).second.m_Source ) - - static_cast( (*mapIt).second.m_Target ) ) / - ( static_cast( (*mapIt).second.m_Source ) + - static_cast( (*mapIt).second.m_Target ) ); - return value; -} - -template -typename LabelOverlapMeasuresImageFilter::RealType -LabelOverlapMeasuresImageFilter -::GetFalseNegativeError() -{ - RealType numerator = 0.0; - RealType denominator = 0.0; - for( MapIterator mapIt = this->m_LabelSetMeasures.begin(); - mapIt != this->m_LabelSetMeasures.end(); ++mapIt ) - { - // Do not include the background in the final value. - if( (*mapIt).first == NumericTraits::Zero ) - { - continue; - } - numerator += static_cast( (*mapIt).second.m_TargetComplement ); - denominator += static_cast( (*mapIt).second.m_Target ); - } - return ( numerator / denominator ); -} - -template -typename LabelOverlapMeasuresImageFilter::RealType -LabelOverlapMeasuresImageFilter -::GetFalseNegativeError( LabelType label ) -{ - MapIterator mapIt = this->m_LabelSetMeasures.find( label ); - if( mapIt == this->m_LabelSetMeasures.end() ) - { - itkWarningMacro( "Label " << label << " not found." ); - return 0.0; - } - RealType value = - static_cast( (*mapIt).second.m_TargetComplement ) / - static_cast( (*mapIt).second.m_Target ); - return value; -} - -template -typename LabelOverlapMeasuresImageFilter::RealType -LabelOverlapMeasuresImageFilter -::GetFalsePositiveError() -{ - RealType numerator = 0.0; - RealType denominator = 0.0; - for( MapIterator mapIt = this->m_LabelSetMeasures.begin(); - mapIt != this->m_LabelSetMeasures.end(); ++mapIt ) - { - // Do not include the background in the final value. - if( (*mapIt).first == NumericTraits::Zero ) - { - continue; - } - numerator += static_cast( (*mapIt).second.m_SourceComplement ); - denominator += static_cast( (*mapIt).second.m_Source ); - } - return ( numerator / denominator ); -} - -template -typename LabelOverlapMeasuresImageFilter::RealType -LabelOverlapMeasuresImageFilter -::GetFalsePositiveError( LabelType label ) -{ - MapIterator mapIt = this->m_LabelSetMeasures.find( label ); - if( mapIt == this->m_LabelSetMeasures.end() ) - { - itkWarningMacro( "Label " << label << " not found." ); - return 0.0; - } - RealType value = - static_cast( (*mapIt).second.m_SourceComplement ) / - static_cast( (*mapIt).second.m_Source ); - return value; -} - -template -void -LabelOverlapMeasuresImageFilter -::PrintSelf( std::ostream& os, Indent indent ) const -{ - Superclass::PrintSelf( os, indent ); - -} - - -}// end namespace itk -#endif diff --git a/superbuild/CMakeLists.txt b/superbuild/CMakeLists.txt index df23773..b0710d7 100644 --- a/superbuild/CMakeLists.txt +++ b/superbuild/CMakeLists.txt @@ -103,13 +103,36 @@ ExternalProject_Add( SET(VTK_DIR ${build_prefix}/VTK) #========================================================= +#========================================================= +# GDCM + ExternalProject_Add( + GDCM + SOURCE_DIR ${source_prefix}/gdcm + GIT_REPOSITORY git://git.code.sf.net/p/gdcm/gdcm + GIT_TAG v2.2.4 + INSTALL_COMMAND "" + CMAKE_ARGS + -DCMAKE_C_FLAGS_DEBUG:STRING=${CMAKE_C_FLAGS_DEBUG} + -DCMAKE_C_FLAGS_MINSIZEREL:STRING=${CMAKE_C_FLAGS_MINSIZEREL} + -DCMAKE_C_FLAGS_RELEASE:STRING=${CMAKE_C_FLAGS_RELEASE} + -DCMAKE_C_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_C_FLAGS_RELWITHDEBINFO} + -DCMAKE_CXX_FLAGS_DEBUG:STRING=${CMAKE_CXX_FLAGS_DEBUG} + -DCMAKE_CXX_FLAGS_MINSIZEREL:STRING=${CMAKE_CXX_FLAGS_MINSIZEREL} + -DCMAKE_CXX_FLAGS_RELEASE:STRING=${CMAKE_CXX_FLAGS_RELEASE} + -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_CXX_FLAGS_RELWITHDEBINFO} + -DCMAKE_INSTALL_PREFIX:PATH=${INSTALL_PREFIX} + -DCMAKE_BUILD_TYPE:STRING=${build_type} +) +SET(GDCM_DIR ${build_prefix}/GDCM) +#========================================================= + #========================================================= # ITK ExternalProject_Add( ITK SOURCE_DIR ${source_prefix}/itk GIT_REPOSITORY git://itk.org/ITK.git - GIT_TAG v4.2.0 + GIT_TAG v4.4.0 INSTALL_COMMAND "" CMAKE_ARGS -DCMAKE_C_FLAGS_DEBUG:STRING=${CMAKE_C_FLAGS_DEBUG} @@ -148,12 +171,14 @@ endif(MSVC) ExternalProject_Add( VV - DEPENDS QT VTK ITK + DEPENDS QT VTK ITK GDCM SOURCE_DIR ${source_prefix}/vv GIT_REPOSITORY git://git.creatis.insa-lyon.fr/clitk - INSTALL_COMMAND ${MAKE_COMMAND} package + INSTALL_DIR ${install_prefix} + INSTALL_COMMAND make install CMAKE_ARGS -DQT_QMAKE_EXECUTABLE:FILEPATH=${qmake_executable} + -DGDCM_DIR:PATH=${GDCM_DIR} -DITK_DIR:PATH=${ITK_DIR} -DVTK_DIR:PATH=${VTK_DIR} -DCMAKE_C_FLAGS_DEBUG:STRING=${CMAKE_C_FLAGS_DEBUG} diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 77f12f9..6d70fc3 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -24,7 +24,13 @@ ADD_LIBRARY(clitkMIPLib clitkMIPGenericFilter.cxx ${clitkMIP_GGO_C}) WRAP_GGO(clitkMedianImageFilter_GGO_C clitkMedianImageFilter.ggo) ADD_LIBRARY(clitkMedianImageFilterLib clitkMedianImageGenericFilter.cxx ${clitkMedianImageFilter_GGO_C}) +#========================================================= IF (CLITK_BUILD_TOOLS) + + #========================================================= + # install scripts + ADD_SUBDIRECTORY(${CLITK_SOURCE_DIR}/cluster_tools ${PROJECT_BINARY_DIR}/cluster_tools) + WRAP_GGO(clitkDicomInfo_GGO_C clitkDicomInfo.ggo) ADD_EXECUTABLE(clitkDicomInfo clitkDicomInfo.cxx ${clitkDicomInfo_GGO_C}) TARGET_LINK_LIBRARIES(clitkDicomInfo clitkCommon) @@ -89,7 +95,7 @@ IF (CLITK_BUILD_TOOLS) WRAP_GGO(clitkMedianTemporalDimension_GGO_C clitkMedianTemporalDimension.ggo) ADD_EXECUTABLE(clitkMedianTemporalDimension clitkMedianTemporalDimension.cxx - ${clitkMedianTemporalDimension_GGO_C}) + ${clitkMedianTemporalDimension_GGO_C}) TARGET_LINK_LIBRARIES(clitkMedianTemporalDimension clitkCommon ) SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkMedianTemporalDimension) @@ -113,13 +119,22 @@ IF (CLITK_BUILD_TOOLS) TARGET_LINK_LIBRARIES(clitkElastixTransformToMatrix clitkCommon ) SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkElastixTransformToMatrix) + WRAP_GGO(clitkMatrixToElastixTransform_GGO_C clitkMatrixToElastixTransform.ggo) + ADD_EXECUTABLE(clitkMatrixToElastixTransform clitkMatrixToElastixTransform.cxx ${clitkMatrixToElastixTransform_GGO_C}) + TARGET_LINK_LIBRARIES(clitkMatrixToElastixTransform clitkCommon ) + SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkMatrixToElastixTransform) + + WRAP_GGO(clitkMatrixInverse_GGO_C clitkMatrixInverse.ggo) + ADD_EXECUTABLE(clitkMatrixInverse clitkMatrixInverse.cxx ${clitkMatrixInverse_GGO_C}) + TARGET_LINK_LIBRARIES(clitkMatrixInverse clitkCommon ) + SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkMatrixInverse) WRAP_GGO(clitkSetBackground_GGO_C clitkSetBackground.ggo) ADD_EXECUTABLE(clitkSetBackground clitkSetBackground.cxx clitkSetBackgroundGenericFilter.cxx ${clitkSetBackground_GGO_C}) TARGET_LINK_LIBRARIES(clitkSetBackground clitkCommon) SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkSetBackground) - WRAP_GGO(clitkGammaIndex_GGO_C clitkGammaIndex.ggo) + WRAP_GGO(clitkGammaIndex_GGO_C clitkGammaIndex.ggo) ADD_EXECUTABLE(clitkGammaIndex clitkGammaIndex.cxx ${clitkGammaIndex_GGO_C}) TARGET_LINK_LIBRARIES(clitkGammaIndex clitkCommon) SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkGammaIndex) @@ -134,12 +149,12 @@ IF (CLITK_BUILD_TOOLS) WRAP_GGO(clitkUnsharpMask_GGO_C clitkUnsharpMask.ggo) ADD_EXECUTABLE(clitkUnsharpMask clitkUnsharpMask.cxx ${clitkUnsharpMask_GGO_C}) - TARGET_LINK_LIBRARIES(clitkUnsharpMask clitkCommon ) + TARGET_LINK_LIBRARIES(clitkUnsharpMask clitkCommon ) SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkUnsharpMask) WRAP_GGO(clitkFooImage_GGO_C clitkFooImage.ggo) ADD_EXECUTABLE(clitkFooImage clitkFooImage.cxx ${clitkFooImage_GGO_C}) - TARGET_LINK_LIBRARIES(clitkFooImage clitkCommon ) + TARGET_LINK_LIBRARIES(clitkFooImage clitkCommon ) SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkFooImage) #WRAP_GGO(clitkMedianImageFilter_GGO_C clitkMedianImageFilter.ggo) @@ -195,7 +210,7 @@ IF (CLITK_BUILD_TOOLS) # ADD_EXECUTABLE(clitkExtractSlice clitkExtractSlice.cxx clitkExtractSliceGenericFilter.cxx ${clitkExtractSlice_GGO_C}) # TARGET_LINK_LIBRARIES(clitkExtractSlice clitkCommon) #SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkExtractSlice) - + WRAP_GGO(clitkFlipImage_GGO_C clitkFlipImage.ggo) ADD_EXECUTABLE(clitkFlipImage clitkFlipImage.cxx clitkFlipImageGenericFilter.cxx ${clitkFlipImage_GGO_C}) TARGET_LINK_LIBRARIES(clitkFlipImage clitkCommon) @@ -240,6 +255,11 @@ IF (CLITK_BUILD_TOOLS) TARGET_LINK_LIBRARIES(clitkTransformLandmarks clitkCommon) SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkTransformLandmarks) + WRAP_GGO(clitkDice_GGO_C clitkDice.ggo) + ADD_EXECUTABLE(clitkDice clitkDice.cxx ${clitkDice_GGO_C}) + TARGET_LINK_LIBRARIES(clitkDice clitkSegmentationGgoLib clitkCommon ${ITK_LIBRARIES} ) + SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkDice) + WRAP_GGO(clitkMaskLandmarks_GGO_C clitkMaskLandmarks.ggo) ADD_EXECUTABLE(clitkMaskLandmarks clitkMaskLandmarks.cxx ${clitkMaskLandmarks_GGO_C}) TARGET_LINK_LIBRARIES(clitkMaskLandmarks clitkCommon) @@ -249,7 +269,7 @@ IF (CLITK_BUILD_TOOLS) ADD_EXECUTABLE(clitkJacobianImage clitkJacobianImage.cxx clitkJacobianImageGenericFilter.cxx ${clitkJacobianImage_GGO_C}) TARGET_LINK_LIBRARIES(clitkJacobianImage clitkCommon) SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkJacobianImage) - + WRAP_GGO(clitkPadImage_GGO_C clitkPadImage.ggo) ADD_EXECUTABLE(clitkPadImage clitkPadImage.cxx clitkPadImageGenericFilter.cxx ${clitkPadImage_GGO_C}) TARGET_LINK_LIBRARIES(clitkPadImage clitkCommon) @@ -262,18 +282,49 @@ IF (CLITK_BUILD_TOOLS) WRAP_GGO(clitkAnisotropicDiffusion_GGO_C clitkAnisotropicDiffusion.ggo) ADD_EXECUTABLE(clitkAnisotropicDiffusion clitkAnisotropicDiffusion.cxx - clitkAnisotropicDiffusionGenericFilter.cxx - ${clitkAnisotropicDiffusion_GGO_C}) + clitkAnisotropicDiffusionGenericFilter.cxx + ${clitkAnisotropicDiffusion_GGO_C}) TARGET_LINK_LIBRARIES(clitkAnisotropicDiffusion clitkCommon) SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkAnisotropicDiffusion) WRAP_GGO(clitkChangeImageInfo_GGO_C clitkChangeImageInfo.ggo) ADD_EXECUTABLE(clitkChangeImageInfo clitkChangeImageInfo.cxx - clitkChangeImageInfoGenericFilter.cxx - ${clitkChangeImageInfo_GGO_C}) + clitkChangeImageInfoGenericFilter.cxx + ${clitkChangeImageInfo_GGO_C}) TARGET_LINK_LIBRARIES(clitkChangeImageInfo clitkCommon) SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkChangeImageInfo) + WRAP_GGO(clitkMergeAsciiDoseActor_GGO_C clitkMergeAsciiDoseActor.ggo) + ADD_EXECUTABLE(clitkMergeAsciiDoseActor clitkMergeAsciiDoseActor.cxx ${clitkMergeAsciiDoseActor_GGO_C}) + TARGET_LINK_LIBRARIES(clitkMergeAsciiDoseActor ITKCommon clitkCommon) + SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkMergeAsciiDoseActor) + + WRAP_GGO(clitkImageUncertainty_GGO_C clitkImageUncertainty.ggo) + ADD_EXECUTABLE(clitkImageUncertainty clitkImageUncertainty.cxx clitkImageUncertainty_ggo.c) + TARGET_LINK_LIBRARIES(clitkImageUncertainty clitkCommon ${ITK_LIBRARIES}) + SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkImageUncertainty) + + #========================================================= + option(CLITK_USE_ROOT "Build experimental tools using root" OFF) + if (CLITK_USE_ROOT) + FIND_PACKAGE(ROOT REQUIRED) + if(ROOT_FOUND) + MESSAGE(STATUS "ROOT found : ${ROOT_LIBRARY_DIR} ${ROOT_INCLUDE_DIR} ${ROOT_LIBRARIES}") + ELSE(ROOT_FOUND) + MESSAGE(FATAL_ERROR + "Cannot build without ROOT. Please set ROOTSYS environement variable.") + endif(ROOT_FOUND) + INCLUDE_DIRECTORIES(${ROOT_INCLUDE_DIR}) + LINK_DIRECTORIES(${ROOT_LIBRARY_DIR}) + WRAP_GGO(clitkMergeRootFiles_GGO_C clitkMergeRootFiles.ggo) + ADD_EXECUTABLE(clitkMergeRootFiles clitkMergeRootFiles.cxx GateMergeManager.cc ${clitkMergeRootFiles_GGO_C}) + TARGET_LINK_LIBRARIES(clitkMergeRootFiles ${ROOT_LIBRARIES}) + SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkMergeRootFiles) + endif() + #========================================================= + + + #========================================================= IF(CLITK_EXPERIMENTAL) WRAP_GGO(clitkBinaryImageToMesh_GGO_C clitkBinaryImageToMesh.ggo) ADD_EXECUTABLE(clitkBinaryImageToMesh clitkBinaryImageToMesh.cxx ${clitkBinaryImageToMesh_GGO_C}) @@ -290,7 +341,10 @@ IF (CLITK_BUILD_TOOLS) TARGET_LINK_LIBRARIES(clitkMeshViewer clitkCommon) SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkMeshViewer) ENDIF(CLITK_EXPERIMENTAL) + #========================================================= + + #========================================================= IF(ITK_VERSION_MAJOR VERSION_LESS 4) MESSAGE("clitkDicomRTPlan2Gate is not compatible with GDCM<2 (ITK<4). It will not be built.") ELSE(ITK_VERSION_MAJOR VERSION_LESS 4) @@ -299,8 +353,9 @@ IF (CLITK_BUILD_TOOLS) TARGET_LINK_LIBRARIES(clitkDicomRTPlan2Gate clitkCommon) SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkDicomRTPlan2Gate) ENDIF(ITK_VERSION_MAJOR VERSION_LESS 4) + #========================================================= + INSTALL (TARGETS ${TOOLS_INSTALL} DESTINATION bin PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) ENDIF(CLITK_BUILD_TOOLS) - diff --git a/tools/GateMergeManager.cc b/tools/GateMergeManager.cc new file mode 100644 index 0000000..5c5a12c --- /dev/null +++ b/tools/GateMergeManager.cc @@ -0,0 +1,766 @@ +/*---------------------- + GATE version name: gate_v... + + Copyright (C): OpenGATE Collaboration + +This software is distributed under the terms +of the GNU Lesser General Public Licence (LGPL) +See GATE/LICENSE.txt for further details +----------------------*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GateMergeManager.hh" + +using namespace std; + +void GateMergeManager::StartMerging(string splitfileName){ + + // get the files to merge + ReadSplitFile(splitfileName); + //do the merging + if (m_fastMerge==true) FastMergeRoot(); + else MergeRoot(); + + //if we are here the merging has been successful + //we mark the directory as ready for cleanup + //string dir = splitfileName.substr(0,splitfileName.rfind("/")); + //string ready = "touch "+dir+"/ready_for_delete"; + //const int res=system(ready.c_str()); + //if(res) cout<<"Strange?? Can't mark "<2) cout<<"Root input file name: "<2) cout<<"Root output file name: "<0) return; + + stringstream ssnfiles; + char cline[512]; + while(splitfile){ //we allow for rubbish before "Number of files:" + splitfile.getline(cline,512); + if(!strncmp(cline,"Number of files:",16)){ + ssnfiles.str(cline+16); + ssnfiles>>m_Nfiles; // the number of files to merge + break; + } + } + + // now we look for the file names + int iRoot=0; + while(splitfile){ + splitfile.getline(cline,512); + // check for root + // input files + if(!strncmp(cline,"Root filename:",14)){ + m_vRootFileNames.push_back(strtok(cline+15," ")); + m_vRootFileNames[iRoot]+=".root"; + if(m_verboseLevel>2) cout<<"Root input file name: "<2) cout<<"Root output file name: "<Get("latest_event_ID"); + m_lastEvents[i+1]=int(h->GetMean()); + } + + if(!flgLstEvntID) { + cout<<"FastMerge: No latest_event_ID histogram - exit!"< treeNames; + TFile* node = TFile::Open(m_vRootFileNames[0].c_str(),"OLD"); + TIter nextkey(node->GetListOfKeys()); + TKey *key=0; + while ((key = (TKey*)nextkey())) + { + node->cd(); + TObject* obj = (TObject*)key->ReadObj(); + if( obj->IsA()->InheritsFrom("TTree")) + { + //no doubles + bool singleName=true; + for(unsigned int i=0;iGetName())==0) + { + singleName=false; + break; + } + } + if(singleName) treeNames.push_back(obj->GetName()); + } + } + //take care of all trees + for(unsigned int i=0;i1) cout<<"Problem with merging "<0) { + cout<<"Combining: "; + for(int i=0;i "<GetName()< treeNames; + TFile* node = TFile::Open(m_vRootFileNames[0].c_str(),"OLD"); + if(node==NULL){ + cout<<"Not a readable file "<GetListOfKeys()); + TKey *key=0; + while ((key = (TKey*)nextkey())) { + node->cd(); + TObject* obj = (TObject*)key->ReadObj(); + if( obj->IsA()->InheritsFrom("TH1")){ + m_RootTarget->cd(); + TH1 *h1 = (TH1 *)obj->Clone(); + if(strcmp(h1->GetName(),"latest_event_ID")){ + //any other histogram + for(int i=1;iGet( h1->GetName() ); + h1->Add( h2 ); + } + h1->Write(); + } else { + // latest_event_ID histogram + flgLstEvntID=true; + m_lastEvents[1]=int(h1->GetMean()); + TH1* h=NULL; + for(int i=1;iGet("latest_event_ID"); + m_lastEvents[i+1]=int(h->GetMean()); + } + if(h!=NULL) h->Write(); // we keep the highest latest_event_ID to allow for successive merging + else h1->Write(); + } + } + if( obj->IsA()->InheritsFrom("TH2")){ + m_RootTarget->cd(); + TH2 *h1 = (TH2 *)obj->Clone(); + for(int i=1;iGet( h1->GetName() ); + h1->Add( h2 ); + } + h1->Write(); + } + if( obj->IsA()->InheritsFrom("TTree")){ + //no doubles + bool singleName=true; + for(unsigned int i=0;iGetName())==0){ + singleName=false; + break; + } + } + if(singleName) treeNames.push_back(obj->GetName()); + } + } + if(!flgLstEvntID) { + cout<<"Merge: No latest_event_ID histogram - exit!"<1) cout<<"Problem with merging "<1) cout<<"Going to erase the following files:"<1||test){ + cout<<" --> "< "<Add(m_vRootFileNames[i].c_str()); + int nentries=chain->GetEntries(); + if(nentries<=0) { + if(m_verboseLevel>1) cout<GetName()<<" is empty!"<FindBranch("eventID1")!=NULL) { + if( (chain->FindBranch("runID")==NULL) + ||(chain->FindBranch("time1")==NULL) + ||(chain->FindBranch("time2")==NULL) ) { + cout<<"Cannot find one of: runID, time1, time2 in "<GetName()<FindBranch("runID")==NULL)||(chain->FindBranch("eventID")==NULL) + ||(chain->FindBranch("time")==NULL) ) + { + cout<<"Cannot find one of: runID, eventID, time in "<GetName()<ReOpen("UPDATE"); + TTree *oldTree = (TTree*)gDirectory->Get(name.c_str()); + TBranch *branch = oldTree->GetBranch("event"); + branch->SetAddress(&event); + TBranch* newBranch=oldTree->Branch("eventcluster",&event,"event"); + + Int_t nentries=(Int_t)oldTree->GetEntries(); + + if (j==0) offset=0; + else offset+=m_lastEvents[currentfile]; + currentfile++; + + for(int i=0;iGetEvent(i); + if(lastEvent!=event) + { + lastEvent=event; + event+=offset; + newBranch->Fill(); + } + else + { + if((i==nentries-1) && (j==m_Nfiles-1)) + { + event+=offset; + newBranch->Fill(); + } + else if (i!=nentries-1) + { + branch->GetEvent(i); + event+=offset; + newBranch->Fill(); + lastEvent=0; + offset=0; + } + } + } + oldTree->Write(); + } + return true; +} + +/*******************************************************************************************/ +bool GateMergeManager::FastMergeSing(string name) +{ +int eventID = 0; +int runID = 0; +int offset = 0; +int currentfile = 0; +float lastRun =-1; +string clusterName=name+"_cluster"; + +for(int j=0;jReOpen("UPDATE"); + TTree *oldTree = (TTree*)gDirectory->Get(name.c_str()); + TBranch *branch = oldTree->GetBranch("eventID"); + branch->SetAddress(&eventID); + TBranch *branch2 = oldTree->GetBranch("runID"); + branch2->SetAddress(&runID); + TBranch* newBranch=oldTree->Branch("eventIDcluster",&eventID,"eventID/I"); + + Int_t nentries=(Int_t)oldTree->GetEntries(); + + if (j==0) offset=0; + else offset+=m_lastEvents[currentfile]; + currentfile++; + + for(int i=0;iGetEvent(i); + if(lastRun!=runID) + { + lastRun=runID; + offset=0; + } + eventID+=offset; + newBranch->Fill(); + } + oldTree->Write(); + } + return true; +} + +/*******************************************************************************************/ +bool GateMergeManager::FastMergeCoin(string name) +{ +//create the output file +int eventID1 = 0; +int eventID2 = 0; +int runID = 0; +int offset = 0; +int currentfile = 0; +float lastRun =-1; +string clusterName=name+"_cluster"; +cout<<"starting coincidence merging..."<ReOpen("UPDATE"); + TTree *oldTree = (TTree*)gDirectory->Get(name.c_str()); + TBranch *branch1 = oldTree->GetBranch("eventID1"); + branch1->SetAddress(&eventID1); + TBranch *branch2 = oldTree->GetBranch("eventID2"); + branch2->SetAddress(&eventID2); + TBranch *branch3 = oldTree->GetBranch("runID"); + branch3->SetAddress(&runID); + + TBranch* newBranch1=oldTree->Branch("eventID1cluster",&eventID1,"eventID1/I"); + TBranch* newBranch2=oldTree->Branch("eventID2cluster",&eventID2,"eventID2/I"); + + Int_t nentries=(Int_t)oldTree->GetEntries(); + + if (j==0) offset=0; + else offset+=m_lastEvents[currentfile]; + cout<<"the offset in this file is: "<GetEvent(i); + branch2->GetEvent(i); + branch3->GetEvent(i); + if(lastRun!=runID) + { + lastRun=runID; + offset=0; + } + eventID1+=offset; + eventID2+=offset; + newBranch1->Fill(); + newBranch2->Fill(); + } + oldTree->Write(); + } + return true; +} + +/*******************************************************************************************/ +// Gate tree merger +bool GateMergeManager::MergeGate(TChain* chainG) { + + int nentries=chainG->GetEntries(); + + float event = 0; + chainG->SetBranchAddress("event",&event); + Float_t iontime = 0; + chainG->SetBranchAddress("iontime",&iontime); + + //create the new tree + //Allow for large files and do not write every bit separately + m_RootTarget->cd(); + TTree * newTree = chainG->CloneTree(0); + newTree->SetAutoSave(2000000000); + if(m_maxRoot!=0) newTree->SetMaxTreeSize(m_maxRoot); + else newTree->SetMaxTreeSize(17179869184LL); + + // changing the compression level everywhere + TBranch *br; + TIter next(newTree->GetListOfBranches()); + while ((br=(TBranch*)next())) br->SetCompressionLevel(m_CompLevel); + + // the main part: modify the eventID + int offset = 0; + int currentTree = 0; + float lastEvent =-1; + float maxtime =-999999999; + for(int i=0;iGetEntry(i) <= 0) break; //end of chain + if(chainG->GetTreeNumber()>currentTree) { + currentTree++; + offset+=m_lastEvents[currentTree]; + // check for overlaping time intervalls between different files + // (not within the same file i.e. no time order assumed) + if(iontime0) + cout<<"Warning - overlapping Gate iontime (" + <Fill(); + } else { + cout<<"Warning - inf or NaN in Gate tree for iontime! "<GetEntry(i+1) <= 0) { //chain end fill the double event + event+=offset; + newTree->Fill(); + } else if(chainG->GetTreeNumber()==currentTree //no new file or + ||(chainG->GetTreeNumber()>currentTree + &&m_lastEvents[chainG->GetTreeNumber()]==0) ) { //new file with no offset fill double event + chainG->GetEntry(i); + event+=offset; + newTree->Fill(); + lastEvent=0;// we may have triple 1 (1 event run) + offset=0; + } + } + } + newTree->Write(); + delete newTree; + return true; +} + +/*******************************************************************************************/ +// Singles and Hits tree merger +bool GateMergeManager::MergeSing(TChain* chainS){ + + int nentriesS=chainS->GetEntries(); + + int eventID = 0; + int runID = 0; + double time = 0; + + chainS->SetBranchAddress("eventID",&eventID); + chainS->SetBranchAddress("runID",&runID); + chainS->SetBranchAddress("time",&time); + + m_RootTarget->cd(); + TTree * newSing = chainS->CloneTree(0); + newSing->SetAutoSave(2000000000); + if(m_maxRoot!=0) newSing->SetMaxTreeSize(m_maxRoot); + else newSing->SetMaxTreeSize(17179869184LL); + + // changing CompLevel everywhere + TBranch *br; + TIter next(newSing->GetListOfBranches()); + while ((br=(TBranch*)next())) br->SetCompressionLevel(m_CompLevel); + + //the main part: changing eventID + int offset = 0; + int currentTree = 0; + float lastRun = 0; + float maxtime =-999999999; + for(int i=0;iGetEntry(i) <= 0) break; //end of chain + if(chainS->GetTreeNumber()>currentTree) { + currentTree++; + offset+=m_lastEvents[currentTree]; + // check for overlaping time intervalls between different files + // (not within the same file i.e. no time order assumed) + if(time0) + cout<<"Warning - overlapping Singles time (" + <Fill(); + if(maxtimeWrite(); + delete newSing; + return true; +}; + +/*******************************************************************************************/ +// Coincidences tree merger +bool GateMergeManager::MergeCoin(TChain* chainC){ + + int nentriesC=chainC->GetEntries(); + + int eventID1 = 0; + chainC->SetBranchAddress("eventID1",&eventID1); + double time1 = 0; + chainC->SetBranchAddress("time1",&time1); + int eventID2 = 0; + chainC->SetBranchAddress("eventID2",&eventID2); + double time2 = 0; + chainC->SetBranchAddress("time2",&time2); + int runID = 0; + chainC->SetBranchAddress("runID",&runID); + + m_RootTarget->cd(); + TTree * newCoin = chainC->CloneTree(0); + newCoin->SetAutoSave(2000000000); + if(m_maxRoot!=0) newCoin->SetMaxTreeSize(m_maxRoot); + else newCoin->SetMaxTreeSize(17179869184LL); + + // changing CompLevel everywhere + TBranch *br; + TIter next(newCoin->GetListOfBranches()); + while ((br=(TBranch*)next())) br->SetCompressionLevel(m_CompLevel); + + int offset = 0; + int currentTree = 0; + float lastRun = 0; + float maxtime =-999999999; + for(int i=0;iGetEntry(i) <= 0) break; //end of chain + if(chainC->GetTreeNumber()>currentTree) { + currentTree++; + offset+=m_lastEvents[currentTree]; + // check for overlaping time intervalls between different files + // (not within the same file i.e. no time order assumed) + if(time10) + cout<<"Warning - overlapping Coincidences time1 (" + <0) + cout<<"Warning - overlapping Coincidences time2 (" + <Fill(); + if(maxtimeWrite(); + delete newCoin; + return true; +} +/*******************************************************************************************/ diff --git a/tools/GateMergeManager.hh b/tools/GateMergeManager.hh new file mode 100644 index 0000000..126dea3 --- /dev/null +++ b/tools/GateMergeManager.hh @@ -0,0 +1,81 @@ +/*---------------------- + GATE version name: gate_v... + + Copyright (C): OpenGATE Collaboration + +This software is distributed under the terms +of the GNU Lesser General Public Licence (LGPL) +See GATE/LICENSE.txt for further details +----------------------*/ + + +#ifndef GateMergeManager_h +#define GateMergeManager_h 1 +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +typedef list Strings; + +class GateMergeManager +{ +public: + + GateMergeManager(bool fastMerge,int verboseLevel,bool forced,Long64_t maxRoot,string outDir){ + m_verboseLevel = verboseLevel; + m_forced = forced; + m_maxRoot = maxRoot; + m_outDir = outDir; + m_CompLevel = 1; + m_fastMerge = fastMerge; + }; + ~GateMergeManager() + { + for (std::vector::const_iterator iter=filearr.begin(); iter!=filearr.end(); iter++) + { + (*iter)->Close(); + delete *iter; + } + } + + + void StartMerging(string splitfileName); + void StartMergingFromFilenames(Strings filenames, string outputfile); + void ReadSplitFile(string splitfileName); + bool MergeTree(string name); + bool MergeGate(TChain* chain); + bool MergeSing(TChain* chain); + bool MergeCoin(TChain* chain); + + // the cleanup after succesful merging + void StartCleaning(string splitfileName,bool test); + + // the merging methods + void MergeRoot(); + +private: + void FastMergeRoot(); + bool FastMergeGate(string name); + bool FastMergeSing(string name); + bool FastMergeCoin(string name); + bool m_forced; // if to overwrite existing files + int m_verboseLevel; + std::vector filearr; + Long64_t m_maxRoot; // maximum size of root output file + int m_CompLevel; // compression level for root output + string m_outDir; // where to save the output files + int m_Nfiles; // number of files to mergw + vector m_lastEvents; // latestevent from al files + vector m_vRootFileNames; // names of root files to merge + TFile* m_RootTarget; // root output file + string m_RootTargetName; // name of target i.e. root output file + bool m_fastMerge; // fast merge option, corrects the eventIDs locally +}; + + +#endif diff --git a/tools/clitkAffineTransformGenericFilter.h b/tools/clitkAffineTransformGenericFilter.h index 3950632..613e1cc 100644 --- a/tools/clitkAffineTransformGenericFilter.h +++ b/tools/clitkAffineTransformGenericFilter.h @@ -87,11 +87,6 @@ namespace clitk //---------------------------------------- void Update(); - template - static - typename itk::Matrix - createMatrixFromElastixFile(std::vector & filename, bool verbose=true); - protected: //---------------------------------------- @@ -108,10 +103,6 @@ namespace clitk template void UpdateWithDimAndPixelType(); template void UpdateWithDimAndVectorType(); - static bool GetElastixValueFromTag(std::ifstream & is, std::string tag, std::string & value); - static void GetValuesFromValue(const std::string & s, - std::vector & values); - //---------------------------------------- // Data members //---------------------------------------- diff --git a/tools/clitkAffineTransformGenericFilter.txx b/tools/clitkAffineTransformGenericFilter.txx index 03cf862..150c8c1 100644 --- a/tools/clitkAffineTransformGenericFilter.txx +++ b/tools/clitkAffineTransformGenericFilter.txx @@ -22,6 +22,7 @@ #include #include #include +#include "clitkElastix.h" namespace clitk { @@ -183,7 +184,7 @@ namespace clitk if (m_ArgsInfo.elastix_given) { std::vector s; for(uint i=0; i(s, m_Verbose); + matrix = createMatrixFromElastixFile(s, m_Verbose); } else matrix.SetIdentity(); @@ -491,140 +492,6 @@ namespace clitk } //------------------------------------------------------------------- - - - //------------------------------------------------------------------- - template - template - typename itk::Matrix - AffineTransformGenericFilter::createMatrixFromElastixFile(std::vector & filename, bool verbose) - { - if (Dimension != 3) { - FATAL("Only 3D yet" << std::endl); - } - typename itk::Matrix matrix; - - itk::CenteredEuler3DTransform::Pointer mat = itk::CenteredEuler3DTransform::New(); - itk::CenteredEuler3DTransform::Pointer previous; - for(uint j=0; j cor; - GetValuesFromValue(s, cor); - - // Get Transformparameters - GetElastixValueFromTag(is, "TransformParameters ", s); // space is needed - if (!b) { - FATAL("Error must read 'TransformParameters' in " << filename[j] << std::endl); - } - std::vector results; - GetValuesFromValue(s, results); - - // construct a stream from the string - itk::CenteredEuler3DTransform::ParametersType p; - p.SetSize(9); - for(uint i=0; i<3; i++) - p[i] = atof(results[i].c_str()); // Rotation - for(uint i=0; i<3; i++) - p[i+3] = atof(cor[i].c_str()); // Centre of rotation - for(uint i=0; i<3; i++) - p[i+6] = atof(results[i+3].c_str()); // Translation - mat->SetParameters(p); - - if (verbose) { - std::cout << "Rotation (deg) : " << rad2deg(p[0]) << " " << rad2deg(p[1]) << " " << rad2deg(p[2]) << std::endl; - std::cout << "Center of rot (phy) : " << p[3] << " " << p[4] << " " << p[5] << std::endl; - std::cout << "Translation (phy) : " << p[6] << " " << p[7] << " " << p[8] << std::endl; - } - - // Compose with previous if needed - if (j!=0) { - mat->Compose(previous); - if (verbose) { - std::cout << "Composed rotation (deg) : " << rad2deg(mat->GetAngleX()) << " " << rad2deg(mat->GetAngleY()) << " " << rad2deg(mat->GetAngleZ()) << std::endl; - std::cout << "Composed center of rot (phy) : " << mat->GetCenter() << std::endl; - std::cout << "Compsoed translation (phy) : " << mat->GetTranslation() << std::endl; - } - } - // previous = mat->Clone(); // ITK4 - previous = itk::CenteredEuler3DTransform::New(); - previous->SetParameters(mat->GetParameters()); - } - - mat = previous; - for(uint i=0; i<3; i++) - for(uint j=0; j<3; j++) - matrix[i][j] = mat->GetMatrix()[i][j]; - // Offset is -Rc + t + c - matrix[0][3] = mat->GetOffset()[0]; - matrix[1][3] = mat->GetOffset()[1]; - matrix[2][3] = mat->GetOffset()[2]; - matrix[3][3] = 1; - - return matrix; - } - - //------------------------------------------------------------------- - template - bool - AffineTransformGenericFilter::GetElastixValueFromTag(std::ifstream & is, - std::string tag, - std::string & value) - { - std::string line; - is.seekg (0, is.beg); - while(std::getline(is, line)) { - unsigned pos = line.find(tag); - if (pos - void - AffineTransformGenericFilter::GetValuesFromValue(const std::string & s, - std::vector & values) - { - std::stringstream strstr(s); - std::istream_iterator it(strstr); - std::istream_iterator end; - std::vector results(it, end); - values.clear(); - values.resize(results.size()); - for(uint i=0; i FilterType; + FilterType::Pointer filter = FilterType::New(); + + filter->SetArgsInfo(args_info); + + try { + filter->Update(); + } catch(std::runtime_error e) { + std::cout << e.what() << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} // This is the end, my friend +//-------------------------------------------------------------------- diff --git a/tools/clitkDice.ggo b/tools/clitkDice.ggo new file mode 100644 index 0000000..3fcaeaf --- /dev/null +++ b/tools/clitkDice.ggo @@ -0,0 +1,17 @@ +#File clitkDice.ggo +package "clitkDice" +version "1.0" +purpose "Compute Dice between labeled images. Background must be 0." + +section "General options" +option "config" - "Config file" string no +option "verbose" v "Verbose" flag off +option "imagetypes" - "Display allowed image types" flag off +option "long" l "Long display (not only dice)" flag off + +section "Input" +option "input1" i "Input mask 1" string yes +option "input2" j "Input mask 2" string yes + +option "label1" - "Label in input1" int no default="1" +option "label2" - "Label in input2" int no default="1" diff --git a/tools/clitkElastixTransformToMatrix.cxx b/tools/clitkElastixTransformToMatrix.cxx index 59bf49e..7efc4e9 100644 --- a/tools/clitkElastixTransformToMatrix.cxx +++ b/tools/clitkElastixTransformToMatrix.cxx @@ -19,6 +19,8 @@ // clitk #include "clitkElastixTransformToMatrix_ggo.h" #include "clitkAffineTransformGenericFilter.h" +#include "clitkElastix.h" +#include "clitkMatrix.h" //-------------------------------------------------------------------- int main(int argc, char * argv[]) @@ -29,21 +31,15 @@ int main(int argc, char * argv[]) CLITK_INIT; // Use static fct of AffineTransformGenericFilter - typedef clitk::AffineTransformGenericFilter FilterType; std::vector l; l.push_back(args_info.input_arg); - itk::Matrix m = - FilterType::createMatrixFromElastixFile<3, int>(l, args_info.verbose_flag); + itk::Matrix m = clitk::createMatrixFromElastixFile<3>(l, args_info.verbose_flag); // Print matrix std::ofstream os; clitk::openFileForWriting(os, args_info.output_arg); - for(unsigned int i=0; i<4; i++) { - for(unsigned int j=0; j<4; j++) - os << m[i][j] << " "; - os << std::endl; - } - os.close(); + os << clitk::Get4x4MatrixDoubleAsString(m, 16); + os.close(); return EXIT_SUCCESS; }// end main diff --git a/tools/clitkImageUncertainty.cxx b/tools/clitkImageUncertainty.cxx new file mode 100644 index 0000000..63b1f12 --- /dev/null +++ b/tools/clitkImageUncertainty.cxx @@ -0,0 +1,115 @@ +/*========================================================================= + + Program: clitk + Module: $RCSfile: clitkImageUncertainty.cxx,v $ + Language: C++ + Date: $Date: 2011/03/03 15:03:30 $ + Version: $Revision: 1.3 $ + + Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de + l'Image). All rights reserved. See Doc/License.txt or + http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef CLITKIMAGEUNCERTAINTY_CXX +#define CLITKIMAGEUNCERTAINTY_CXX + +/** + ================================================= + * @file clitkImageUncertainty.cxx + * @author David Sarrut + * @date 04 Jul 2006 14:03:57 + * + * @brief + * + * + =================================================*/ + +// clitk include +#include "clitkImageUncertainty_ggo.h" +#include "clitkImageCommon.h" +#include "clitkCommon.h" +#include "clitkPortability.h" + +// itk include +#include "itkImageRegionConstIterator.h" +#include "itkImageRegionIterator.h" + +//==================================================================== +int main(int argc, char * argv[]) { + + // init command line + GGO(clitkImageUncertainty, args_info); + + // Declare main types + typedef float PixelType; + const unsigned int Dimension=3; + typedef itk::Image< PixelType, Dimension > ImageType; + + // Read images + ImageType::Pointer input = + clitk::readImage(args_info.input_arg, args_info.verbose_flag); + ImageType::Pointer inputSquared = + clitk::readImage(args_info.inputSquared_arg, args_info.verbose_flag); + + // Create Output + ImageType::Pointer output = ImageType::New(); + output->SetRegions(input->GetLargestPossibleRegion()); + output->CopyInformation(input); + output->Allocate(); + + // Loop + typedef itk::ImageRegionConstIterator ConstIteratorType; + ConstIteratorType pi(input, input->GetLargestPossibleRegion()); + ConstIteratorType pii(inputSquared, inputSquared->GetLargestPossibleRegion()); + pi.GoToBegin(); + pii.GoToBegin(); + typedef itk::ImageRegionIterator IteratorType; + IteratorType po(output, output->GetLargestPossibleRegion()); + po.GoToBegin(); + + int NumberOfEvents = args_info.NumberOfEvents_arg; + while ( !pi.IsAtEnd() ) { + double squared = pii.Get(); + double mean = pi.Get(); + double uncert = sqrt((NumberOfEvents*squared - mean*mean) / ((NumberOfEvents-1)*(mean*mean))); + if (!IsNormal(uncert)) uncert = 1.; + po.Set(uncert); + ++pi; + ++pii; + ++po; + } +// *po = sqrt( (NumberOfEvents*squared - mean*mean) / +// ((NumberOfEvents-1)*(mean*mean)) ); +// ++po; + + + + // Write output image + // DD(clitk::GetExtension(args_info.output_arg)); + if (clitk::GetExtension(args_info.output_arg) != "txt") { + clitk::writeImage(output, args_info.output_arg, args_info.verbose_flag); + } + else { + std::ofstream os; + clitk::openFileForWriting(os, args_info.output_arg); + typedef itk::ImageRegionConstIterator IteratorType; + IteratorType pi(output, output->GetLargestPossibleRegion()); + pi.GoToBegin(); + os << "# Image size = " << output->GetLargestPossibleRegion().GetSize() << std::endl; + os << "# Image spacing = " << output->GetSpacing() << std::endl; + os << "# Number of events = " << NumberOfEvents << std::endl; + while (!pi.IsAtEnd()) { + os << pi.Get() << std::endl; + ++pi; + } + } +} + + +#endif /* end #define CLITKIMAGEUNCERTAINTY_CXX */ diff --git a/tools/clitkImageUncertainty.ggo b/tools/clitkImageUncertainty.ggo new file mode 100644 index 0000000..af5dfad --- /dev/null +++ b/tools/clitkImageUncertainty.ggo @@ -0,0 +1,10 @@ +# file clitkImageRescaleIntensity.ggo +package "clitk" +version "Rescale intensity in the image" + +option "config" - "Config file" string no +option "input" i "Input image filename" string yes +option "inputSquared" s "Input squared image filename" string yes +option "output" o "Output image filename" string yes +option "NumberOfEvents" n "Number of events" int yes +option "verbose" v "Verbose" flag off diff --git a/tools/clitkLabelImageOverlapMeasureGenericFilter.h b/tools/clitkLabelImageOverlapMeasureGenericFilter.h new file mode 100644 index 0000000..05332ea --- /dev/null +++ b/tools/clitkLabelImageOverlapMeasureGenericFilter.h @@ -0,0 +1,76 @@ +/*========================================================================= + 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 CLITKLABELIMAGEOVERLAPMEASUREGENERICFILTER_H +#define CLITKLABELIMAGEOVERLAPMEASUREGENERICFILTER_H + +// clitk +#include "clitkImageToImageGenericFilter.h" +#include "clitkLabelImageOverlapMeasureFilter.h" +#include "clitkBoundingBoxUtils.h" +#include "clitkCropLikeImageFilter.h" + +//-------------------------------------------------------------------- +namespace clitk +{ + + template + class ITK_EXPORT LabelImageOverlapMeasureGenericFilter: + public ImageToImageGenericFilter > + { + public: + //-------------------------------------------------------------------- + LabelImageOverlapMeasureGenericFilter(); + + //-------------------------------------------------------------------- + typedef ImageToImageGenericFilter > Superclass; + typedef LabelImageOverlapMeasureGenericFilter Self; + typedef itk::SmartPointer Pointer; + typedef itk::SmartPointer ConstPointer; + + //-------------------------------------------------------------------- + itkNewMacro(Self); + itkTypeMacro(LabelImageOverlapMeasureGenericFilter, LightObject); + + //-------------------------------------------------------------------- + void SetArgsInfo(const ArgsInfoType & a); + template + void SetOptionsFromArgsInfoToFilter(FilterType * f) ; + + //-------------------------------------------------------------------- + // Main function called each time the filter is updated + template + void UpdateWithInputImageType(); + + protected: + template void InitializeImageType(); + ArgsInfoType mArgsInfo; + + private: + LabelImageOverlapMeasureGenericFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + };// end class + //-------------------------------------------------------------------- +} // end namespace clitk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "clitkLabelImageOverlapMeasureGenericFilter.txx" +#endif + +#endif // #define CLITKRELATIVEPOSITIONANALYZERGENERICFILTER_H diff --git a/tools/clitkLabelImageOverlapMeasureGenericFilter.txx b/tools/clitkLabelImageOverlapMeasureGenericFilter.txx new file mode 100644 index 0000000..1ac11ee --- /dev/null +++ b/tools/clitkLabelImageOverlapMeasureGenericFilter.txx @@ -0,0 +1,102 @@ +/*========================================================================= + 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 + ===========================================================================**/ + +//-------------------------------------------------------------------- +template +clitk::LabelImageOverlapMeasureGenericFilter:: +LabelImageOverlapMeasureGenericFilter(): + ImageToImageGenericFilter("LabelImageOverlapMeasure") +{ + // Default values + cmdline_parser_clitkDice_init(&mArgsInfo); + //InitializeImageType<2>(); + InitializeImageType<3>(); +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +template +template +void clitk::LabelImageOverlapMeasureGenericFilter:: +InitializeImageType() +{ + ADD_IMAGE_TYPE(Dim, uchar); +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +template +void clitk::LabelImageOverlapMeasureGenericFilter:: +SetArgsInfo(const ArgsInfoType & a) +{ + mArgsInfo=a; + //this->SetIOVerbose(mArgsInfo.verbose_flag); + if (mArgsInfo.imagetypes_flag) this->PrintAvailableImageTypes(); + if (mArgsInfo.input1_given) this->AddInputFilename(mArgsInfo.input1_arg); + if (mArgsInfo.input2_given) this->AddInputFilename(mArgsInfo.input2_arg); +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +// Update with the number of dimensions and the pixeltype +//-------------------------------------------------------------------- +template +template +void clitk::LabelImageOverlapMeasureGenericFilter:: +SetOptionsFromArgsInfoToFilter(FilterType * f) +{ + f->SetLabel1(mArgsInfo.label1_arg); + f->SetLabel2(mArgsInfo.label2_arg); + f->SetVerboseFlag(mArgsInfo.verbose_flag); + f->SetLongFlag(mArgsInfo.long_flag); +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +// Update with the number of dimensions and the pixeltype +//-------------------------------------------------------------------- +template +template +void clitk::LabelImageOverlapMeasureGenericFilter:: +UpdateWithInputImageType() +{ + // Reading input + typename ImageType::Pointer input1 = this->template GetInput(0); + typename ImageType::Pointer input2 = this->template GetInput(1); + + // Create filter + typedef clitk::LabelImageOverlapMeasureFilter FilterType; + typename FilterType::Pointer filter = FilterType::New(); + + // Set global Options + filter->SetInput(0, input1); + filter->SetInput(1, input2); + SetOptionsFromArgsInfoToFilter(filter); + + // Go ! + filter->Update(); + + // Write/Save results + // typename ImageType::Pointer output = filter->GetOutput(); + // this->template SetNextOutput(output); +} +//-------------------------------------------------------------------- diff --git a/tools/clitkMatrixInverse.cxx b/tools/clitkMatrixInverse.cxx new file mode 100644 index 0000000..7171467 --- /dev/null +++ b/tools/clitkMatrixInverse.cxx @@ -0,0 +1,54 @@ +/*========================================================================= + 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 +===========================================================================**/ + +// clitk +#include "clitkMatrixInverse_ggo.h" +#include "clitkTransformUtilities.h" +#include "clitkIO.h" +#include "clitkMatrix.h" + +//-------------------------------------------------------------------- +int main(int argc, char * argv[]) +{ + // Init command line + GGO(clitkMatrixInverse, args_info); + CLITK_INIT; + + // Read matrix + itk::Matrix matrix; + try { + matrix = clitk::ReadMatrix3D(args_info.input_arg); + } + catch (itk::ExceptionObject & err) { + std::cerr << "Error reading " << args_info.input_arg << std::endl; + std::cerr << err.GetDescription() << std::endl; + exit(-1); + } + + matrix = matrix.GetInverse(); + + // Print matrix + std::ofstream os; + clitk::openFileForWriting(os, args_info.output_arg); + os << clitk::Get4x4MatrixDoubleAsString(matrix, 16); + os.close(); + + return EXIT_SUCCESS; +}// end main + +//-------------------------------------------------------------------- diff --git a/tools/clitkMatrixInverse.ggo b/tools/clitkMatrixInverse.ggo new file mode 100644 index 0000000..391ae2f --- /dev/null +++ b/tools/clitkMatrixInverse.ggo @@ -0,0 +1,8 @@ +#File clitkMatrixToElastixTransform.ggo +package "clitkMatrixInverse" +version "1.0" +purpose "" + +option "config" - "Config file" string optional +option "input" i "Input matrix filename" string required +option "output" o "Output matrix filename" string required diff --git a/tools/clitkMatrixToElastixTransform.cxx b/tools/clitkMatrixToElastixTransform.cxx new file mode 100644 index 0000000..a8b7520 --- /dev/null +++ b/tools/clitkMatrixToElastixTransform.cxx @@ -0,0 +1,118 @@ +/*========================================================================= + 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 +===========================================================================**/ + +// clitk +#include "clitkMatrixToElastixTransform_ggo.h" +#include "clitkTransformUtilities.h" +#include "clitkIO.h" + +// itk +#include + +//-------------------------------------------------------------------- +int main(int argc, char * argv[]) +{ + // Init command line + GGO(clitkMatrixToElastixTransform, args_info); + CLITK_INIT; + + // Read matrix + itk::Matrix matrix; + try { + matrix = clitk::ReadMatrix3D(args_info.input_arg); + } + catch (itk::ExceptionObject & err) { + std::cerr << "Error reading " << args_info.input_arg << std::endl; + std::cerr << err.GetDescription() << std::endl; + exit(-1); + } + + // Compute parameters from transfer using itk Euler transform + itk::Euler3DTransform::CenterType center; + center.Fill(0.); + if(args_info.center_given==3) { + center[0] = args_info.center_arg[0]; + center[1] = args_info.center_arg[1]; + center[2] = args_info.center_arg[2]; + } + itk::Euler3DTransform::MatrixType rotMat; + itk::Euler3DTransform::OutputVectorType transVec; + for(int i=0; i<3; i++) { + transVec[i] = matrix[i][3]; + for(int j=0; j<3; j++) + rotMat[i][j] = matrix[i][j]; + } + itk::Euler3DTransform::Pointer euler; + euler = itk::Euler3DTransform::New(); + euler->SetCenter(center); + euler->SetOffset(transVec); + euler->SetComputeZYX(false); + try { + euler->SetMatrix(rotMat); + } + catch (itk::ExceptionObject & err) { + std::cerr << "Error reading " << args_info.input_arg << std::endl; + std::cerr << err.GetDescription() << std::endl; + exit(-1); + } + + // Write result + std::ofstream out; + clitk::openFileForWriting(out, args_info.output_arg); + out << "(Transform \"EulerTransform\")" << std::endl; + out << "(NumberOfParameters 6)" << std::endl; + out << "(TransformParameters "; + for(unsigned int i=0; i<6; i++) + out << euler->GetParameters()[i] << ' '; + out << ')' << std::endl; + out << "(InitialTransformParametersFileName \"NoInitialTransform\")" << std::endl; + out << "(HowToCombineTransforms \"Compose\")" << std::endl; + + out << "// EulerTransform specific" << std::endl; + out << "(CenterOfRotationPoint "<< center[0] << ' ' << center[1] << ' ' << center[2] << ')' << std::endl; + out << "(ComputeZYX \"false\")" << std::endl; + + // The rest is commented, up to the user to define it manually + out << "// Image specific" << std::endl; + out << "// (FixedImageDimension 3)" << std::endl; + out << "// (MovingImageDimension 3)" << std::endl; + out << "// (FixedInternalImagePixelType \"float\")" << std::endl; + out << "// (MovingInternalImagePixelType \"float\")" << std::endl; + out << "// (Size 1 1 1)" << std::endl; + out << "// (Index 0 0 0)" << std::endl; + out << "// (Spacing 1 1 1)" << std::endl; + out << "// (Origin -0.5 -0.5 -0.5)" << std::endl; + out << "// (Direction 1 0 0 0 1 0 0 0 1)" << std::endl; + out << "// (UseDirectionCosines \"true\")" << std::endl << std::endl; + + out << "// ResampleInterpolator specific" << std::endl; + out << "// (ResampleInterpolator \"FinalBSplineInterpolator\")" << std::endl; + out << "// (FinalBSplineInterpolationOrder 3)" << std::endl << std::endl; + + out << "// Resampler specific" << std::endl; + out << "// (Resampler \"DefaultResampler\")" << std::endl; + out << "// (DefaultPixelValue 0.000000)" << std::endl; + out << "// (ResultImageFormat \"mhd\")" << std::endl; + out << "// (ResultImagePixelType \"short\")" << std::endl; + out << "// (CompressResultImage \"false\")" << std::endl; + out.close(); + + return EXIT_SUCCESS; +}// end main + +//-------------------------------------------------------------------- diff --git a/tools/clitkMatrixToElastixTransform.ggo b/tools/clitkMatrixToElastixTransform.ggo new file mode 100644 index 0000000..38f73fa --- /dev/null +++ b/tools/clitkMatrixToElastixTransform.ggo @@ -0,0 +1,10 @@ +#File clitkMatrixToElastixTransform.ggo +package "clitkMatrixToElastixTransform" +version "1.0" +purpose "" + +option "config" - "Config file" string optional +option "verbose" v "Verbose" flag off +option "input" i "Input matrix filename" string required +option "output" o "Output elastix filename" string required +option "center" - "Rotation center" float no multiple(3) diff --git a/tools/clitkMergeAsciiDoseActor.cxx b/tools/clitkMergeAsciiDoseActor.cxx new file mode 100644 index 0000000..4b1f861 --- /dev/null +++ b/tools/clitkMergeAsciiDoseActor.cxx @@ -0,0 +1,64 @@ +/*========================================================================= + Program: vv http://www.creatis.insa-lyon.fr/rio/vv + Main authors : XX XX XX + + Authors belongs to: + - University of LYON http://www.universite-lyon.fr/ + - Léon Bérard cancer center http://oncora1.lyon.fnclcc.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 http://www.opensource.org/licenses/bsd-license.php + - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html + + =========================================================================*/ + +#include +#include "clitkCommon.h" +#include "clitkMergeAsciiDoseActor_ggo.h" + +//-------------------------------------------------------------------- +int main(int argc, char * argv[]) { + + // Init command line + GGO(clitkMergeAsciiDoseActor, args_info); + + // Read input 1 + std::vector input1; + clitk::readDoubleFromFile(args_info.input1_arg, input1); + DD(input1.size()); + + // Read input 2 + std::vector input2; + clitk::readDoubleFromFile(args_info.input2_arg, input2); + DD(input2.size()); + + // Check + if (input1.size() != input2.size()) { + std::cerr << "Error. Please provide input file with the same number of values. Read " + << input1.size() << " in " << args_info.input1_arg + << " and " << input2.size() << " in " << args_info.input2_arg << std::endl; + exit(0); + } + + // Add + for(unsigned int i=0; i + * @date 01 Apr 2009 + * + * @brief + * + =================================================*/ + +#include "clitkMergeRootFiles_ggo.h" +#include "clitkCommon.h" +#include "GateMergeManager.hh" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::endl; +using std::cout; + +struct PetInputFile +{ + string filename; + double mean_time; +}; + +bool sort_pet_input_file(const PetInputFile& a, const PetInputFile& b) +{ + return a.mean_time PetInputFiles; + +//----------------------------------------------------------------------------- +int main(int argc, char * argv[]) { + + gROOT->GetPluginManager()->AddHandler("TVirtualStreamerInfo", "*", + "TStreamerInfo", "RIO", "TStreamerInfo()"); + + // init command line + GGO(clitkMergeRootFiles, args_info); + + // Check parameters + if (args_info.input_given < 2) { + FATAL("Error, please provide at least two inputs files"); + } + + { // Detect Pet output + bool all_pet_output = true; + PetInputFiles pet_input_files; + for (uint i=0; i(handle->Get("Hits")); + TTree* singles = dynamic_cast(handle->Get("Singles")); + const bool is_pet_output = (hits!=NULL) && (singles!=NULL); + cout << "testing " << filename << " is_pet_output " << is_pet_output; + + if (is_pet_output) + { + double time; + double time_accum = 0; + singles->SetBranchAddress("time",&time); + size_t total = singles->GetEntries(); + for (size_t kk=0; kkGetEntry(kk); + time_accum += time; + } + + input_file.mean_time = time_accum/total; + pet_input_files.push_back(input_file); + cout << " mean_time " << input_file.mean_time; + } + + cout << endl; + + handle->Close(); + delete handle; + all_pet_output &= is_pet_output; + } + cout << "all_pet_output " << all_pet_output << endl; + + if (all_pet_output) + { + GateMergeManager manager(args_info.fastmerge_given,args_info.verbose_arg,true,0,""); + + cout << "sorting input file using singles time" << endl; + std::sort(pet_input_files.begin(),pet_input_files.end(),sort_pet_input_file); + + Strings input_filenames; + for (PetInputFiles::const_iterator iter=pet_input_files.begin(); iter!=pet_input_files.end(); iter++) + input_filenames.push_back(iter->filename); + + manager.StartMergingFromFilenames(input_filenames,args_info.output_arg); + return 0; + } + } + + + // Merge + TFileMerger * merger = new TFileMerger; + for (uint i=0; iAddFile(args_info.input_arg[i]); + merger->OutputFile(args_info.output_arg); + merger->Merge(); + + // this is the end my friend + return 0; +} +//----------------------------------------------------------------------------- diff --git a/tools/clitkMergeRootFiles.ggo b/tools/clitkMergeRootFiles.ggo new file mode 100644 index 0000000..7baa396 --- /dev/null +++ b/tools/clitkMergeRootFiles.ggo @@ -0,0 +1,13 @@ +# -------------------------------------------- +# file clitkMergeRootFiles.ggo +package "clitkMergeRootFiles" +version "1.0" +purpose "Merge several ROOT files" +# -------------------------------------------- + +option "config" - "Config file" string no +option "input" i "Input ROOT filenames" string multiple yes +option "output" o "Output ROOT filename" string yes +option "fastmerge" f "Fast merge" optional +option "verbose" v "Verbose level" int optional + diff --git a/vv/vvMainWindow.cxx b/vv/vvMainWindow.cxx index 4210798..15e1d91 100644 --- a/vv/vvMainWindow.cxx +++ b/vv/vvMainWindow.cxx @@ -48,6 +48,7 @@ It is distributed under dual licence #include "vvSaveState.h" #include "vvReadState.h" #include "clitkConfiguration.h" +#include "clitkMatrix.h" // ITK include #include @@ -1145,7 +1146,7 @@ void vvMainWindow::ImageInfoChanged() infoPanel->setNPixel(QString::number(NPixel)+" ("+inputSizeInBytes+")"); transformation = imageSelected->GetTransform()[tSlice]->GetMatrix(); - infoPanel->setTransformation(Get4x4MatrixDoubleAsString(transformation)); + infoPanel->setTransformation(clitk::Get4x4MatrixDoubleAsString(transformation).c_str()); landmarksPanel->SetCurrentLandmarks(mSlicerManagers[index]->GetLandmarks(), mSlicerManagers[index]->GetTSlice()); @@ -1343,38 +1344,6 @@ QString vvMainWindow::GetSizeInBytes(unsigned long size) } //------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -QString vvMainWindow::Get4x4MatrixDoubleAsString(vtkSmartPointer matrix, const int precision) -{ - std::ostringstream strmatrix; - - // Figure out the number of digits of the integer part of the largest absolute value - // for each column - unsigned width[4]; - for (unsigned int j = 0; j < 4; j++){ - double absmax = 0.; - for (unsigned int i = 0; i < 4; i++) - absmax = std::max(absmax, vnl_math_abs(matrix->GetElement(i, j))); - unsigned ndigits = (unsigned)std::max(0.,std::log10(absmax))+1; - width[j] = precision+ndigits+3; - } - - // Output with correct width, aligned to the right - for (unsigned int i = 0; i < 4; i++) { - for (unsigned int j = 0; j < 4; j++) { - strmatrix.setf(ios::fixed,ios::floatfield); - strmatrix.precision(precision); - strmatrix.fill(' '); - strmatrix.width(width[j]); - strmatrix << std::right << matrix->GetElement(i, j); - } - strmatrix << std::endl; - } - QString result = strmatrix.str().c_str(); - return result; -} -//------------------------------------------------------------------------------ - //------------------------------------------------------------------------------ QString vvMainWindow::GetVectorDoubleAsString(std::vector vectorDouble) { diff --git a/vv/vvMainWindow.h b/vv/vvMainWindow.h index e5e3155..b093554 100644 --- a/vv/vvMainWindow.h +++ b/vv/vvMainWindow.h @@ -69,7 +69,6 @@ class vvMainWindow: public vvMainWindowBase, void SaveCurrentStateAs(const std::string& stateFile); void ReadSavedStateFile(const std::string& stateFile); void LinkAllImages(); - QString Get4x4MatrixDoubleAsString(vtkSmartPointer matrix, const int precision=3); virtual void UpdateCurrentSlicer(); virtual QTabWidget * GetTab(); diff --git a/vv/vvToolRigidReg.cxx b/vv/vvToolRigidReg.cxx index 508551d..2948165 100644 --- a/vv/vvToolRigidReg.cxx +++ b/vv/vvToolRigidReg.cxx @@ -30,6 +30,7 @@ // clitk #include "clitkTransformUtilities.h" +#include "clitkMatrix.h" // qt #include @@ -120,7 +121,7 @@ void vvToolRigidReg::InputIsSelected(vvSlicerManager *input) for(int i=0; i<4; i++) // TODO SR and BP: check on the list of transforms and not the first only mInitialMatrix->SetElement(i,j, mCurrentSlicerManager->GetImage()->GetTransform()[0]->GetMatrix()->GetElement(i,j)); - QString origTransformString = dynamic_cast(mMainWindow)->Get4x4MatrixDoubleAsString(mInitialMatrix); + QString origTransformString(clitk::Get4x4MatrixDoubleAsString(mInitialMatrix).c_str()); transformationLabel->setText(origTransformString); SetTransform(mInitialMatrix); @@ -298,7 +299,7 @@ void vvToolRigidReg::SaveFile() if (file.open(QFile::WriteOnly | QFile::Truncate)) { // TODO SR and BP: check on the list of transforms and not the first only vtkMatrix4x4* matrix = mCurrentSlicerManager->GetImage()->GetTransform()[0]->GetMatrix(); - QString matrixStr = dynamic_cast(mMainWindow)->Get4x4MatrixDoubleAsString(matrix,16); + QString matrixStr = clitk::Get4x4MatrixDoubleAsString(matrix,16).c_str(); QTextStream out(&file); out << matrixStr; }