[med-svn] [plastimatch] 02/06: New upstream version 1.6.6+dfsg.1
Greg Sharp
gregsharp-guest at moszumanska.debian.org
Wed Oct 11 17:24:38 UTC 2017
This is an automated email from the git hooks/post-receive script.
gregsharp-guest pushed a commit to branch master
in repository plastimatch.
commit 9a47d41b87aab60a17701754f66f3da273a27d0a
Author: Gregory C. Sharp <gregsharp.geo at yahoo.com>
Date: Wed Oct 11 12:47:19 2017 -0400
New upstream version 1.6.6+dfsg.1
---
CMakeLists.txt | 20 +-
INSTALL.TXT | 0
LICENSE.TXT | 0
README.TXT | 37 +-
Testing/CMakeLists.txt | 180 ++--
Testing/Data/plm-bsp-dmap-k.txt | 15 +
Testing/Data/plm-bsp-sm-multi-a.txt | 12 +-
Testing/Data/plm-reg-align-center.txt | 9 +-
Testing/Data/plm-reg-gw-a.txt | 8 +
Testing/Data/plm-reg-multi-a.txt | 1 -
Testing/Data/proton-dose-1.txt | 0
.../{proton-dose-5g.txt => proton-dose-5d.txt} | 36 +-
.../Data/{proton-dose-1.txt => proton-dose-7a.txt} | 42 +-
cmake/FindCUDA_wrap.cmake | 9 +
cmake/FindKaze.cmake | 35 +
cmake/FindPaxscan.cmake | 2 +-
doc/NOTES.TXT | 396 +++++++-
doc/STYLE_GUIDE_2.TXT | 35 +
doc/man/drr.1 | 2 +-
doc/man/fdk.1 | 6 +-
doc/man/landmark_warp.1 | 2 +-
doc/man/plastimatch.1 | 32 +-
run_lcov.sh | 7 -
src/CMakeLists.txt | 5 +
src/plastimatch/CHANGELOG.TXT | 10 +
src/plastimatch/CMakeLists.txt | 5 +-
src/plastimatch/COPYRIGHT.TXT | 0
src/plastimatch/Doxyfile.in | 0
src/plastimatch/base/CMakeLists.txt | 3 +
src/plastimatch/base/aperture.cxx | 82 +-
src/plastimatch/base/aperture.h | 11 +-
src/plastimatch/base/bspline_xform.cxx | 33 +-
src/plastimatch/base/bspline_xform.h | 10 +
src/plastimatch/base/dcmtk_config.h | 0
src/plastimatch/base/dcmtk_file.cxx | 8 +-
src/plastimatch/base/dcmtk_file.h | 0
src/plastimatch/base/dcmtk_image.cxx | 11 +-
src/plastimatch/base/dcmtk_metadata.cxx | 0
src/plastimatch/base/dcmtk_metadata.h | 0
src/plastimatch/base/dcmtk_module.cxx | 13 +-
src/plastimatch/base/dcmtk_rdd.cxx | 0
src/plastimatch/base/dcmtk_rdd.h | 0
src/plastimatch/base/dcmtk_rt_study.cxx | 0
src/plastimatch/base/dcmtk_rt_study.h | 1 +
src/plastimatch/base/dcmtk_rtdose.cxx | 5 +-
src/plastimatch/base/dcmtk_rtplan.cxx | 152 ++-
src/plastimatch/base/dcmtk_rtss.cxx | 7 +-
src/plastimatch/base/dcmtk_rtss.h | 0
src/plastimatch/base/dcmtk_series.cxx | 0
src/plastimatch/base/dcmtk_series.h | 2 +-
src/plastimatch/base/dcmtk_slice_data.h | 0
src/plastimatch/base/dcmtk_uid.cxx | 0
src/plastimatch/base/dcmtk_uid.h | 0
src/plastimatch/base/dcmtk_util.cxx | 6 +
src/plastimatch/base/dcmtk_util.h | 2 +
src/plastimatch/base/dicom.dic | 0
src/plastimatch/base/dicom_util.cxx | 0
src/plastimatch/base/dicom_util.h | 0
src/plastimatch/base/direction_cosines.cxx | 0
src/plastimatch/base/direction_cosines.h | 0
src/plastimatch/base/direction_matrices.cxx | 0
src/plastimatch/base/direction_matrices.h | 0
src/plastimatch/base/float_pair_list.cxx | 0
src/plastimatch/base/float_pair_list.h | 0
src/plastimatch/base/gaussian.cxx | 1 -
src/plastimatch/base/gaussian.h | 0
src/plastimatch/base/gdcm1_dose.cxx | 0
src/plastimatch/base/gdcm1_dose.h | 0
src/plastimatch/base/gdcm1_file.cxx | 0
src/plastimatch/base/gdcm1_file.h | 0
src/plastimatch/base/gdcm1_rdd.cxx | 0
src/plastimatch/base/gdcm1_rdd.h | 0
src/plastimatch/base/gdcm1_rtss.cxx | 0
src/plastimatch/base/gdcm1_rtss.h | 0
src/plastimatch/base/gdcm1_series.cxx | 0
src/plastimatch/base/gdcm1_series.h | 0
src/plastimatch/base/gdcm1_series_helper_2.cxx | 0
src/plastimatch/base/gdcm1_series_helper_2.h | 0
src/plastimatch/base/gdcm1_util.cxx | 0
src/plastimatch/base/gdcm1_util.h | 0
src/plastimatch/base/gdcm2_util.cxx | 0
src/plastimatch/base/gdcm2_util.h | 0
src/plastimatch/base/hnd_io.cxx | 2 +-
src/plastimatch/base/interpolate.cxx | 76 +-
src/plastimatch/base/interpolate.h | 23 +-
src/plastimatch/base/itkClampCastImageFilter.h | 0
src/plastimatch/base/itkClampCastImageFilter.txx | 0
src/plastimatch/base/itk_bbox.cxx | 50 +
src/plastimatch/base/{dcmtk_uid.h => itk_bbox.h} | 9 +-
src/plastimatch/base/itk_dicom_load.cxx | 0
src/plastimatch/base/itk_dicom_load.h | 0
src/plastimatch/base/itk_dicom_save.cxx | 0
src/plastimatch/base/itk_dicom_save.h | 0
src/plastimatch/base/itk_directions.cxx | 0
src/plastimatch/base/itk_directions.h | 0
src/plastimatch/base/itk_image_clone.cxx | 22 +-
src/plastimatch/base/itk_image_clone.h | 2 +
src/plastimatch/base/itk_image_load_char.cxx | 0
src/plastimatch/base/itk_image_load_double.cxx | 0
src/plastimatch/base/itk_image_type.h | 0
src/plastimatch/base/itk_metadata.cxx | 0
src/plastimatch/base/itk_metadata.h | 0
src/plastimatch/base/itk_pointset.cxx | 0
src/plastimatch/base/itk_pointset.h | 0
src/plastimatch/base/parameter_parser.cxx | 42 +-
src/plastimatch/base/parameter_parser.h | 12 +
src/plastimatch/base/plm_file_format.cxx | 0
src/plastimatch/base/plm_file_format.h | 0
src/plastimatch/base/plm_image_header.cxx | 13 +
src/plastimatch/base/plm_image_header.h | 2 +
src/plastimatch/base/plm_image_type.cxx | 0
src/plastimatch/base/proj_image.cxx | 6 +-
src/plastimatch/base/proj_matrix.cxx | 21 +-
src/plastimatch/base/proj_matrix.h | 14 +-
src/plastimatch/base/proj_volume.cxx | 51 +-
src/plastimatch/base/proj_volume.h | 23 +-
src/plastimatch/base/pwlut.cxx | 0
src/plastimatch/base/pwlut.h | 0
src/plastimatch/base/ray_trace.h | 7 +-
src/plastimatch/base/ray_trace_uniform.cxx | 6 -
src/plastimatch/base/rpl_volume.cxx | 1051 ++++++--------------
src/plastimatch/base/rpl_volume.h | 58 +-
src/plastimatch/base/rpl_volume_lut.cxx | 163 +++
src/plastimatch/base/rpl_volume_lut.h | 37 +
src/plastimatch/base/rt_study_metadata.cxx | 109 +-
src/plastimatch/base/rt_study_metadata.h | 24 +-
src/plastimatch/base/rt_study_p.h | 0
src/plastimatch/base/rtplan.cxx | 11 +
src/plastimatch/base/rtplan.h | 16 +
src/plastimatch/base/rtplan_beam.cxx | 43 +-
src/plastimatch/base/rtplan_beam.h | 30 +-
src/plastimatch/base/rtplan_control_pt.h | 0
src/plastimatch/base/rtss.cxx | 16 +-
src/plastimatch/base/slice_list.cxx | 0
src/plastimatch/base/slice_list.h | 0
src/plastimatch/base/thumbnail.cxx | 0
src/plastimatch/base/thumbnail.h | 0
src/plastimatch/base/vf.cxx | 0
src/plastimatch/base/vf_convolve.cxx | 0
src/plastimatch/base/volume.cxx | 2 +-
src/plastimatch/base/volume.h | 24 +-
src/plastimatch/base/volume_boundary_behavior.h | 24 +
src/plastimatch/base/volume_fill.cxx | 0
src/plastimatch/base/volume_fill.h | 0
src/plastimatch/base/volume_grad.cxx | 8 +-
src/plastimatch/base/volume_grad.h | 4 +-
src/plastimatch/base/volume_header.cxx | 11 +
src/plastimatch/base/volume_header.h | 2 +
src/plastimatch/base/volume_limit.h | 0
src/plastimatch/base/volume_macros.h | 0
src/plastimatch/base/volume_resample.cxx | 0
src/plastimatch/base/volume_stats.cxx | 0
src/plastimatch/base/volume_stats.h | 0
src/plastimatch/base/xform_convert.cxx | 0
src/plastimatch/base/xform_convert.h | 0
src/plastimatch/base/xform_legacy.cxx | 0
src/plastimatch/base/xform_legacy.h | 0
src/plastimatch/base/xio_ct.cxx | 0
src/plastimatch/base/xio_ct_transform.cxx | 0
src/plastimatch/base/xio_ct_transform.h | 0
src/plastimatch/base/xio_demographic.cxx | 0
src/plastimatch/base/xio_demographic.h | 0
src/plastimatch/base/xio_dir.cxx | 0
src/plastimatch/base/xio_patient.cxx | 0
src/plastimatch/base/xio_patient.h | 0
src/plastimatch/base/xio_structures.cxx | 0
src/plastimatch/cli/CMakeLists.txt | 5 +-
src/plastimatch/cli/pcmd_add.h | 0
src/plastimatch/cli/pcmd_adjust.cxx | 0
src/plastimatch/cli/pcmd_adjust.h | 0
src/plastimatch/cli/pcmd_autolabel.cxx | 0
src/plastimatch/cli/pcmd_autolabel.h | 0
src/plastimatch/cli/pcmd_autolabel_train.cxx | 0
src/plastimatch/cli/pcmd_autolabel_train.h | 0
src/plastimatch/cli/pcmd_bbox.cxx | 130 +++
src/plastimatch/cli/{pcmd_drr.h => pcmd_bbox.h} | 6 +-
src/plastimatch/cli/pcmd_benchmark.cxx | 0
src/plastimatch/cli/pcmd_benchmark.h | 0
src/plastimatch/cli/pcmd_boundary.cxx | 0
src/plastimatch/cli/pcmd_boundary.h | 0
src/plastimatch/cli/pcmd_compare.cxx | 0
src/plastimatch/cli/pcmd_compare.h | 0
src/plastimatch/cli/pcmd_compose.cxx | 0
src/plastimatch/cli/pcmd_compose.h | 0
src/plastimatch/cli/pcmd_crop.cxx | 0
src/plastimatch/cli/pcmd_crop.h | 0
src/plastimatch/cli/pcmd_dice.cxx | 0
src/plastimatch/cli/pcmd_dice.h | 0
src/plastimatch/cli/pcmd_diff.cxx | 0
src/plastimatch/cli/pcmd_diff.h | 0
src/plastimatch/cli/pcmd_dmap.cxx | 0
src/plastimatch/cli/pcmd_dmap.h | 0
src/plastimatch/cli/pcmd_dose.cxx | 33 +
src/plastimatch/cli/{pcmd_add.h => pcmd_dose.h} | 6 +-
src/plastimatch/cli/pcmd_drr.cxx | 0
src/plastimatch/cli/pcmd_drr.h | 0
src/plastimatch/cli/pcmd_dvh.cxx | 0
src/plastimatch/cli/pcmd_dvh.h | 0
src/plastimatch/cli/pcmd_filter.cxx | 0
src/plastimatch/cli/pcmd_filter.h | 0
src/plastimatch/cli/pcmd_gamma.cxx | 0
src/plastimatch/cli/pcmd_gamma.h | 0
src/plastimatch/cli/pcmd_header.cxx | 0
src/plastimatch/cli/pcmd_header.h | 0
src/plastimatch/cli/pcmd_mabs.cxx | 0
src/plastimatch/cli/pcmd_mabs.h | 0
src/plastimatch/cli/pcmd_mask.cxx | 0
src/plastimatch/cli/pcmd_mask.h | 0
src/plastimatch/cli/pcmd_probe.h | 0
src/plastimatch/cli/pcmd_register.cxx | 9 +-
src/plastimatch/cli/pcmd_scale.h | 0
src/plastimatch/cli/pcmd_segment.cxx | 0
src/plastimatch/cli/pcmd_segment.h | 0
src/plastimatch/cli/pcmd_sift.h | 0
src/plastimatch/cli/pcmd_stats.cxx | 0
src/plastimatch/cli/pcmd_stats.h | 0
src/plastimatch/cli/pcmd_synth.cxx | 0
src/plastimatch/cli/pcmd_synth.h | 0
src/plastimatch/cli/pcmd_synth_vf.cxx | 0
src/plastimatch/cli/pcmd_synth_vf.h | 0
src/plastimatch/cli/pcmd_threshold.cxx | 0
src/plastimatch/cli/pcmd_threshold.h | 0
src/plastimatch/cli/pcmd_thumbnail.cxx | 0
src/plastimatch/cli/pcmd_thumbnail.h | 0
src/plastimatch/cli/pcmd_union.h | 0
.../vf_invert_main.cxx => cli/pcmd_vf_invert.cxx} | 51 +-
.../cli/{pcmd_add.h => pcmd_vf_invert.h} | 6 +-
src/plastimatch/cli/pcmd_warp.cxx | 0
src/plastimatch/cli/pcmd_warp.h | 0
src/plastimatch/cli/pcmd_warp_pointset.cxx | 0
src/plastimatch/cli/pcmd_xf_convert.cxx | 0
src/plastimatch/cli/pcmd_xf_convert.h | 0
src/plastimatch/cli/pcmd_xio_dvh.cxx | 0
src/plastimatch/cli/pcmd_xio_dvh.h | 0
src/plastimatch/cli/plastimatch_main.cxx | 30 +-
src/plastimatch/clp/CMakeLists.txt | 0
src/plastimatch/clp/plm_clp.cxx | 0
src/plastimatch/clp/plm_clp.h | 0
src/plastimatch/cuda/cuda_probe.h | 0
src/plastimatch/dose/CMakeLists.txt | 27 +-
src/plastimatch/dose/dose_volume_functions.cxx | 115 ++-
src/plastimatch/dose/dose_volume_functions.h | 4 +-
src/plastimatch/dose/rt_beam.cxx | 1006 +++++++++++++++----
src/plastimatch/dose/rt_beam.h | 114 ++-
.../{util/gabor.h => dose/rt_beam_model.cxx} | 29 +-
src/plastimatch/dose/rt_beam_model.h | 21 +
src/plastimatch/dose/rt_depth_dose.cxx | 180 ++--
src/plastimatch/dose/rt_depth_dose.h | 24 +-
src/plastimatch/dose/rt_dij.cxx | 57 ++
src/plastimatch/dose/rt_dij.h | 48 +
src/plastimatch/dose/rt_dose.cxx | 1033 ++++++++-----------
src/plastimatch/dose/rt_dose.h | 28 +-
src/plastimatch/dose/rt_dose_timing.h | 39 +
src/plastimatch/dose/rt_lut.cxx | 36 +-
src/plastimatch/dose/rt_mebs.cxx | 308 +++---
src/plastimatch/dose/rt_mebs.h | 49 +-
src/plastimatch/dose/rt_parms.cxx | 80 +-
src/plastimatch/dose/rt_parms.h | 3 +
src/plastimatch/dose/rt_plan.cxx | 848 ++++++----------
src/plastimatch/dose/rt_plan.h | 24 +-
src/plastimatch/dose/rt_sigma.cxx | 264 ++---
src/plastimatch/dose/rt_sigma.h | 12 +-
src/plastimatch/dose/rt_spot_map.cxx | 55 +
src/plastimatch/dose/rt_spot_map.h | 43 +
src/plastimatch/dose/wed_parms.h | 7 +-
src/plastimatch/opencl/CMakeLists.txt | 0
src/plastimatch/opencl/autotune_opencl.cxx | 0
src/plastimatch/opencl/autotune_opencl.h | 0
src/plastimatch/reconstruct/drr.cxx | 7 +-
src/plastimatch/reconstruct/drr_opencl.cxx | 5 -
src/plastimatch/reconstruct/fdk.cxx | 2 +-
src/plastimatch/register/CMakeLists.txt | 76 +-
src/plastimatch/register/bspline.cxx | 149 +--
src/plastimatch/register/bspline.h | 3 +-
src/plastimatch/register/bspline_gm.h | 0
src/plastimatch/register/bspline_gm.txx | 6 +-
src/plastimatch/register/bspline_loop.txx | 34 +-
src/plastimatch/register/bspline_mi.cxx | 365 ++-----
src/plastimatch/register/bspline_mi.h | 0
src/plastimatch/register/bspline_mi.txx | 16 +-
src/plastimatch/register/bspline_mi_hist.h | 77 --
src/plastimatch/register/bspline_mse.cxx | 55 +-
src/plastimatch/register/bspline_mse.h | 0
src/plastimatch/register/bspline_mse.txx | 13 +-
src/plastimatch/register/bspline_optimize.cxx | 84 +-
src/plastimatch/register/bspline_optimize.h | 10 +-
.../register/bspline_optimize_lbfgsb.cxx | 14 +-
.../register/bspline_optimize_liblbfgs.cxx | 2 +-
.../register/bspline_optimize_nlopt.cxx | 2 +-
.../register/bspline_optimize_steepest.cxx | 47 +-
src/plastimatch/register/bspline_parms.cxx | 18 +-
src/plastimatch/register/bspline_parms.h | 58 +-
src/plastimatch/register/bspline_regularize.cxx | 2 -
src/plastimatch/register/bspline_regularize.h | 2 -
src/plastimatch/register/bspline_score.cxx | 43 +-
src/plastimatch/register/bspline_score.h | 40 +-
src/plastimatch/register/bspline_stage.cxx | 277 +++---
src/plastimatch/register/bspline_stage.h | 2 -
src/plastimatch/register/bspline_state.cxx | 218 ++--
src/plastimatch/register/bspline_state.h | 35 +-
src/plastimatch/register/cuda/CMakeLists.txt | 3 -
src/plastimatch/register/cuda/bspline_cuda.cu | 19 +-
src/plastimatch/register/cuda/bspline_cuda.cxx | 60 +-
src/plastimatch/register/cuda/bspline_cuda.h | 10 +-
src/plastimatch/register/gpuit_demons.cxx | 6 +-
.../register/{bspline_gm.h => groupwise_parms.cxx} | 13 +-
.../register/{bspline_gm.h => groupwise_parms.h} | 12 +-
src/plastimatch/register/histogram.cxx | 33 +
src/plastimatch/register/histogram.h | 38 +
src/plastimatch/register/itk_align_center.cxx | 23 +-
src/plastimatch/register/itk_demons.cxx | 81 +-
src/plastimatch/register/itk_registration.cxx | 71 +-
.../register/itk_registration_observer.cxx | 25 +-
.../{bspline_mi_hist.cxx => joint_histogram.cxx} | 260 ++++-
src/plastimatch/register/joint_histogram.h | 50 +
src/plastimatch/register/landmark_warp.cxx | 2 +-
src/plastimatch/register/metric_parms.cxx | 54 +
src/plastimatch/register/metric_parms.h | 28 +
.../{translation_mse.h => metric_state.cxx} | 36 +-
src/plastimatch/register/metric_state.h | 39 +
src/plastimatch/register/process_parms.cxx | 12 +-
src/plastimatch/register/rbf_gauss.cxx | 19 +-
src/plastimatch/register/registration.cxx | 65 +-
src/plastimatch/register/registration.h | 4 +-
src/plastimatch/register/registration_data.cxx | 282 +++++-
src/plastimatch/register/registration_data.h | 55 +-
.../register/registration_metric_type.h | 18 -
src/plastimatch/register/registration_parms.cxx | 230 +----
src/plastimatch/register/registration_parms.h | 16 +-
src/plastimatch/register/registration_resample.cxx | 0
src/plastimatch/register/registration_resample.h | 0
.../register/registration_similarity_data.h | 24 +
src/plastimatch/register/registration_util.cxx | 44 +
...registration_resample.h => registration_util.h} | 17 +-
src/plastimatch/register/shared_parms.cxx | 17 +
src/plastimatch/register/shared_parms.h | 8 +-
..._metric_type.cxx => similarity_metric_type.cxx} | 18 +-
src/plastimatch/register/similarity_metric_type.h | 19 +
src/plastimatch/register/stage_parms.cxx | 4 -
src/plastimatch/register/stage_parms.h | 9 +-
.../register/translation_grid_search.cxx | 180 ++--
src/plastimatch/register/translation_mi.cxx | 21 +-
src/plastimatch/register/translation_mi.h | 3 +-
src/plastimatch/register/translation_mse.cxx | 8 +-
src/plastimatch/register/translation_mse.h | 3 +-
src/plastimatch/segment/autolabel_parms.cxx | 4 +-
src/plastimatch/segment/autolabel_parms.h | 1 +
src/plastimatch/segment/mabs.cxx | 12 +-
src/plastimatch/segment/mabs.h | 0
src/plastimatch/segment/mabs_atlas_selection.cxx | 4 +-
src/plastimatch/segment/mabs_parms.cxx | 2 +
src/plastimatch/segment/mabs_stats.cxx | 0
src/plastimatch/segment/mabs_stats.h | 0
src/plastimatch/standalone/CMakeLists.txt | 6 -
src/plastimatch/standalone/YKThreadRegi.cpp | 4 -
src/plastimatch/standalone/bspline_main.cxx | 49 +-
src/plastimatch/standalone/bspline_opts.cxx | 5 +-
src/plastimatch/standalone/bspline_opts.h | 3 +
src/plastimatch/standalone/check_grad.cxx | 37 +-
src/plastimatch/standalone/dlib_train.cxx | 0
src/plastimatch/standalone/drr_main.cxx | 6 +-
src/plastimatch/standalone/gamma_gui.cpp | 317 ++++++
src/plastimatch/standalone/gamma_gui.h | 3 +
src/plastimatch/standalone/gamma_gui.ui | 23 +
src/plastimatch/standalone/hnd_to_pfm.cxx | 0
src/plastimatch/standalone/opencl_probe.cxx | 0
src/plastimatch/standalone/opencl_probe.h | 0
src/plastimatch/standalone/qt_util.cxx | 2 +-
src/plastimatch/standalone/qt_util.h | 2 +-
src/plastimatch/standalone/shuffle_mha_main.cxx | 0
src/plastimatch/standalone/sobp_main.cxx | 18 +-
src/plastimatch/standalone/vf_invert_main.cxx | 0
src/plastimatch/sys/CMakeLists.txt | 5 +-
src/plastimatch/sys/compiler_warnings.h | 0
src/plastimatch/sys/dlib_threads.cxx | 0
src/plastimatch/sys/dlib_threads.h | 0
src/plastimatch/sys/logfile.cxx | 0
src/plastimatch/sys/plm_endian.cxx | 0
src/plastimatch/sys/plm_macros.h | 0
src/plastimatch/sys/plm_math.h | 29 +-
src/plastimatch/sys/plm_return_code.h | 0
src/plastimatch/sys/plm_sleep.cxx | 0
src/plastimatch/sys/plm_sleep.h | 0
src/plastimatch/sys/plm_timer.cxx | 7 +
src/plastimatch/sys/plm_timer.h | 1 +
src/plastimatch/sys/smart_pointer.h | 0
src/plastimatch/sys/string_util.cxx | 37 +-
src/plastimatch/sys/string_util.h | 6 +-
src/plastimatch/test/api_test.cxx | 0
src/plastimatch/test/cpp_eps_test.cxx | 0
src/plastimatch/test/cpp_limits_test.cxx | 0
src/plastimatch/test/cpp_overflow_test.cxx | 0
src/plastimatch/test/cpp_sizeof_test.cxx | 0
src/plastimatch/test/cpp_template_test.cxx | 17 +-
src/plastimatch/test/cuda/cuda_test.cu | 19 +-
src/plastimatch/test/dcmtk_test.cxx | 0
src/plastimatch/test/dlib_test.cxx | 0
src/plastimatch/test/dlib_thread_test.cxx | 0
src/plastimatch/test/gabor_test.cxx | 0
src/plastimatch/test/itk_test.cxx | 0
src/plastimatch/test/itk_test_directions.cxx | 0
src/plastimatch/test/itk_thread_test.cxx | 0
src/plastimatch/test/libyaml_test.cxx | 0
src/plastimatch/test/plm_restart_test.cxx | 0
src/plastimatch/test/rapidjson_test.cxx | 0
src/plastimatch/test/rtplan_test.cxx | 0
src/plastimatch/test/smartp_test_i.cxx | 0
src/plastimatch/test/smartp_test_ii.cxx | 0
src/plastimatch/test/yamlcpp_test.cxx | 0
src/plastimatch/util/CMakeLists.txt | 5 +-
src/plastimatch/util/dicom_sro_save.cxx | 0
src/plastimatch/util/dicom_sro_save.h | 0
src/plastimatch/util/distance_map.cxx | 26 +-
src/plastimatch/util/distance_map.h | 7 +
src/plastimatch/util/gabor.cxx | 0
src/plastimatch/util/gabor.h | 0
src/plastimatch/util/hausdorff_distance.cxx | 13 +-
src/plastimatch/util/hausdorff_distance.h | 4 +
src/plastimatch/util/image_boundary.cxx | 45 +-
src/plastimatch/util/image_boundary.h | 15 +-
src/plastimatch/util/image_center.cxx | 0
src/plastimatch/util/image_center.h | 0
src/plastimatch/util/itk_adjust.cxx | 73 --
src/plastimatch/util/itk_distance_map.cxx | 0
src/plastimatch/util/itk_threshold.cxx | 0
src/plastimatch/util/itk_threshold.h | 0
src/plastimatch/util/vf_invert.cxx | 0
src/plastimatch/util/vf_invert.h | 0
src/plastimatch/util/volume_adjust.cxx | 40 +
src/plastimatch/util/volume_adjust.h | 15 +
430 files changed, 7503 insertions(+), 4957 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a51daaa..d52f0a9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,7 +8,7 @@ project (plastimatch)
## The version here should be equal to the "next release"
set (PLM_VERSION_MAJOR "1")
set (PLM_VERSION_MINOR "6")
-set (PLM_VERSION_PATCH "5")
+set (PLM_VERSION_PATCH "6")
#set (PLM_RELEASE_VERSION FALSE)
set (PLM_RELEASE_VERSION TRUE)
@@ -307,6 +307,7 @@ find_package (Etags)
#find_package (Fann)
find_package (FFTW)
find_package (Git)
+find_package (Kaze)
find_package (Liblbfgs)
find_package (NLopt)
if (PLM_CONFIG_ENABLE_MATLAB)
@@ -365,10 +366,17 @@ add_subdirectory (libs/devillard)
##-----------------------------------------------------------------------------
## If using local dlib
##-----------------------------------------------------------------------------
-if (NOT DLIB_FOUND)
- set (DLIB_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/libs/dlib-19.1")
- set (DLIB_LIBRARIES "")
- set (DLIB_HAVE_LIBRARY FALSE)
+if (dlib_FOUND)
+ set (DLIB_INCLUDE_DIR ${dlib_INCLUDE_DIR})
+ set (DLIB_LIBRARIES ${dlib_LIBRARIES})
+ set (DLIB_FOUND TRUE)
+endif ()
+if (DLIB_FOUND)
+ set (DLIB_HAVE_LIBRARY TRUE)
+else ()
+ set (DLIB_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/libs/dlib-19.1")
+ set (DLIB_LIBRARIES "")
+ set (DLIB_HAVE_LIBRARY FALSE)
endif ()
##-----------------------------------------------------------------------------
@@ -987,7 +995,7 @@ if (PLM_BUILD_TESTING)
# Copy the lconv script
configure_file (
- "${CMAKE_SOURCE_DIR}/run_lcov.sh"
+ "${CMAKE_SOURCE_DIR}/extra/devtools/run_lcov.sh"
"${CMAKE_BINARY_DIR}/run_lcov.sh"
COPYONLY)
endif ()
diff --git a/INSTALL.TXT b/INSTALL.TXT
old mode 100755
new mode 100644
diff --git a/LICENSE.TXT b/LICENSE.TXT
old mode 100755
new mode 100644
diff --git a/README.TXT b/README.TXT
old mode 100755
new mode 100644
index 5afbf4f..8c25387
--- a/README.TXT
+++ b/README.TXT
@@ -1,33 +1,30 @@
*** Welcome to Plastimatch ***
-Plastimatch is a collection of command-line deformable registration
-software programs, which can be used for anatomic matching of 3D data sets.
-The main features include:
+Plastimatch is a computer software application which has been designed
+for volumetric (usually medical) image processing and
+radiation therapy therapy applications. It can be used
+for the following purposes:
- 1) Image conversion routines
- 2) Patient masking
- 3) B-Spline registration
- 4) Demons registration
- 5) Image warping
+ 1) Deformable registration
+ 2) Atlas-based segmentation
+ 3) Image conversion and manipulation
+ 4) Vector field conversion and manipulation
+ 5) Gamma analysis
+ 6) Dose calculation
+ 7) Registration analysis (Jacobian)
+ 8) Segmentation analysis (Dice, Hausdorff)
+ 9) Many other things
-In addition, plastimatch includes routines for:
+For online documentation, please visit:
- 1) FDK cone-beam
- 2) DRR generation
+http://plastimatch.org
+Questions, comments, bug reports? Please post:
-For help on installing plastimatch, please read INSTALL.TXT.
-
-For help on using plastimatch, please read PLASTIMATCH.ODT.
-
-An example parameter file is included as REGISTRATION.TXT.
+https://groups.google.com/d/forum/plastimatch
Plastimatch is open source software, and can be used, modified, and
distributed, without cost, under a BSD-style license. This software is
intended for research use only, and is not approved by the Food and
Drug Administration (FDA) for clinical use. Please see LICENSE.TXT
for details.
-
-Questions, comments, bug reports? Please send to:
- Greg Sharp, MGH Radiation Oncology
- <gcsharp A at T partners dot org>
diff --git a/Testing/CMakeLists.txt b/Testing/CMakeLists.txt
index 235fcf6..13a9e60 100755
--- a/Testing/CMakeLists.txt
+++ b/Testing/CMakeLists.txt
@@ -31,6 +31,7 @@ set (CONFIG_FILE_LIST
"plm-bsp-mi-c.txt"
"plm-bsp-mi-k.txt"
"plm-bsp-gm-k.txt"
+ "plm-bsp-dmap-k.txt"
"plm-bsp-sm-multi-a.txt"
"plm-bsp-cuda.txt"
"plm-bsp-rect.txt"
@@ -49,6 +50,7 @@ set (CONFIG_FILE_LIST
"plm-bsp-landmark-e.txt"
"plm-bsp-double.txt"
"plm-bsp-regularize-numeric.txt"
+ "plm-reg-align-center.txt"
"plm-reg-itk-translation.txt"
"plm-reg-roi-a.txt"
"plm-reg-roi-b.txt"
@@ -69,12 +71,12 @@ set (CONFIG_FILE_LIST
"plm-reg-trans-mi-a.txt"
"plm-reg-autores-a.txt"
"plm-reg-autores-b.txt"
+ "plm-reg-gw-a.txt"
"proton-dose-1.txt"
"proton-dose-2.txt"
- "proton-dose-3.txt"
"proton-dose-4.txt"
"proton-dose-5a.txt"
- "proton-dose-5g.txt"
+ "proton-dose-5d.txt"
"proton-dose-6a.txt"
"speedtest-a.txt"
"wed-a.txt"
@@ -243,6 +245,9 @@ add_custom_target (speedtest
## gauss-ushort-2 Off-center gauss, ushort
## lung-1 Synthetic lung, tumor position 0
## lung-2 Synthetic lung, tumor position -5
+## gw-lung-a Synthetic lung, tumor position -5, in gw dir
+## gw-lung-b Synthetic lung, tumor position 0, in gw dir
+## gw-lung-c Synthetic lung, tumor position +5, in gw dir
## ptv-1 rect PTV target for dose calculation
## ptv-2 rect PTV target for dose calculation, smaller geometry
## rect-1 Inverted rect, centered
@@ -254,6 +259,11 @@ add_custom_target (speedtest
## rect-7 Standard rect, centered, direction cosines alt-3
## rect-8 Uchar rect, off-center
## rect-9 Uchar rect, centered, higher resolution
+## rect-10-roi-1
+## rect-10-roi-2
+## rect-10
+## rect-11
+## rect-11-roi
## rect-12 Small rect, bg=0, fg=10
## rect-13 Small rect, bg=0, fg=11
## rect-14 Small, off-center rect, bg=0, fg=10
@@ -285,7 +295,7 @@ plm_add_test (
plm_add_test (
"donut-1"
${PLM_PLASTIMATCH_PATH}/plastimatch
- "synth;--output;${PLM_BUILD_TESTING_DIR}/donut-1.mha;--output-ss-img;${PLM_BUILD_TESTING_DIR}/donut-1-ss.mha;--output-ss-list;${PLM_BUILD_TESTING_DIR}/donut-1-ss-list.txt;--output-type;float;--pattern;donut;--origin;-25 -25 -25;--dim;${SYNTH_MHA_SIZE} ${SYNTH_MHA_SIZE} ${SYNTH_MHA_SIZE};--volume-size;50 50 50;--donut-radius;10 10 10;--background;-1000;--foreground;0;--output-dicom;${PLM_BUILD_TESTING_DIR}/donut-1-dicom;--output-prefix;${PLM_BUILD_TESTING_DIR}/donut-1-prefix/"
+ "synth;--output;${PLM_BUILD_TESTING_DIR}/donut-1.mha;--output-ss-img;${PLM_BUILD_TESTING_DIR}/donut-1-ss.mha;--output-ss-list;${PLM_BUILD_TESTING_DIR}/donut-1-ss-list.txt;--output-type;float;--pattern;donut;--origin;-25 -25 -25;--dim;${SYNTH_MHA_SIZE} ${SYNTH_MHA_SIZE} ${SYNTH_MHA_SIZE};--volume-size;50 50 50;--donut-radius;10 10 10;--background;-1000;--foreground;0;--dicom-with-uids;false;--output-dicom;${PLM_BUILD_TESTING_DIR}/donut-1-dicom;--output-prefix;${PLM_BUILD_TESTING_DIR}/do [...]
)
plm_add_test (
"gabor-01"
@@ -358,6 +368,21 @@ plm_add_test (
"synth;--dicom-with-uids;false;--output;${PLM_BUILD_TESTING_DIR}/lung-2.mha;--output-dicom;${PLM_BUILD_TESTING_DIR}/lung-2-dicom;--pattern;lung;--lung-tumor-pos;-5"
)
plm_add_test (
+ "gw-lung-a"
+ ${PLM_PLASTIMATCH_PATH}/plastimatch
+ "synth;--output;${PLM_BUILD_TESTING_DIR}/gw/lung-a.mha;--pattern;lung;--lung-tumor-pos;-5"
+ )
+plm_add_test (
+ "gw-lung-b"
+ ${PLM_PLASTIMATCH_PATH}/plastimatch
+ "synth;--output;${PLM_BUILD_TESTING_DIR}/gw/lung-b.mha;--pattern;lung;--lung-tumor-pos;0"
+ )
+plm_add_test (
+ "gw-lung-c"
+ ${PLM_PLASTIMATCH_PATH}/plastimatch
+ "synth;--output;${PLM_BUILD_TESTING_DIR}/gw/lung-c.mha;--pattern;lung;--lung-tumor-pos;5"
+ )
+plm_add_test (
"ptv-1"
${PLM_PLASTIMATCH_PATH}/plastimatch
"synth;--output;${PLM_BUILD_TESTING_DIR}/ptv-1.mha;--pattern;rect;--dim;60 60 60;--background;0;--foreground;6;--rect-size;20 20 20;--origin;-150 -150 -150;--spacing;5 5 5"
@@ -2301,7 +2326,7 @@ set (PLM_BSPLINE_TEST_UPPER_THRESH "-744.5")
plm_add_test (
"plm-reg-align-center"
${PLM_PLASTIMATCH_PATH}/plastimatch
- "${PLM_TESTING_DATA_DIR}/plm-reg-align-center.txt"
+ "${PLM_BUILD_TESTING_DIR}/plm-reg-align-center.txt"
)
plm_add_test (
"plm-reg-align-center-stats"
@@ -2722,6 +2747,29 @@ set_tests_properties (plm-bsp-gm-k-stats PROPERTIES
set_tests_properties (plm-bsp-gm-k-check PROPERTIES
DEPENDS plm-bsp-gm-k-stats)
+# plm_add_test (
+# "plm-bsp-dmap-k"
+# ${PLM_PLASTIMATCH_PATH}/plastimatch
+# "${PLM_BUILD_TESTING_DIR}/plm-bsp-dmap-k.txt"
+# )
+# plm_add_test (
+# "plm-bsp-dmap-k-stats"
+# ${PLM_PLASTIMATCH_PATH}/plastimatch
+# "stats;${PLM_BUILD_TESTING_DIR}/plm-bsp-dmap-k-img.mha"
+# )
+# plmtest_check_interval ("plm-bsp-dmap-k-check"
+# "${PLM_BUILD_TESTING_DIR}/plm-bsp-dmap-k-stats.stdout.txt"
+# "AVE *([-0-9.]*)"
+# "-122.5"
+# "-121.5"
+# )
+# set_property (TEST plm-bsp-dmap-k APPEND PROPERTY DEPENDS rect-4)
+# set_property (TEST plm-bsp-dmap-k APPEND PROPERTY DEPENDS rect-8)
+# set_tests_properties (plm-bsp-dmap-k-stats PROPERTIES
+# DEPENDS plm-bsp-dmap-k)
+# set_tests_properties (plm-bsp-dmap-k-check PROPERTIES
+# DEPENDS plm-bsp-dmap-k-stats)
+
plm_add_test (
"plm-bsp-sm-multi-a"
${PLM_PLASTIMATCH_PATH}/plastimatch
@@ -3540,6 +3588,16 @@ set_tests_properties (plm-reg-autores-b-check PROPERTIES
DEPENDS plm-reg-autores-b-stats)
## -------------------------------------------------------------------------
+## plastimatch register (group 12)
+## plm-reg-gw-a Groupwise registration
+## -------------------------------------------------------------------------
+# plm_add_test (
+# "plm-reg-gw-a"
+# ${PLM_PLASTIMATCH_PATH}/plastimatch
+# "${PLM_BUILD_TESTING_DIR}/plm-reg-gw-a.txt"
+# )
+
+## -------------------------------------------------------------------------
## plastimatch compose
## This test uses registers from gauss-1 to gauss-2 which are done above,
## and composes with results from an registration from gauss-2 to
@@ -3640,7 +3698,7 @@ plmtest_check_interval ("plm-compose-c-check"
"12.6"
)
set_tests_properties (plm-compose-c PROPERTIES
- DEPENDS "plm-reg-itk-translation;plm-reg-compose")
+ DEPENDS "gauss-5;plm-bsp-mse-h;plm-reg-compose")
set_tests_properties (plm-compose-c-warp PROPERTIES DEPENDS plm-compose-c)
set_tests_properties (plm-compose-c-stats PROPERTIES DEPENDS plm-compose-c)
set_tests_properties (plm-compose-c-check PROPERTIES
@@ -4248,8 +4306,8 @@ set_tests_properties (plm-xf-convert-f PROPERTIES DEPENDS "rect-2;rect-3")
## -------------------------------------------------------------------------
plm_add_test (
"vf-invert-zero-1"
- ${PLM_PLASTIMATCH_PATH}/vf_invert
- "--input;${PLM_BUILD_TESTING_DIR}/vf-zero.mha;--fixed;${PLM_BUILD_TESTING_DIR}/vf-zero.mha;--output;${PLM_BUILD_TESTING_DIR}/vf-invert-zero-1.mha"
+ ${PLM_PLASTIMATCH_PATH}/plastimatch
+ "vf-invert;--input;${PLM_BUILD_TESTING_DIR}/vf-zero.mha;--fixed;${PLM_BUILD_TESTING_DIR}/vf-zero.mha;--output;${PLM_BUILD_TESTING_DIR}/vf-invert-zero-1.mha"
)
plm_add_test (
"vf-invert-zero-1-stats"
@@ -4270,8 +4328,8 @@ set_tests_properties (vf-invert-zero-1-check
plm_add_test (
"vf-invert-trans-1"
- ${PLM_PLASTIMATCH_PATH}/vf_invert
- "--input;${PLM_BUILD_TESTING_DIR}/vf-trans-1.mha;--fixed;${PLM_BUILD_TESTING_DIR}/vf-trans-1.mha;--output;${PLM_BUILD_TESTING_DIR}/vf-invert-trans-1.mha;--iterations;10"
+ ${PLM_PLASTIMATCH_PATH}/plastimatch
+ "vf-invert;--input;${PLM_BUILD_TESTING_DIR}/vf-trans-1.mha;--fixed;${PLM_BUILD_TESTING_DIR}/vf-trans-1.mha;--output;${PLM_BUILD_TESTING_DIR}/vf-invert-trans-1.mha;--iterations;10"
)
plm_add_test (
"vf-invert-trans-1-stats"
@@ -4293,13 +4351,8 @@ set_tests_properties (vf-invert-trans-1-check
## -------------------------------------------------------------------------
## bragg-curve
## proton-dose-1 Flavor a, sobp
-## proton-dose-2 Flavor f, single bragg peak, target, autom. rgcomp
-## proton-dose-3 Flavor g, multiple beam
-## proton-dose-4 Flavor h, load range comp file
## proton-dose-5a Flavor a, sobp target with aperture and rgc
-## proton-dose-5f Flavor f, sobp target with aperture and rgc
-## proton-dose-5g Flavor g, sobp target with aperture and rgc
-## proton-dose-5h Flavor h, sobp target with aperture and rgc
+## proton-dose-5d Flavor d, sobp target with aperture and rgc
## proton-dose-6a Flavor a, target geometry differs from CT geometry
## -------------------------------------------------------------------------
plm_add_test (
@@ -4314,8 +4367,8 @@ set_tests_properties (bragg-curve-check PROPERTIES DEPENDS bragg-curve)
plm_add_test (
"proton-dose-1"
- ${PLM_PLASTIMATCH_PATH}/proton_dose
- "${PLM_BUILD_TESTING_DIR}/proton-dose-1.txt"
+ ${PLM_PLASTIMATCH_PATH}/plastimatch
+ "dose;${PLM_BUILD_TESTING_DIR}/proton-dose-1.txt"
)
plm_add_test (
"proton-dose-1-stats"
@@ -4335,64 +4388,9 @@ set_tests_properties (proton-dose-1-check
PROPERTIES DEPENDS proton-dose-1-stats)
plm_add_test (
- "proton-dose-2"
- ${PLM_PLASTIMATCH_PATH}/proton_dose
- "${PLM_BUILD_TESTING_DIR}/proton-dose-2.txt"
- )
-plm_add_test (
- "proton-dose-2-stats"
- ${PLM_PLASTIMATCH_PATH}/plastimatch
- "stats;${PLM_BUILD_TESTING_DIR}/proton-dose-2.mha"
- )
-plmtest_check_interval ("proton-dose-2-check"
- "${PLM_BUILD_TESTING_DIR}/proton-dose-2-stats.stdout.txt"
- "AVE *([-0-9.]*)"
- "0.10"
- "0.12"
- )
-set_tests_properties (proton-dose-2 PROPERTIES DEPENDS rect-17)
-set_tests_properties (proton-dose-2 PROPERTIES DEPENDS ptv-1)
-set_tests_properties (proton-dose-2-stats
- PROPERTIES DEPENDS proton-dose-2)
-set_tests_properties (proton-dose-2-check
- PROPERTIES DEPENDS proton-dose-2-stats)
-
-plm_add_test (
- "proton-dose-3"
- ${PLM_PLASTIMATCH_PATH}/proton_dose
- "${PLM_BUILD_TESTING_DIR}/proton-dose-3.txt"
- )
-plm_add_test (
- "proton-dose-3-stats"
- ${PLM_PLASTIMATCH_PATH}/plastimatch
- "stats;${PLM_BUILD_TESTING_DIR}/proton-dose-3.mha"
- )
-plmtest_check_interval ("proton-dose-3-check"
- "${PLM_BUILD_TESTING_DIR}/proton-dose-3-stats.stdout.txt"
- "AVE *([-0-9.]*)"
- "0.21"
- "0.22"
- )
-set_tests_properties (proton-dose-3 PROPERTIES DEPENDS rect-17)
-set_tests_properties (proton-dose-3 PROPERTIES DEPENDS ptv-1)
-set_tests_properties (proton-dose-3-stats
- PROPERTIES DEPENDS proton-dose-3)
-set_tests_properties (proton-dose-3-check
- PROPERTIES DEPENDS proton-dose-3-stats)
-
-## This seems to not work, gives zero dose.
-#plm_add_test (
-# "proton-dose-4"
-# ${PLM_PLASTIMATCH_PATH}/proton_dose
-# "${PLM_BUILD_TESTING_DIR}/proton-dose-4.txt"
-# )
-#set_tests_properties (proton-dose-4 PROPERTIES DEPENDS rect-18)
-#set_tests_properties (proton-dose-4 PROPERTIES DEPENDS rgc-1)
-
-plm_add_test (
"proton-dose-5a"
- ${PLM_PLASTIMATCH_PATH}/proton_dose
- "${PLM_BUILD_TESTING_DIR}/proton-dose-5a.txt"
+ ${PLM_PLASTIMATCH_PATH}/plastimatch
+ "dose;${PLM_BUILD_TESTING_DIR}/proton-dose-5a.txt"
)
plm_add_test (
"proton-dose-5a-stats"
@@ -4413,32 +4411,32 @@ set_tests_properties (proton-dose-5a-check
PROPERTIES DEPENDS proton-dose-5a-stats)
plm_add_test (
- "proton-dose-5g"
- ${PLM_PLASTIMATCH_PATH}/proton_dose
- "${PLM_BUILD_TESTING_DIR}/proton-dose-5g.txt"
+ "proton-dose-5d"
+ ${PLM_PLASTIMATCH_PATH}/plastimatch
+ "dose;${PLM_BUILD_TESTING_DIR}/proton-dose-5d.txt"
)
plm_add_test (
- "proton-dose-5g-stats"
+ "proton-dose-5d-stats"
${PLM_PLASTIMATCH_PATH}/plastimatch
- "stats;${PLM_BUILD_TESTING_DIR}/proton-dose-5g.mha"
+ "stats;${PLM_BUILD_TESTING_DIR}/proton-dose-5d.mha"
)
-plmtest_check_interval ("proton-dose-5g-check"
- "${PLM_BUILD_TESTING_DIR}/proton-dose-5g-stats.stdout.txt"
+plmtest_check_interval ("proton-dose-5d-check"
+ "${PLM_BUILD_TESTING_DIR}/proton-dose-5d-stats.stdout.txt"
"AVE *([-0-9.]*)"
- "0.365"
- "0.375"
+ "0.38"
+ "0.39"
)
-set_tests_properties (proton-dose-5g PROPERTIES DEPENDS rect-17)
-set_tests_properties (proton-dose-5g PROPERTIES DEPENDS ptv-1)
-set_tests_properties (proton-dose-5g-stats
- PROPERTIES DEPENDS proton-dose-5g)
-set_tests_properties (proton-dose-5g-check
- PROPERTIES DEPENDS proton-dose-5g-stats)
+set_tests_properties (proton-dose-5d PROPERTIES DEPENDS rect-17)
+set_tests_properties (proton-dose-5d PROPERTIES DEPENDS ptv-1)
+set_tests_properties (proton-dose-5d-stats
+ PROPERTIES DEPENDS proton-dose-5d)
+set_tests_properties (proton-dose-5d-check
+ PROPERTIES DEPENDS proton-dose-5d-stats)
plm_add_test (
"proton-dose-6a"
- ${PLM_PLASTIMATCH_PATH}/proton_dose
- "${PLM_BUILD_TESTING_DIR}/proton-dose-6a.txt"
+ ${PLM_PLASTIMATCH_PATH}/plastimatch
+ "dose;${PLM_BUILD_TESTING_DIR}/proton-dose-6a.txt"
)
plm_add_test (
"proton-dose-6a-stats"
diff --git a/Testing/Data/plm-bsp-dmap-k.txt b/Testing/Data/plm-bsp-dmap-k.txt
new file mode 100644
index 0000000..c69fa19
--- /dev/null
+++ b/Testing/Data/plm-bsp-dmap-k.txt
@@ -0,0 +1,15 @@
+[GLOBAL]
+fixed=@PLM_BUILD_TESTING_DIR@/rect-4.mha
+moving=@PLM_BUILD_TESTING_DIR@/rect-8.mha
+
+vf_out=@PLM_BUILD_TESTING_DIR@/@PLM_TEST_NAME at -vf.mha
+xform_out=@PLM_BUILD_TESTING_DIR@/@PLM_TEST_NAME at -xf.txt
+img_out=@PLM_BUILD_TESTING_DIR@/@PLM_TEST_NAME at -img.mha
+
+[STAGE]
+xform=bspline
+alg_flavor=k
+metric=dmap
+max_its=20
+grid_spac=10 10 10
+res=2 2 2
diff --git a/Testing/Data/plm-bsp-sm-multi-a.txt b/Testing/Data/plm-bsp-sm-multi-a.txt
index 1290189..3082157 100755
--- a/Testing/Data/plm-bsp-sm-multi-a.txt
+++ b/Testing/Data/plm-bsp-sm-multi-a.txt
@@ -1,6 +1,8 @@
[GLOBAL]
-fixed=@PLM_BUILD_TESTING_DIR@/gauss-1.mha
-moving=@PLM_BUILD_TESTING_DIR@/gauss-2.mha
+fixed[0]=@PLM_BUILD_TESTING_DIR@/gauss-1.mha
+moving[0]=@PLM_BUILD_TESTING_DIR@/gauss-2.mha
+fixed[1]=@PLM_BUILD_TESTING_DIR@/gauss-1.mha
+moving[1]=@PLM_BUILD_TESTING_DIR@/gauss-2.mha
vf_out=@PLM_BUILD_TESTING_DIR@/@PLM_TEST_NAME at -vf.mha
xform_out=@PLM_BUILD_TESTING_DIR@/@PLM_TEST_NAME at -xf.txt
@@ -12,8 +14,10 @@ optim=lbfgsb
impl=plastimatch
threading=single
alg_flavor=c
-metric=mi,gm
-metric_lambda=0.1,100
+metric[0]=gm
+metric[1]=mi
+metric_lambda[0]=0.1
+metric_lambda[1]=100
max_its=5
convergence_tol=3
grad_tol=0.1
diff --git a/Testing/Data/plm-reg-align-center.txt b/Testing/Data/plm-reg-align-center.txt
index fb600a4..7933ab7 100755
--- a/Testing/Data/plm-reg-align-center.txt
+++ b/Testing/Data/plm-reg-align-center.txt
@@ -1,8 +1,9 @@
[GLOBAL]
-fixed=gauss-1.mha
-moving=gauss-6.mha
-xform_out=plm-reg-align-center-xf.txt
-img_out=plm-reg-align-center-img.mha
+fixed=@PLM_BUILD_TESTING_DIR@/gauss-1.mha
+moving=@PLM_BUILD_TESTING_DIR@/gauss-6.mha
+
+xform_out=@PLM_BUILD_TESTING_DIR@/@PLM_TEST_NAME at -xf.txt
+img_out=@PLM_BUILD_TESTING_DIR@/@PLM_TEST_NAME at -img.mha
[STAGE]
xform=align_center
diff --git a/Testing/Data/plm-reg-gw-a.txt b/Testing/Data/plm-reg-gw-a.txt
new file mode 100755
index 0000000..59c9b55
--- /dev/null
+++ b/Testing/Data/plm-reg-gw-a.txt
@@ -0,0 +1,8 @@
+[GLOBAL]
+group_dir=@PLM_BUILD_TESTING_DIR@/gw
+
+[STAGE]
+xform=translation
+impl=plastimatch
+gridsearch_min_overlap=0.8 0.8 0.8
+res_mm=3 3 3
diff --git a/Testing/Data/plm-reg-multi-a.txt b/Testing/Data/plm-reg-multi-a.txt
index ccb1fa3..5f37349 100755
--- a/Testing/Data/plm-reg-multi-a.txt
+++ b/Testing/Data/plm-reg-multi-a.txt
@@ -3,7 +3,6 @@ fixed=@PLM_BUILD_TESTING_DIR@/rect-2.mha
moving=@PLM_BUILD_TESTING_DIR@/sphere-2.mha
vf_out=@PLM_BUILD_TESTING_DIR@/plm-reg-multi-a-vf.nrrd
-xform_out=@PLM_BUILD_TESTING_DIR@/plm-reg-multi-a-xf.txt
img_out=@PLM_BUILD_TESTING_DIR@/plm-reg-multi-a-img.nrrd
[STAGE]
diff --git a/Testing/Data/proton-dose-1.txt b/Testing/Data/proton-dose-1.txt
old mode 100644
new mode 100755
diff --git a/Testing/Data/proton-dose-5g.txt b/Testing/Data/proton-dose-5d.txt
old mode 100644
new mode 100755
similarity index 92%
rename from Testing/Data/proton-dose-5g.txt
rename to Testing/Data/proton-dose-5d.txt
index 4f6c815..9bccb30
--- a/Testing/Data/proton-dose-5g.txt
+++ b/Testing/Data/proton-dose-5d.txt
@@ -1,18 +1,18 @@
-[PLAN]
-patient = @PLM_BUILD_TESTING_DIR@/rect-17.mha
-target = @PLM_BUILD_TESTING_DIR@/ptv-1.mha
-dose_out = @PLM_BUILD_TESTING_DIR@/@PLM_TEST_NAME at .mha
-
-[BEAM]
-flavor = g
-homo_approx = n
-
-source = 0 -2000 0
-isocenter = 0 0 0
-
-aperture_offset = 1500
-aperture_origin = -75 -75
-aperture_spacing = 3.75 3.75
-aperture_resolution = 41 41
-aperture_smearing = 5
-source_size = 0
+[PLAN]
+patient = @PLM_BUILD_TESTING_DIR@/rect-17.mha
+target = @PLM_BUILD_TESTING_DIR@/ptv-1.mha
+dose_out = @PLM_BUILD_TESTING_DIR@/@PLM_TEST_NAME at .mha
+
+[BEAM]
+flavor = d
+homo_approx = n
+
+source = 0 -2000 0
+isocenter = 0 0 0
+
+aperture_offset = 1500
+aperture_origin = -75 -75
+aperture_spacing = 3.75 3.75
+aperture_resolution = 41 41
+aperture_smearing = 5
+source_size = 0
diff --git a/Testing/Data/proton-dose-1.txt b/Testing/Data/proton-dose-7a.txt
old mode 100644
new mode 100755
similarity index 66%
copy from Testing/Data/proton-dose-1.txt
copy to Testing/Data/proton-dose-7a.txt
index a9d0d23..d42353f
--- a/Testing/Data/proton-dose-1.txt
+++ b/Testing/Data/proton-dose-7a.txt
@@ -1,24 +1,18 @@
-[PLAN]
-patient = @PLM_BUILD_TESTING_DIR@/rect-17.mha
-dose_out = @PLM_BUILD_TESTING_DIR@/@PLM_TEST_NAME at .mha
-
-dose_prescription = 70
-
-[BEAM]
-flavor = a
-homo_approx = n
-
-source = 0 -2000 0
-isocenter = 0 0 0
-
-aperture_origin = -10 -10
-aperture_offset = 1500
-aperture_spacing = 1 1
-aperture_resolution = 21 21
-source_size = 0
-prescription_min_max = 70 90
-
-#[PEAK]
-#energy=100.0000
-#spread=1.000000
-#weight=1
+[PLAN]
+patient = @PLM_BUILD_TESTING_DIR@/rect-17.mha
+dose_out = @PLM_BUILD_TESTING_DIR@/@PLM_TEST_NAME at .mha
+dose_prescription = 70
+
+[BEAM]
+flavor = a
+homo_approx = n
+source = 0 -2000 0
+isocenter = 0 0 0
+
+aperture_origin = -20 -20
+aperture_offset = 1500
+aperture_spacing = 1 1
+aperture_resolution = 41 41
+source_size = 0
+
+spot = -5,0,120,6.0,1.5
diff --git a/cmake/FindCUDA_wrap.cmake b/cmake/FindCUDA_wrap.cmake
index ee63f8f..0866bd7 100755
--- a/cmake/FindCUDA_wrap.cmake
+++ b/cmake/FindCUDA_wrap.cmake
@@ -23,7 +23,16 @@ else ()
# GCS 2012-05-07: Workaround for poor, troubled FindCUDA
set (CUDA_ATTACH_VS_BUILD_RULE_TO_CUDA_FILE FALSE)
+
find_package (CUDA QUIET)
+
+ # GCS 2016-12-23: Tell FindCUDA to tell nvcc to use the c++ compiler,
+ # which it doesn't do even if CUDA_HOST_COMPILATION_CPP is true.
+ # This has to be done after calling FindCUDA, because FindCUDA overwrites
+ # the variable. PS: Merry Christmas!
+ if (NOT MSVC)
+ set (CUDA_HOST_COMPILER "${CMAKE_CXX_COMPILER}")
+ endif ()
endif ()
# 14-5-2016 PAOLO: WORKAROUND GCC 6.1 AND CUDA 7.5 INCOMPATIBILITY
diff --git a/cmake/FindKaze.cmake b/cmake/FindKaze.cmake
new file mode 100644
index 0000000..003b4b0
--- /dev/null
+++ b/cmake/FindKaze.cmake
@@ -0,0 +1,35 @@
+# - Find libkaze
+# KAZE_INCLUDE_DIR - where to find kaze.h, etc.
+# KAZE_LIBRARIES - List of libraries when using kaze.
+# KAZE_FOUND - True if kaze found.
+
+set (KAZE_DIR "" CACHE PATH "Root of libkaze install tree (optional).")
+
+if (KAZE_INCLUDE_DIR)
+ # Already in cache, be silent
+ set (Kaze_FIND_QUIETLY TRUE)
+endif ()
+
+
+find_path (KAZE_INCLUDE_DIR kimage.h
+ ${KAZE_DIR}/include)
+
+set (KAZE_NAMES kaze)
+find_library (KAZE_LIBRARY NAMES ${KAZE_NAMES}
+ PATHS
+ ${KAZE_DIR}/lib)
+
+# handle the QUIETLY and REQUIRED arguments and set KAZE_FOUND to TRUE if
+# all listed variables are TRUE
+include (FindPackageHandleStandardArgs)
+find_package_handle_standard_args (Kaze DEFAULT_MSG
+ KAZE_LIBRARY
+ KAZE_INCLUDE_DIR)
+
+if (KAZE_FOUND)
+ set (KAZE_LIBRARIES ${KAZE_LIBRARY})
+else ()
+ set (KAZE_LIBRARIES)
+endif ()
+
+mark_as_advanced (KAZE_LIBRARY KAZE_INCLUDE_DIR)
diff --git a/cmake/FindPaxscan.cmake b/cmake/FindPaxscan.cmake
index d5c0b4f..ca07cfc 100755
--- a/cmake/FindPaxscan.cmake
+++ b/cmake/FindPaxscan.cmake
@@ -15,7 +15,7 @@ endif ()
FIND_PATH (PAXSCAN_INCLUDE_DIR "HcpFuncDefs.h"
"C:/Program Files/Varian/PaxscanL04/DeveloperFiles/Includes"
)
-FIND_LIBRARY (PAXSCAN_LIBRARIES VirtCp
+FIND_LIBRARY (PAXSCAN_LIBRARIES "VirtCp.lib"
"C:/Program Files/Varian/PaxscanL04/DeveloperFiles/VirtCpRel")
INCLUDE (FindPackageHandleStandardArgs)
diff --git a/doc/NOTES.TXT b/doc/NOTES.TXT
old mode 100644
new mode 100755
index 394c0d2..f0cfe02
--- a/doc/NOTES.TXT
+++ b/doc/NOTES.TXT
@@ -1,4 +1,371 @@
******************************************************************************
+Good ideas
+
+Elastix:
+A good set of random sampling options
+Schedule of grid spacing allows multiple sub-stages
+Parameter file overwrites
+Rigidity penalty
+
+******************************************************************************
+Groupwise registration
+
+Current form:
+fixed=foo.mha
+moving=foo.mha
+
+Future form:
+group=dir/
+
+[GROUP]
+iterations=3
+convergence=XX
+
+(or)
+
+group=dir/
+group_iterations=3
+group_convergence=XX
+
+
+******************************************************************************
+Beam model, spot map
+
+rt_beam_model: TBD.
+
+rt_depth_dose: This contains a single depth-dose curve. Currently
+only generated by analytic model.
+
+rt_mebs: This contain a grid of beamlet weights as a function of
+energy and position.
+
+rt_spot_map: This contains a list of spots, each spot containing
+spot position, energy, sigma, weight.
+
+rt_dij: This contains a sparse dose grid. Ideally it should use the
+same data structure as pcmd_warp_dij. However, that structure
+uses ushort. Need to consider how to mitigate truncation and overflow.
+
+Active scanning:
+
+A beam contains a dij.
+A beam contains a spot map.
+A beam contains a mebs.
+There is a map from mebs to spots.
+
+There is a dij for each meb.
+There is a dij for each spot.
+
+The pre-optimizer calculates dij for each spot.
+For each beamlet:
+ Calculate dij
+ Increment involved spots by dij
+
+An optimizer will take a set of dij, and will create spot weights.
+
+The final calculations sums the weighted dij.
+
+Passive scattering:
+
+A beam contains a mebs.
+The
+
+
+
+******************************************************************************
+Calc methodology
+
+1. manual beamlet map
+ compute_beam_data_from_beamlet_map
+ mebs()->clear_depth_dose
+ mebs()->load_beamlet_map
+ update_aperture_and_range_compensator
+ (not implemented)
+2. manual spot map
+3. manual peaks
+ compute_beam_data_from_manual_peaks
+ mebs()->generate_part_num_from_weight
+ compute_beam_modifiers_active_scanning
+ compute_beam_modifiers_passive_scattering
+4. dose prescription
+ mebs()->set_target_depths
+ compute_beam_data_from_prescription
+5. target
+ compute_beam_data_from_target
+ if passive
+ compute_beam_modifiers
+ compute_beam_data_from_prescription
+ if active
+ compute_beam_modifiers_active_scanning
+ compute_particle_number_matrix_from_target_active
+6. 100 MeV sample beam
+ compute_default_beam
+ mebs()->add_peak
+ compute_beam_data_from_manual_peaks
+
+******************************************************************************
+Dose calculation LUTs
+
+rpl_volume.cxx
+--------------
+compute_density_from_HU
+ "From Schneider paper" (Not clear how.)
+compute_PrSTPR_Schneider_weq_from_HU
+ "From Schneider paper" (Not clear how.)
+compute_PrSTRP_XiO_MGH_weq_from_HU
+ Not used (?)
+compute_PrWER_from_HU
+ Stopping power / density
+
+rpl_lut.cxx
+-----------
+get_proton_stop
+ energy -> ??
+get_proton_range
+ energy -> ??
+compute_X0_from_HU
+ HU -> radiation length (Where does this come from?)
+
+
+******************************************************************************
+Global vs stage vs shared
+
+There are only a few small differences.
+
+Review of global options
+
+- No registration is run
+- Allows process stage before first registration stage
+- Global outputs are written after final stage
+-- Written at original resolution, potentially with different options
+- Logfile is global
+-- I suppose you could switch logfile per stage if you wanted
+
+Review of stage options
+
+- Resume stage / finalize stage
+
+******************************************************************************
+Alternate syntax
+
+[METRIC]
+id=0
+metric=mse
+fixed=x1
+moving=y1
+lambda=0.1
+
+[METRIC]
+id=1
+metric=dmap
+fixed=x2
+moving=y2
+lambda=1.0
+histogram_bins=30
+
+[STAGE]
+metric=mse,dmap
+
+Note that this is not more powerful. Instead we could do this:
+
+fixed[0]=x1
+moving[0]=y1
+metric[0]=mse
+fixed[1]=x2
+moving[1]=y2
+metric[1]=mi
+histogram_bins[1]=30
+
+Also, with the first syntax, you might want some way to specify
+warped images (warped y1 and y2).
+
+
+******************************************************************************
+Registration similarity parms/data (cont.)
+
+On the use of std::map.
+
+There are three places where it gets used.
+- Shared_parms
+-- Individual maps for filenames fixed, moving, etc
+- Stage_parms
+-- To be added, individual maps for parameters smetric, smetric_lambda
+- Registration_data
+-- Map of Registration_similarity_data's (containing Plm_image's)
+
+After this, the map gets dissolved into a vector of Stage_similarity_data
+
+- Filenames go raw into map for Shared_parms, images get loaded
+ into Registration_data.
+- Smetric gets cooked and split going into vector for Stage_parms.
+- The Registration_similarity_data (and then Stage_similarity_data)
+ seem to need the parameters.
+
+The main question seems to be that parms and images are considered separate.
+What kind of remedies are there for this?
+
+- Keep separate, parallel maps
+-- Registration_similarity_data stays as-is
+-- Individual maps (or Similarity_parms map) remain in Stage_parms
+-- Copy into unified vector of Stage_similarity_data
+- Single unified parameter map, duplicated parms
+-- Upgrade smetric, smetric_lambda to shared parms
+-- Copy parms into unified Registration_similarity_data at same time
+ as image load for each stage
+- Unify Registration_parms and Registration_data
+-- Upgrade smetric, smetric_lambda to shared parms
+-- Create <filename,Plm_image> pairs
+--- Or scoreboard that maps filename -> Plm_image
+-- At filename load, the <filename,Plm_image> pairs are interpreted
+
+The first option seems easiest, and we could eventually upgrade
+to third option later.
+
+The second option is largely similar to the first, and does not appear
+to have significant advantages, with the exception of a unified map.
+
+The third option seems elegant, but may have some fragile points.
+
+- What to do about process section? Possible solutions:
+-- Update scoreboard entries with process results
+-- Augment scoreboard to include variable
+-- In any case, this is not super-well supported anyway
+- What to do about avoiding repeat loads
+-- Images in scoreboard, filenames get passed to stages
+-- Pointers copied from stage to stage
+
+Similarity_data
+ <fixed_fn,fixed>, <moving_fn,moving>,
+ smetric, smetric_lambda
+
+Registration_parms
+ list<Stage_parms*>
+
+Stage_parms
+ map<str,Similarity_data>
+
+Final decision: "first option"
+
+******************************************************************************
+Registration similarity parms/data (cont.)
+
+ROIs are different from similarity? Here are ways they are different.
+
+- Probably ROIs should affect multiple similarity metrics
+- Probably ROIs should affect regularization
+-- This one is not currently implemented
+-- Ideally should be allowed independent of similarity roi
+-- Ideally should be allowed on a per-regularization basis
+
+Current decision. Make ROI affect multiple similiary metrics.
+
+******************************************************************************
+Registration similarity parms/data (cont.)
+
+Proposed change option 1
+
+Registration_parms
+ list<Stage_parms*>
+ Shared_parms
+ map<str,Similarity_parms> <- new
+
+Similarity_parms
+ fixed_fn
+ moving_fn
+
+What should happen with un-specified parameters? Example:
+
+fixed[0] = a.mha
+moving[0] = b.mha
+metric[0] = mi // A) should this propagate to [1]?
+impl = plastimatch // B) should this propagate to [1]?
+fixed[1] = c.mha // C) if moving[1] not specified should anything happen?
+histeq[1] = true // D) should this propagate to [0]?
+
+Answers:
+
+A) No.
+B) No.
+C) No.
+D) No.
+
+******************************************************************************
+Registration similarity parms/data (cont.)
+
+Current status 2016-12-28
+
+Registration_parms
+ list<Stage_parms*>
+ Shared_parms
+ map<str,str> fixed_fn, moving_fn, etc
+
+Registration_data
+ map<str,Reg_sim_data>
+ list<str>
+ Stage_parms auto_parms
+
+Bspline_stage
+ Bspline_optimize <- check_grad, bspline_score only depends on this
+ Bspline_parms
+ Bspline_state <- needs parms & bxf to initialize
+ Stage_similarity_data <- newly created bxf depends on master image
+ Bspline_score
+ Bspline_xform <- might be loaded from disc, might rely on
+ fixed image size to set # of control points
+
+1a) Load image
+1b) Fixate image
+2a) Load xform
+2b) Fixate xform
+
+N.b. also
+
+ Bspline_options
+ Bspline_parms
+
+
+******************************************************************************
+Registration similarity parms/data
+
+There are three main types of similarity data:
+- parms
+- original images
+- derived images
+
+In 2016-12-22 design (so far),
+
+- parms
+ - Read into Stage_parms during parameter file parsing.
+ - For each stage, copied into Bspline_parms.
+- original images
+ - Filenames are read into Shared_parms (but update each
+ stage not implemented) during parameter file parsing.
+ - Images loaded during load_stage_input(), placed in
+ Registration_data (Type Similarity_data).
+ - They are not reloaded each stage because file_names are
+ not copied when new stages are created.
+- derived images
+ - Images subsampled and grad calculated into Bspline_stage,
+ then copied into Bspline_parms.
+
+Next iteration of design.
+
+- parms
+ - Read into Stage_parms during parameter file parsing.
+ - For each stage, copied into Bspline_parms.
+- original images
+ - Filenames are read into Shared_parms (but update each
+ stage not implemented) during parameter file parsing.
+ - Images loaded during load_stage_input(), placed in
+ Registration_data (type Registration_data::similarity_images).
+ - They are not reloaded each stage because file_names are
+ not copied when new stages are created.
+- derived images
+ - Images subsampled and grad calculated into Bspline_stage,
+ then copied into Bspline_parms, type Bspline_data::similarity_images.
+
+
+******************************************************************************
register_gui
2016-10-31
@@ -1353,35 +1720,6 @@ Or like this:
4) Move source code to src/ subdirectory
-***** Consistency of indices *****
-
-By convention:
-
- k, z = slowest moving index (usually IS)
- j, y = middle moving index (usually AP)
- i, x = fastest moving index (usually RL)
-
-Arrays which hold things like the dimensions are indexed as follows:
-
- dim[0] = dimensions of fastest moving index
- dim[1] = dimensions of middle moving index
- dim[2] = dimensions of slowest moving index
-
-Loops should be nested from slowest index to fastest index.
-Therefore, the correct nesting is:
-
- for (k = 0; k < fixed->dim[2]; k++) {
- for (j = 0; j < fixed->dim[1]; j++) {
- for (i = 0; i < fixed->dim[0]; i++) { ... } } }
-
-Embedded indices, such as (x,y,z) coordinates of the vector
-field at a voxel, should be in the order of x, then y, then z.
-
-When you pass indices into a function it should be
-in order x, then y, then z. For example:
-
- int volume_index (int* dims, int i, int j, int k);
-
***** How to compile libf2c *****
Edit libf2c/makefile.vc, and change:
diff --git a/doc/STYLE_GUIDE_2.TXT b/doc/STYLE_GUIDE_2.TXT
index ef65db0..11ad334 100644
--- a/doc/STYLE_GUIDE_2.TXT
+++ b/doc/STYLE_GUIDE_2.TXT
@@ -161,6 +161,41 @@ return type:
object.get_volume_float ();
+Index convention in images and volumes
+--------------------------------------
+The following convention is used for walking through images
+
+ k, z = slowest moving index (usually IS)
+ j, y = middle moving index (usually AP)
+ i, x = fastest moving index (usually RL)
+
+Arrays which hold things like the dimensions are indexed as follows:
+
+ dim[0] = dimensions of fastest moving index
+ dim[1] = dimensions of middle moving index
+ dim[2] = dimensions of slowest moving index
+
+Loops should be nested from slowest index to fastest index.
+Therefore, the correct nesting is:
+
+ for (k = 0; k < fixed->dim[2]; k++) {
+ for (j = 0; j < fixed->dim[1]; j++) {
+ for (i = 0; i < fixed->dim[0]; i++) { ... } } }
+
+Embedded indices, such as (x,y,z) coordinates of the vector
+field at a voxel, should be in the order of x, then y, then z.
+
+When you pass indices into a function it should be
+in order x, then y, then z. For example:
+
+ int volume_index (int* dims, int i, int j, int k);
+
+For 2D images, dim is preferred over ires. And (j,i) preferred over (r,c).
+But for legacy code, the following should be true:
+
+ r, j, dim[1], ires[1] = slowest moving index (row)
+ c, i, dim[0], ires[0] = fastest moving index (column)
+
Variable naming for indexing [Proposed, not implemented]
---------------------------------------------------------
idx index one dimensional index
diff --git a/doc/man/drr.1 b/doc/man/drr.1
index 2513da0..c0f44f5 100644
--- a/doc/man/drr.1
+++ b/doc/man/drr.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "DRR" "1" "Dec 04, 2016" "Plastimatch 1.6.5" "Plastimatch"
+.TH "DRR" "1" "October 11, 2017" "Plastimatch 1.6.6" "Plastimatch"
.SH NAME
drr \- create a digitally reconstructed radiograph
.
diff --git a/doc/man/fdk.1 b/doc/man/fdk.1
index c51849f..e3c8515 100644
--- a/doc/man/fdk.1
+++ b/doc/man/fdk.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "FDK" "1" "Dec 04, 2016" "Plastimatch 1.6.5" "Plastimatch"
+.TH "FDK" "1" "October 11, 2017" "Plastimatch 1.6.6" "Plastimatch"
.SH NAME
fdk \- cone-beam reconstruction from projections using the FDK algorithm
.
@@ -64,7 +64,7 @@ Options:
.UNINDENT
.sp
The usage of the fdk program is best understood by following along
-with the tutorials: fdk_tutorial_i and fdk_tutorial_ii\&.
+with the tutorials: \fIfdk_tutorial_i\fP and \fIfdk_tutorial_ii\fP\&.
.SH INPUT FILES
.sp
Three different formats of input files are supported. These are:
@@ -87,7 +87,7 @@ with the .txt extension. For example, if you want to use image_0000.pfm
in a reconstruction, you should supply another file image_0000.txt
which contains the geometry.
A brief description of the geometry file format is given in
-proj_mat_file_format\&.
+\fIproj_mat_file_format\fP\&.
.sp
The sequence of files should be stored with the pattern:
.INDENT 0.0
diff --git a/doc/man/landmark_warp.1 b/doc/man/landmark_warp.1
index c38c56c..2f65948 100644
--- a/doc/man/landmark_warp.1
+++ b/doc/man/landmark_warp.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "LANDMARK_WARP" "1" "Dec 04, 2016" "Plastimatch 1.6.5" "Plastimatch"
+.TH "LANDMARK_WARP" "1" "October 11, 2017" "Plastimatch 1.6.6" "Plastimatch"
.SH NAME
landmark_warp \- warp an image using point landmarks
.
diff --git a/doc/man/plastimatch.1 b/doc/man/plastimatch.1
index 24e7197..8aefd7d 100644
--- a/doc/man/plastimatch.1
+++ b/doc/man/plastimatch.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "PLASTIMATCH" "1" "Dec 04, 2016" "Plastimatch 1.6.5" "Plastimatch"
+.TH "PLASTIMATCH" "1" "October 11, 2017" "Plastimatch 1.6.6" "Plastimatch"
.SH NAME
plastimatch \- register, convert, warp, or manipulate images
.
@@ -47,16 +47,17 @@ without any additional command line arguments:
.nf
.ft C
$ plastimatch
-plastimatch version 1.6.0\-beta (5023)
+plastimatch version 1.6.6
Usage: plastimatch command [options]
Commands:
- add adjust average boundary crop
- compare compose convert dice diff
- dmap dvh fill filter gamma
- header jacobian mabs mask probe
+ add adjust average bbox boundary
+ crop compare compose convert dice
+ diff dmap dose dvh fill
+ filter gamma header jacobian mabs
+ mask maximum ml\-convert multiply probe
register resample scale segment stats
synth synth\-vf threshold thumbnail union
- warp xf\-convert
+ vf\-invert warp xf\-convert
For detailed usage of a specific command, type:
plastimatch command
@@ -616,10 +617,11 @@ plastimatch convert \e
.sp
In the previous example, the geometry of the output file wasn\(aqt specified.
When the geometry of a DICOM RT structure set isn\(aqt specified, it is
-assumed to match the geometry of the DICOM CT image associated with the
-contours. If the associated DICOM CT image is in the same directory as
+assumed to match the geometry of the DICOM (CT, MR, etc)
+image associated with the
+contours. If the associated DICOM image is in the same directory as
the structure set file, it will be found automatically. Otherwise, we
-have to tell plastimatch where it is located with the \-\-dicom\-dir option.
+have to tell plastimatch where it is located with the \-\-referenced\-ct option.
.INDENT 0.0
.INDENT 3.5
.sp
@@ -629,7 +631,7 @@ plastimatch convert \e
\-\-input structures.dcm \e
\-\-output\-ss\-img outfile.nrrd \e
\-\-output\-ss\-list outfile.txt \e
- \-\-dicom\-dir ../ct\-directory
+ \-\-referenced\-ct ../image\-directory
.ft P
.fi
.UNINDENT
@@ -1132,8 +1134,8 @@ Prior to running the mabs command, you must create a configuration
file, and you must arrange your training data into the proper
directory format.
For a complete description of the command file syntax and
-usage examples, please refer to the mabs_guidebook
-and the segmentation_command_file_reference\&.
+usage examples, please refer to the \fImabs_guidebook\fP
+and the \fIsegmentation_command_file_reference\fP\&.
.SH PLASTIMATCH MASK
.sp
The \fImask\fP command is used to fill an image region with a constant
@@ -1287,7 +1289,7 @@ and each stage begins with a line containing the string "[STAGE]".
The global section is used to set input files, output files, and
global parameters, while the each stage section defines a sequential
stage of processing. For a complete description of the command file
-syntax, please refer to the registration_command_file_reference\&.
+syntax, please refer to the \fIregistration_command_file_reference\fP\&.
.SS Examples
.sp
If you want to register image_2.mha to match image_1.mha using
@@ -1367,7 +1369,7 @@ res=1 1 1
.UNINDENT
.UNINDENT
.sp
-For more examples, please refer to the image_registration_guidebook\&.
+For more examples, please refer to the \fIimage_registration_guidebook\fP\&.
.SH PLASTIMATCH RESAMPLE
.sp
The \fIresample\fP command can be used to change the geometry of an image.
diff --git a/run_lcov.sh b/run_lcov.sh
deleted file mode 100755
index 10be6e4..0000000
--- a/run_lcov.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#! /bin/sh
-
-lcov --directory . --zerocounters
-ctest
-lcov --directory . --capture --output-file app.info
-genhtml app.info
-firefox ./index.html
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
old mode 100755
new mode 100644
index 38cf8a2..993e2c8
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -43,6 +43,10 @@ if (FFTW_FOUND)
set (PLASTIMATCH_LIBS ${PLASTIMATCH_LIBS} ${FFTW_LIBRARIES})
endif ()
+if (KAZE_FOUND)
+ set (PLASTIMATCH_LIBS ${PLASTIMATCH_LIBS} ${KAZE_LIBRARIES})
+endif ()
+
if (LIBDL_FOUND)
set (PLASTIMATCH_LIBS ${PLASTIMATCH_LIBS} dl)
endif ()
@@ -93,6 +97,7 @@ endif ()
if (NOT PLM_CONFIG_DISABLE_ISE)
add_subdirectory (ise)
+ add_subdirectory (fatm)
endif ()
if (NOT PLM_CONFIG_DISABLE_FATM)
diff --git a/src/plastimatch/CHANGELOG.TXT b/src/plastimatch/CHANGELOG.TXT
index 9ba791e..cd3279f 100644
--- a/src/plastimatch/CHANGELOG.TXT
+++ b/src/plastimatch/CHANGELOG.TXT
@@ -1,3 +1,13 @@
+Version 1.6.6 (tag v1.6.6)
+Wed Oct 11 10:54:34 EDT 2017
+* Support for multi-metric registration
+* Support for multi-planar registration
+* Support image masks in multi-planar registration
+* Support for dmap registration metric type
+* Many dose calculation improvements
+* DICOM RT Ion plan support
+* Many other bug fixes
+
Version 1.6.5 (tag v1.6.5)
Sun Dec 4 18:07:24 EST 2016
* Improved support for DICOM RT ion plan
diff --git a/src/plastimatch/CMakeLists.txt b/src/plastimatch/CMakeLists.txt
old mode 100755
new mode 100644
index df4dc82..4f2a706
--- a/src/plastimatch/CMakeLists.txt
+++ b/src/plastimatch/CMakeLists.txt
@@ -86,7 +86,7 @@ include_directories (AFTER ${MSINTTYPES_INCLUDE_DIR})
include_directories (AFTER ${RANSAC_INCLUDE_DIRS})
if (${PLM_CONFIG_USE_PATCHED_ITK})
- include_directories (AFTER ${CMAKE_SOURCE_DIR}/libs/itk-3.20.0)
+ include_directories (AFTER ${CMAKE_SOURCE_DIR}/libs/itk-3.20.0)
endif ()
if (CUDA_FOUND)
@@ -99,6 +99,9 @@ if (FFTW_FOUND)
include_directories (BEFORE ${FFTW_INCLUDE_DIR})
link_directories (${FFTW_DIR})
endif ()
+if (KAZE_FOUND)
+ include_directories (AFTER ${KAZE_INCLUDE_DIR})
+endif ()
if (MATLAB_FOUND)
include_directories (AFTER ${MATLAB_INCLUDE_DIRS})
endif ()
diff --git a/src/plastimatch/COPYRIGHT.TXT b/src/plastimatch/COPYRIGHT.TXT
old mode 100755
new mode 100644
diff --git a/src/plastimatch/Doxyfile.in b/src/plastimatch/Doxyfile.in
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/CMakeLists.txt b/src/plastimatch/base/CMakeLists.txt
old mode 100644
new mode 100755
index 3bf638d..d5149e8
--- a/src/plastimatch/base/CMakeLists.txt
+++ b/src/plastimatch/base/CMakeLists.txt
@@ -38,6 +38,7 @@ set (PLMBASE_LIBRARY_SRC
interpolate_macros.h
itkAndConstantToImageFilter.h
itkClampCastImageFilter.txx itkClampCastImageFilter.h
+ itk_bbox.cxx itk_bbox.h
itk_dicom_load.cxx itk_dicom_load.h
itk_dicom_save.cxx itk_dicom_save.h
itk_directions.cxx itk_directions.h
@@ -102,6 +103,7 @@ set (PLMBASE_LIBRARY_SRC
ray_trace_probe.h
ray_trace_uniform.cxx
rpl_volume.cxx rpl_volume.h
+ rpl_volume_lut.cxx rpl_volume_lut.h
rtds_dcmtk.cxx
rtds_gdcm.cxx
rt_study.cxx rt_study.h
@@ -126,6 +128,7 @@ set (PLMBASE_LIBRARY_SRC
vf_jacobian.cxx vf_jacobian.h
vf_stats.cxx vf_stats.h
volume.cxx volume.h
+ volume_boundary_behavior.h
volume_conv.cxx volume_conv.h
volume_fill.cxx volume_fill.h
volume_gaussian.cxx volume_gaussian.h
diff --git a/src/plastimatch/base/aperture.cxx b/src/plastimatch/base/aperture.cxx
old mode 100644
new mode 100755
index 5b08f6e..c2dc6a7
--- a/src/plastimatch/base/aperture.cxx
+++ b/src/plastimatch/base/aperture.cxx
@@ -36,7 +36,7 @@ public:
Plm_image::Pointer range_compensator_image;
double distance;
- int dim[2];
+ plm_long dim[2];
double center[2];
double spacing[2];
};
@@ -45,8 +45,8 @@ Aperture::Aperture ()
{
this->d_ptr = new Aperture_private;
- /* The aperture and the range compensator are inizialized */
- this->allocate_aperture_images();
+ /* The aperture and the range compensator are inizialized */
+ this->allocate_aperture_images();
this->vup[0] = 0.0;
this->vup[1] = 0.0;
@@ -71,8 +71,8 @@ Aperture::Aperture (const Aperture::Pointer& ap)
{
this->d_ptr = new Aperture_private (ap->d_ptr);
- /* The aperture and the range compensator are initialized */
- this->allocate_aperture_images();
+ /* The aperture and the range compensator are initialized */
+ this->allocate_aperture_images();
vec3_copy (this->vup, ap->vup);
vec3_copy (this->pdn, ap->pdn);
@@ -83,19 +83,19 @@ Aperture::Aperture (const Aperture::Pointer& ap)
vec3_copy (this->incr_r, ap->incr_r);
vec3_copy (this->incr_c, ap->incr_c);
- Volume::Pointer ap_tmp = ap->get_aperture_volume();
- unsigned char* ap_tmp_img = (unsigned char*) ap_tmp->img;
- Volume::Pointer rc_tmp = ap->get_range_compensator_volume();
- float* rc_tmp_img = (float*) rc_tmp->img;
+ Volume::Pointer ap_tmp = ap->get_aperture_volume();
+ unsigned char* ap_tmp_img = (unsigned char*) ap_tmp->img;
+ Volume::Pointer rc_tmp = ap->get_range_compensator_volume();
+ float* rc_tmp_img = (float*) rc_tmp->img;
- unsigned char* ap_img = (unsigned char*) this->get_aperture_volume()->img;
- float* rc_img = (float*) this->get_range_compensator_volume()->img;
+ unsigned char* ap_img = (unsigned char*) this->get_aperture_volume()->img;
+ float* rc_img = (float*) this->get_range_compensator_volume()->img;
- for (int i = 0; i < d_ptr->dim[0] * d_ptr->dim[1]; i++)
- {
- ap_img[i] = ap_tmp_img[i];
- rc_img[i] = rc_tmp_img[i];
- }
+ for (int i = 0; i < d_ptr->dim[0] * d_ptr->dim[1]; i++)
+ {
+ ap_img[i] = ap_tmp_img[i];
+ rc_img[i] = rc_tmp_img[i];
+ }
}
Aperture::~Aperture ()
@@ -115,27 +115,27 @@ Aperture::set_distance (double distance)
d_ptr->distance = distance;
}
-const int*
+const plm_long*
Aperture::get_dim () const
{
return d_ptr->dim;
}
-int
+plm_long
Aperture::get_dim (int dim) const
{
return d_ptr->dim[dim];
}
void
-Aperture::set_dim (const int* dim)
+Aperture::set_dim (const plm_long* dim)
{
d_ptr->dim[0] = dim[0];
d_ptr->dim[1] = dim[1];
d_ptr->center[0] = (dim[0]-1) / 2;
d_ptr->center[1] = (dim[1]-1) / 2;
- this->allocate_aperture_images();
+ this->allocate_aperture_images();
}
const double*
@@ -239,15 +239,15 @@ Aperture::allocate_aperture_images ()
Volume *ap_vol = new Volume (dim, origin, spacing, NULL, PT_UCHAR, 1);
Volume *rc_vol = new Volume (dim, origin, spacing, NULL, PT_FLOAT, 1);
- /* Set the volume to values = 0 for range compensator and 1 for aperture */
- unsigned char* ap_img = (unsigned char*) ap_vol->img;
- float* rc_img = (float*) rc_vol->img;
+ /* Set the volume to values = 0 for range compensator and 1 for aperture */
+ unsigned char* ap_img = (unsigned char*) ap_vol->img;
+ float* rc_img = (float*) rc_vol->img;
- for (int i = 0; i < d_ptr->dim[0] * d_ptr->dim[1]; i++)
- {
- ap_img[i] = 1;
- rc_img[i] = 0;
- }
+ for (int i = 0; i < d_ptr->dim[0] * d_ptr->dim[1]; i++)
+ {
+ ap_img[i] = 1;
+ rc_img[i] = 0;
+ }
d_ptr->aperture_image = Plm_image::New (ap_vol);
d_ptr->range_compensator_image = Plm_image::New (rc_vol);
@@ -271,6 +271,12 @@ Aperture::get_aperture_volume ()
return d_ptr->aperture_image->get_volume_uchar ();
}
+Volume*
+Aperture::get_aperture_vol ()
+{
+ return this->get_aperture_volume().get();
+}
+
void
Aperture::set_aperture_image (const char *ap_filename)
{
@@ -320,8 +326,8 @@ Aperture::apply_smearing_to_aperture (float smearing, float reference_depth)
int strel_half_size[2];
int strel_size[2];
- strel_half_size[0] = ROUND_INT(smearing * d_ptr->distance / (reference_depth * d_ptr->spacing[0]));
- strel_half_size[1] = ROUND_INT(smearing * d_ptr->distance / (reference_depth * d_ptr->spacing[1]));
+ strel_half_size[0] = ROUND_INT(smearing * d_ptr->distance / (reference_depth * d_ptr->spacing[0]));
+ strel_half_size[1] = ROUND_INT(smearing * d_ptr->distance / (reference_depth * d_ptr->spacing[1]));
strel_size[0] = 1 + 2 * strel_half_size[0];
strel_size[1] = 1 + 2 * strel_half_size[1];
@@ -354,9 +360,9 @@ Aperture::apply_smearing_to_aperture (float smearing, float reference_depth)
Volume::Pointer ap_vol_new = ap_vol->clone ();
unsigned char* ap_img_new = (unsigned char*) ap_vol_new->img;
- for (int ar = 0; ar < d_ptr->dim[1]; ar++) {
- for (int ac = 0; ac < d_ptr->dim[0]; ac++) {
- int aidx = ar * d_ptr->dim[0] + ac;
+ for (plm_long ar = 0; ar < d_ptr->dim[1]; ar++) {
+ for (plm_long ac = 0; ac < d_ptr->dim[0]; ac++) {
+ plm_long aidx = ar * d_ptr->dim[0] + ac;
unsigned char ap_acc = 0;
for (int sr = 0; sr < strel_size[1]; sr++) {
int pr = ar + sr - strel_half_size[1];
@@ -398,8 +404,8 @@ Aperture::apply_smearing_to_range_compensator (float smearing, float reference_d
int strel_half_size[2];
int strel_size[2];
- strel_half_size[0] = ROUND_INT(smearing * d_ptr->distance / (reference_depth * d_ptr->spacing[0]));
- strel_half_size[1] = ROUND_INT(smearing * d_ptr->distance / (reference_depth * d_ptr->spacing[1]));
+ strel_half_size[0] = ROUND_INT(smearing * d_ptr->distance / (reference_depth * d_ptr->spacing[0]));
+ strel_half_size[1] = ROUND_INT(smearing * d_ptr->distance / (reference_depth * d_ptr->spacing[1]));
strel_size[0] = 1 + 2 * strel_half_size[0];
strel_size[1] = 1 + 2 * strel_half_size[1];
@@ -432,9 +438,9 @@ Aperture::apply_smearing_to_range_compensator (float smearing, float reference_d
Volume::Pointer rc_vol_new = rc_vol->clone ();
float* rc_img_new = (float*) rc_vol_new->img;
- for (int ar = 0; ar < d_ptr->dim[1]; ar++) {
- for (int ac = 0; ac < d_ptr->dim[0]; ac++) {
- int aidx = ar * d_ptr->dim[0] + ac;
+ for (plm_long ar = 0; ar < d_ptr->dim[1]; ar++) {
+ for (plm_long ac = 0; ac < d_ptr->dim[0]; ac++) {
+ plm_long aidx = ar * d_ptr->dim[0] + ac;
float rc_acc = FLT_MAX;
for (int sr = 0; sr < strel_size[1]; sr++) {
int pr = ar + sr - strel_half_size[1];
diff --git a/src/plastimatch/base/aperture.h b/src/plastimatch/base/aperture.h
old mode 100644
new mode 100755
index acab887..893d658
--- a/src/plastimatch/base/aperture.h
+++ b/src/plastimatch/base/aperture.h
@@ -24,11 +24,11 @@ public:
///@{
/*! \brief Get the aperture dimension, in pixels */
- const int* get_dim () const;
+ const plm_long* get_dim () const;
/*! \brief Get the i or j aperture dimension, in pixels */
- int get_dim (int dim) const;
+ plm_long get_dim (int dim) const;
/*! \brief Set the aperture dimension, in pixels */
- void set_dim (const int* dim);
+ void set_dim (const plm_long* dim);
/*! \brief Get the aperture center, in pixels */
const double* get_center () const;
@@ -74,6 +74,7 @@ public:
Plm_image::Pointer& get_aperture_image ();
/*! \brief Get the aperture image as Volume */
Volume::Pointer& get_aperture_volume ();
+ Volume* get_aperture_vol ();
/*! \brief Load the aperture image from a file */
void set_aperture_image (const char *ap_filename);
@@ -96,9 +97,9 @@ public:
/*! \brief Expand aperture and smear compensator. The smearing
parameters is defined as mm around the target in the beam eye view frame
- at the target minimal depth. */
+ at the target minimal depth. */
void apply_smearing_to_aperture (float smearing, float target_depth);
- void apply_smearing_to_range_compensator (float smearing, float target_depth);
+ void apply_smearing_to_range_compensator (float smearing, float target_depth);
///@}
public:
diff --git a/src/plastimatch/base/bspline_xform.cxx b/src/plastimatch/base/bspline_xform.cxx
index 68915df..59cbdb4 100644
--- a/src/plastimatch/base/bspline_xform.cxx
+++ b/src/plastimatch/base/bspline_xform.cxx
@@ -201,8 +201,7 @@ bspline_xform_load (const char* filename)
return 0;
}
- std::string tag, val;
- if (!split_tag_val (line, tag, val)) {
+ if (line.find('=') == std::string::npos) {
/* No "=" found. Better be the first coefficient. */
break;
}
@@ -642,6 +641,22 @@ Bspline_xform::fill_coefficients (float val)
}
}
+void
+Bspline_xform::jitter_if_zero ()
+{
+ /* The MI algorithm will get stuck for a set of coefficients all equaling
+ * zero due to the method we use to compute the cost function gradient.
+ * However, it is possible we could be inheriting coefficients from a
+ * prior stage, so we must check for inherited coefficients before
+ * applying an initial offset to the coefficient array. */
+ for (int i = 0; i < this->num_coeff; i++) {
+ if (this->coeff[i] != 0.0f) {
+ return;
+ }
+ }
+ fill_coefficients (0.01f);
+}
+
/* Set volume header from B-spline Xform */
void
Bspline_xform::get_volume_header (Volume_header *vh)
@@ -649,3 +664,17 @@ Bspline_xform::get_volume_header (Volume_header *vh)
vh->set (this->img_dim, this->img_origin, this->img_spacing,
this->dc.get_matrix());
}
+
+void
+Bspline_xform::log_header ()
+{
+ logfile_printf ("BSPLINE XFORM HEADER\n");
+ logfile_printf ("vox_per_rgn = %d %d %d\n",
+ this->vox_per_rgn[0], this->vox_per_rgn[1], this->vox_per_rgn[2]);
+ logfile_printf ("roi_offset = %d %d %d\n",
+ this->roi_offset[0], this->roi_offset[1], this->roi_offset[2]);
+ logfile_printf ("roi_dim = %d %d %d\n",
+ this->roi_dim[0], this->roi_dim[1], this->roi_dim[2]);
+ logfile_printf ("img_dc = %s\n", this->dc.get_string().c_str());
+}
+
diff --git a/src/plastimatch/base/bspline_xform.h b/src/plastimatch/base/bspline_xform.h
index f322560..1d0e8ff 100644
--- a/src/plastimatch/base/bspline_xform.h
+++ b/src/plastimatch/base/bspline_xform.h
@@ -15,6 +15,10 @@
class Volume;
class Volume_header;
+/*! \brief
+ * The Bspline_xform class encapsulates the B-spline coefficients
+ * used by native registration and warping algorithms.
+ */
class PLMBASE_API Bspline_xform {
public:
SMART_POINTER_SUPPORT (Bspline_xform);
@@ -71,7 +75,13 @@ public:
);
void save (const char* filename);
void fill_coefficients (float val);
+ /*! \brief This function jitters the coefficients if they are all zero.
+ * It is used to prevent local minima artifact when optimizing an MI cost
+ * function for images with the same geometry.
+ */
+ void jitter_if_zero ();
void get_volume_header (Volume_header *vh);
+ void log_header ();
};
PLMBASE_C_API Bspline_xform* bspline_xform_load (const char* filename);
diff --git a/src/plastimatch/base/dcmtk_config.h b/src/plastimatch/base/dcmtk_config.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/dcmtk_file.cxx b/src/plastimatch/base/dcmtk_file.cxx
old mode 100755
new mode 100644
index d769363..556b171
--- a/src/plastimatch/base/dcmtk_file.cxx
+++ b/src/plastimatch/base/dcmtk_file.cxx
@@ -246,10 +246,12 @@ Dcmtk_file::load_header (const char *fn) {
/* PixelSpacing */
ofrc = dset->findAndGetString (DCM_PixelSpacing, c);
if (ofrc.good() && c) {
- float spacing[3];
- int rc = parse_dicom_float2 (spacing, c);
+ float dcm_spacing[2];
+ int rc = parse_dicom_float2 (dcm_spacing, c);
if (!rc) {
- spacing[2] = 0.0;
+ float spacing[3] = {
+ dcm_spacing[1], dcm_spacing[0], 0.0
+ };
d_ptr->m_vh.set_spacing (spacing);
}
}
diff --git a/src/plastimatch/base/dcmtk_file.h b/src/plastimatch/base/dcmtk_file.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/dcmtk_image.cxx b/src/plastimatch/base/dcmtk_image.cxx
old mode 100755
new mode 100644
index 1398105..9cc64d9
--- a/src/plastimatch/base/dcmtk_image.cxx
+++ b/src/plastimatch/base/dcmtk_image.cxx
@@ -116,6 +116,8 @@ Dcmtk_rt_study::image_load ()
df->get_cstr (DCM_StudyDate));
d_ptr->rt_study_metadata->set_study_time (
df->get_cstr (DCM_StudyTime));
+ d_ptr->rt_study_metadata->set_study_id (
+ df->get_cstr (DCM_StudyID));
/* Store remaining metadata */
Metadata::Pointer& study_metadata = d_ptr->rt_study_metadata->get_study_metadata ();
@@ -129,6 +131,7 @@ Dcmtk_rt_study::image_load ()
dcmtk_copy_into_metadata (image_metadata, df, DCM_Modality);
dcmtk_copy_into_metadata (image_metadata, df, DCM_InstanceCreationDate);
dcmtk_copy_into_metadata (image_metadata, df, DCM_InstanceCreationTime);
+ dcmtk_copy_into_metadata (image_metadata, df, DCM_SeriesDescription);
}
/* Divine image type */
@@ -478,6 +481,8 @@ dcmtk_save_slice (const Rt_study_metadata::Pointer rsm, Dcmtk_slice_data *dsd)
modality.c_str());
dataset->putAndInsertString (DCM_SeriesInstanceUID,
rsm->get_ct_series_uid());
+ dataset->putAndInsertString (DCM_SeriesDescription,
+ rsm->get_ct_series_description());
/* Frame of Reference module */
Dcmtk_module::set_frame_of_reference (dataset, rsm);
@@ -496,7 +501,7 @@ dcmtk_save_slice (const Rt_study_metadata::Pointer rsm, Dcmtk_slice_data *dsd)
}
/* Image Plane module */
- tmp = string_format ("%f\\%f", dsd->vol->spacing[0], dsd->vol->spacing[1]);
+ tmp = string_format ("%f\\%f", dsd->vol->spacing[1], dsd->vol->spacing[0]);
dataset->putAndInsertString (DCM_PixelSpacing, tmp.c_str());
dataset->putAndInsertString (DCM_ImageOrientationPatient, dsd->iop.c_str());
dataset->putAndInsertString (DCM_ImagePositionPatient, dsd->ipp.c_str());
@@ -547,6 +552,10 @@ dcmtk_save_slice (const Rt_study_metadata::Pointer rsm, Dcmtk_slice_data *dsd)
dataset->putAndInsertString (
DCM_SOPClassUID, UID_NuclearMedicineImageStorage);
}
+ else if (modality == "US") {
+ dataset->putAndInsertString (
+ DCM_SOPClassUID, UID_UltrasoundImageStorage);
+ }
else {
dataset->putAndInsertString (
DCM_SOPClassUID, UID_CTImageStorage);
diff --git a/src/plastimatch/base/dcmtk_metadata.cxx b/src/plastimatch/base/dcmtk_metadata.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/dcmtk_metadata.h b/src/plastimatch/base/dcmtk_metadata.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/dcmtk_module.cxx b/src/plastimatch/base/dcmtk_module.cxx
index 2887a50..b7bb400 100644
--- a/src/plastimatch/base/dcmtk_module.cxx
+++ b/src/plastimatch/base/dcmtk_module.cxx
@@ -34,12 +34,14 @@ Dcmtk_module::set_general_study (
rsm->get_study_date());
dataset->putAndInsertOFStringArray (DCM_StudyTime,
rsm->get_study_time());
- dataset->putAndInsertString (DCM_ReferringPhysicianName, "");
+ dataset->putAndInsertString (DCM_ReferringPhysicianName,
+ rsm->get_referring_physician_name());
dcmtk_copy_from_metadata (dataset, rsm->get_study_metadata(),
DCM_StudyID, "");
- dataset->putAndInsertOFStringArray (DCM_AccessionNumber, "");
- dcmtk_copy_from_metadata (dataset, rsm->get_study_metadata (),
- DCM_StudyDescription, "");
+ dataset->putAndInsertString (DCM_AccessionNumber,rsm->get_accession_number() );
+ dataset->putAndInsertString (DCM_StudyDescription,rsm->get_study_description() );
+ // dcmtk_copy_from_metadata (dataset, rsm->get_study_metadata (),
+ // DCM_StudyDescription, "");
dataset->putAndInsertOFStringArray (DCM_StudyID,
rsm->get_study_id());
}
@@ -75,10 +77,11 @@ Dcmtk_module::set_general_equipment (DcmDataset *dataset,
const Metadata::Pointer& meta)
{
dcmtk_copy_from_metadata (dataset, meta, DCM_Manufacturer, "Plastimatch");
- dcmtk_copy_from_metadata (dataset, meta, DCM_InstitutionName, "");
+ //dcmtk_copy_from_metadata (dataset, meta, DCM_InstitutionName, "");
dcmtk_copy_from_metadata (dataset, meta, DCM_StationName, "");
dcmtk_copy_from_metadata (dataset, meta, DCM_ManufacturerModelName,
"Plastimatch");
+ dcmtk_copy_from_metadata (dataset, meta, DCM_DeviceSerialNumber, "");
dcmtk_copy_from_metadata (dataset, meta, DCM_SoftwareVersions,
PLASTIMATCH_VERSION_STRING);
}
diff --git a/src/plastimatch/base/dcmtk_rdd.cxx b/src/plastimatch/base/dcmtk_rdd.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/dcmtk_rdd.h b/src/plastimatch/base/dcmtk_rdd.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/dcmtk_rt_study.cxx b/src/plastimatch/base/dcmtk_rt_study.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/dcmtk_rt_study.h b/src/plastimatch/base/dcmtk_rt_study.h
old mode 100755
new mode 100644
index 15461fa..9b14812
--- a/src/plastimatch/base/dcmtk_rt_study.h
+++ b/src/plastimatch/base/dcmtk_rt_study.h
@@ -38,6 +38,7 @@ public:
const char* get_rtss_series_uid () const;
const char* get_study_date () const;
const char* get_study_time () const;
+ const char* get_study_description () const;
const char* get_study_uid () const;
std::vector<Dcmtk_slice_data>* get_slice_data();
diff --git a/src/plastimatch/base/dcmtk_rtdose.cxx b/src/plastimatch/base/dcmtk_rtdose.cxx
old mode 100755
new mode 100644
index fd4ffba..10b32f1
--- a/src/plastimatch/base/dcmtk_rtdose.cxx
+++ b/src/plastimatch/base/dcmtk_rtdose.cxx
@@ -15,6 +15,7 @@
#include "dcmtk_rt_study_p.h"
#include "dcmtk_rtdose.h"
#include "dcmtk_series.h"
+#include "dcmtk_util.h"
#include "file_util.h"
#include "logfile.h"
#include "plm_image.h"
@@ -330,7 +331,7 @@ Dcmtk_rt_study::save_dose (const char *dicom_dir)
/* SOP common module */
dataset->putAndInsertString (DCM_SOPClassUID, UID_RTDoseStorage);
- dataset->putAndInsertString (DCM_SOPInstanceUID,
+ dcmtk_put (dataset, DCM_SOPInstanceUID,
d_ptr->rt_study_metadata->get_dose_instance_uid());
dataset->putAndInsertOFStringArray(DCM_InstanceCreationDate,
d_ptr->rt_study_metadata->get_study_date());
@@ -473,7 +474,7 @@ Dcmtk_rt_study::save_dose (const char *dicom_dir)
DCM_ReferencedStructureSetSequence, dcm_item, -2);
dcm_item->putAndInsertString (DCM_ReferencedSOPClassUID,
UID_RTStructureSetStorage);
- dcm_item->putAndInsertString (DCM_ReferencedSOPInstanceUID,
+ dcmtk_put (dcm_item, DCM_ReferencedSOPInstanceUID,
d_ptr->rt_study_metadata->get_rtstruct_instance_uid());
/* Convert image bytes to integer, then add to dataset */
diff --git a/src/plastimatch/base/dcmtk_rtplan.cxx b/src/plastimatch/base/dcmtk_rtplan.cxx
old mode 100755
new mode 100644
index e0dae3b..a2e55dc
--- a/src/plastimatch/base/dcmtk_rtplan.cxx
+++ b/src/plastimatch/base/dcmtk_rtplan.cxx
@@ -190,33 +190,54 @@ Dcmtk_rt_study::save_rtplan (const char *dicom_dir)
/* Frame of reference module */
dataset->putAndInsertString (DCM_FrameOfReferenceUID,
rsm->get_frame_of_reference_uid());
- dataset->putAndInsertString (DCM_PositionReferenceIndicator, "");
+ dataset->putAndInsertString (DCM_PositionReferenceIndicator,
+ rsm->get_position_reference_indicator());
/* General equipment module */
Dcmtk_module::set_general_equipment (dataset,rtplan_metadata);
/* RT general plan module */
- dataset->putAndInsertString (DCM_RTPlanLabel, "TESTONLY");
- dataset->putAndInsertString (DCM_RTPlanName, "TESTONLY");
- dataset->putAndInsertString (DCM_RTPlanDescription, "This is only a test");
- dataset->putAndInsertString (DCM_RTPlanDate, "");
- dataset->putAndInsertString (DCM_RTPlanTime, "");
+ dataset->putAndInsertString (DCM_RTPlanLabel, rtplan->rt_plan_label.c_str());
+ dataset->putAndInsertString (DCM_RTPlanName, rtplan->rt_plan_name.c_str());
+ //dataset->putAndInsertString (DCM_RTPlanDescription, "This is only a test");
+ dataset->putAndInsertString (DCM_RTPlanDate, rtplan->rt_plan_date.c_str());
+ dataset->putAndInsertString (DCM_RTPlanTime, rtplan->rt_plan_time.c_str());
- /* GCS TODO: Add support for PATIENT at some point */
- // dataset->putAndInsertString (DCM_RTPlanGeometry, "PATIENT");
- dataset->putAndInsertString (DCM_RTPlanGeometry, "TREATMENT_DEVICE");
+
+ if (rsm->get_rtstruct_instance_uid() == "") {
+ dataset->putAndInsertString (DCM_RTPlanGeometry, "TREATMENT_DEVICE");
+ } else {
+ dataset->putAndInsertString (DCM_RTPlanGeometry, "PATIENT");
+ DcmItem *rsss_item = 0;
+ dataset->findOrCreateSequenceItem (
+ DCM_ReferencedStructureSetSequence, rsss_item, -2);
+ dcmtk_put (rsss_item, DCM_ReferencedSOPClassUID,
+ UID_RTStructureSetStorage);
+ dcmtk_put (rsss_item, DCM_ReferencedSOPInstanceUID,
+ rsm->get_rtstruct_instance_uid());
+ }
+
+ if (rsm->get_dose_instance_uid() != "") {
+ DcmItem *rds_item = 0;
+ dataset->findOrCreateSequenceItem (
+ DCM_ReferencedDoseSequence, rds_item, -2);
+ dcmtk_put (rds_item, DCM_ReferencedSOPClassUID,
+ UID_RTDoseStorage);
+ dcmtk_put (rds_item, DCM_ReferencedSOPInstanceUID,
+ rsm->get_dose_instance_uid());
+ }
/* SOP common module */
/* GCS TODO: Figure out whether to use Plan or Ion Plan */
// dataset->putAndInsertString (DCM_SOPClassUID, UID_RTPlanStorage);
dataset->putAndInsertString (DCM_SOPClassUID, UID_RTIonPlanStorage);
- dataset->putAndInsertString (DCM_SOPInstanceUID,
- d_ptr->rt_study_metadata->get_dose_instance_uid());
- dataset->putAndInsertOFStringArray(DCM_InstanceCreationDate,
+ dcmtk_put (dataset, DCM_SOPInstanceUID,
+ d_ptr->rt_study_metadata->get_plan_instance_uid());
+ dataset->putAndInsertString(DCM_InstanceCreationDate,
d_ptr->rt_study_metadata->get_study_date());
- dataset->putAndInsertOFStringArray(DCM_InstanceCreationTime,
+ dataset->putAndInsertString(DCM_InstanceCreationTime,
d_ptr->rt_study_metadata->get_study_time());
-
+
/* RT prescription module * GCS TODO */
/* RT tolerance tables */
@@ -237,10 +258,21 @@ Dcmtk_rt_study::save_rtplan (const char *dicom_dir)
rtplan->tolerance_table_top_longitudinal);
dcmtk_put (iots_item, DCM_TableTopLateralPositionTolerance,
rtplan->tolerance_table_top_lateral);
+ dcmtk_put (iots_item, DCM_TableTopPitchAngleTolerance,
+ rtplan->tolerance_table_top_pitch);
+ dcmtk_put (iots_item, DCM_TableTopRollAngleTolerance,
+ rtplan->tolerance_table_top_roll);
dcmtk_put (iots_item, DCM_SnoutPositionTolerance,
rtplan->tolerance_snout_position);
}
-
+
+ /* RT patient setup module */
+ DcmItem *ps_item = 0;
+ dataset->findOrCreateSequenceItem (
+ DCM_PatientSetupSequence, ps_item, -2);
+ dcmtk_put (ps_item, DCM_PatientSetupNumber, 1);
+ dcmtk_put (ps_item, DCM_PatientPosition, rtplan->patient_position);
+
/* RT fraction scheme module */
DcmItem *fgs_item = 0;
dataset->findOrCreateSequenceItem (
@@ -249,11 +281,16 @@ Dcmtk_rt_study::save_rtplan (const char *dicom_dir)
dcmtk_put (fgs_item, DCM_NumberOfFractionsPlanned,
rtplan->number_of_fractions_planned);
dcmtk_put (fgs_item, DCM_NumberOfBeams, rtplan->beamlist.size());
+ dcmtk_put (fgs_item, DCM_FractionGroupDescription, rtplan->fraction_group_description.c_str());
+ dcmtk_put (fgs_item, DCM_NumberOfFractionPatternDigitsPerDay,
+ rtplan->number_of_fraction_pattern_digits_per_day.c_str());
+ dcmtk_put (fgs_item, DCM_RepeatFractionCycleLength, rtplan->repeat_fraction_cycle_length.c_str());
+ dcmtk_put (fgs_item, DCM_FractionPattern, rtplan->fraction_pattern.c_str());
for (size_t b = 0; b < rtplan->beamlist.size(); b++) {
DcmItem *rbs_item = 0;
fgs_item->findOrCreateSequenceItem (
DCM_ReferencedBeamSequence, rbs_item, -2);
- dcmtk_put (rbs_item, DCM_ReferencedBeamNumber, b);
+ dcmtk_put (rbs_item, DCM_ReferencedBeamNumber, b+1);
Rtplan_beam *beam = rtplan->beamlist[b];
dcmtk_put (rbs_item, DCM_BeamMeterset,
beam->final_cumulative_meterset_weight);
@@ -269,7 +306,7 @@ Dcmtk_rt_study::save_rtplan (const char *dicom_dir)
DcmItem *ib_item = 0;
dataset->findOrCreateSequenceItem (
DCM_IonBeamSequence, ib_item, -2);
- s = PLM_to_string (b);
+ s = PLM_to_string (b+1);
ib_item->putAndInsertString (DCM_BeamNumber, s.c_str());
Rtplan_beam *beam = rtplan->beamlist[b];
@@ -285,14 +322,28 @@ Dcmtk_rt_study::save_rtplan (const char *dicom_dir)
"STATIONARY");
#endif
ib_item->putAndInsertString (DCM_TreatmentMachineName,
- "Reference machine");
+ beam->treatment_machine_name.c_str());
+ ib_item->putAndInsertString (DCM_Manufacturer,
+ beam->manufacturer.c_str());
+ ib_item->putAndInsertString (DCM_InstitutionName,
+ beam->institution_name.c_str());
+ ib_item->putAndInsertString (DCM_InstitutionAddress,
+ beam->institution_address.c_str());
+ ib_item->putAndInsertString (DCM_InstitutionalDepartmentName,
+ beam->institutional_department_name.c_str());
+ ib_item->putAndInsertString (DCM_ManufacturerModelName,
+ beam->manufacturer_model_name.c_str());
ib_item->putAndInsertString (DCM_PrimaryDosimeterUnit, "NP");
if (rtplan->tolerance_table_label != "") {
dcmtk_put (ib_item, DCM_ReferencedToleranceTableNumber, 0);
}
+ if (rtplan->patient_position != "") {
+ dcmtk_put (ib_item, DCM_ReferencedPatientSetupNumber, 1);
+ }
ib_item->putAndInsertString (DCM_VirtualSourceAxisDistances,
- "2000\\2000");
- ib_item->putAndInsertString (DCM_TreatmentDeliveryType, "TREATMENT");
+ beam->virtual_source_axis_distances.c_str());
+ ib_item->putAndInsertString (DCM_TreatmentDeliveryType,
+ beam->treatment_delivery_type.c_str());
ib_item->putAndInsertString (DCM_NumberOfWedges, "0");
ib_item->putAndInsertString (DCM_NumberOfCompensators, "0");
ib_item->putAndInsertString (DCM_NumberOfBoli, "0");
@@ -318,11 +369,14 @@ Dcmtk_rt_study::save_rtplan (const char *dicom_dir)
DcmItem *rs_item = 0;
ib_item->findOrCreateSequenceItem (
DCM_RangeShifterSequence, rs_item, -2);
- rs_item->putAndInsertString (DCM_RangeShifterNumber, "0");
+ rs_item->putAndInsertString (DCM_RangeShifterNumber,
+ rtplan->range_shifter_number.c_str());
rs_item->putAndInsertString (DCM_RangeShifterID,
rtplan->range_shifter_id.c_str());
rs_item->putAndInsertString (DCM_AccessoryCode,
rtplan->range_shifter_code.c_str());
+ rs_item->putAndInsertString (DCM_RangeShifterType,
+ rtplan->range_shifter_type.c_str());
}
if (rtplan->range_modulator_id != "") {
DcmItem *rm_item = 0;
@@ -334,10 +388,15 @@ Dcmtk_rt_study::save_rtplan (const char *dicom_dir)
rm_item->putAndInsertString (DCM_AccessoryCode,
rtplan->range_modulator_code.c_str());
}
- ib_item->putAndInsertString (DCM_NumberOfRangeShifters, "0");
- ib_item->putAndInsertString (DCM_NumberOfLateralSpreadingDevices, "0");
+ ib_item->putAndInsertString (DCM_NumberOfRangeShifters,
+ rtplan->number_of_range_shifters.c_str());
+ ib_item->putAndInsertString (DCM_NumberOfLateralSpreadingDevices,"0");
ib_item->putAndInsertString (DCM_NumberOfRangeModulators, "0");
ib_item->putAndInsertString (DCM_PatientSupportType, "TABLE");
+ ib_item->putAndInsertString (DCM_PatientSupportID,
+ rtplan->patient_support_id.c_str());
+ ib_item->putAndInsertString (DCM_PatientSupportAccessoryCode,
+ rtplan->patient_support_accessory_code.c_str());
dcmtk_put (ib_item, DCM_FinalCumulativeMetersetWeight,
beam->final_cumulative_meterset_weight);
@@ -354,19 +413,52 @@ Dcmtk_rt_study::save_rtplan (const char *dicom_dir)
cp_item->putAndInsertString (DCM_CumulativeMetersetWeight,
s.c_str());
if (c == 0) {
- dcmtk_put (cp_item, DCM_SnoutPosition,
- beam->snout_position);
+ s = PLM_to_string (beam->snout_position);
+ cp_item->putAndInsertString (DCM_SnoutPosition, s.c_str());
+ s = PLM_to_string (beam->gantry_angle);
+ cp_item->putAndInsertString (DCM_GantryAngle, s.c_str());
+ cp_item->putAndInsertString (DCM_GantryRotationDirection,
+ beam->gantry_rotation_direction.c_str());
+ s = PLM_to_string (beam->gantry_pitch_angle);
+ cp_item->putAndInsertString (DCM_GantryPitchAngle, s.c_str());
+ cp_item->putAndInsertString (DCM_GantryPitchRotationDirection,
+ beam-> gantry_pitch_rotation_direction.c_str());
+ s = PLM_to_string (beam->beam_limiting_device_angle);
+ cp_item->putAndInsertString (DCM_BeamLimitingDeviceAngle, s.c_str());
+ cp_item->putAndInsertString (DCM_BeamLimitingDeviceRotationDirection,
+ beam-> beam_limiting_device_rotation_direction.c_str());
+ s = PLM_to_string (beam->patient_support_angle);
+ cp_item->putAndInsertString (DCM_PatientSupportAngle, s.c_str());
+ cp_item->putAndInsertString (DCM_PatientSupportRotationDirection,
+ beam-> patient_support_rotation_direction.c_str());
+ s = PLM_to_string (beam->table_top_vertical_position);
+ cp_item->putAndInsertString (DCM_TableTopVerticalPosition, s.c_str());
+ s = PLM_to_string (beam->table_top_longitudinal_position);
+ cp_item->putAndInsertString (DCM_TableTopLongitudinalPosition, s.c_str());
+ s = PLM_to_string (beam->table_top_lateral_position);
+ cp_item->putAndInsertString (DCM_TableTopLateralPosition, s.c_str());
+ s = PLM_to_string (beam->table_top_pitch_angle);
+ cp_item->putAndInsertString (DCM_TableTopPitchAngle, s.c_str());
+ cp_item->putAndInsertString (DCM_TableTopPitchRotationDirection,
+ beam-> table_top_pitch_rotation_direction.c_str());
+ s = PLM_to_string (beam->table_top_roll_angle);
+ cp_item->putAndInsertString (DCM_TableTopRollAngle, s.c_str());
+ cp_item->putAndInsertString (DCM_TableTopRollRotationDirection,
+ beam-> table_top_roll_rotation_direction.c_str());
+ s = string_format ("%f\\%f\\%f",
+ beam->isocenter_position[0],
+ beam->isocenter_position[1],
+ beam->isocenter_position[2]);
+ cp_item->putAndInsertString (DCM_IsocenterPosition, s.c_str());
}
s = PLM_to_string (cp->nominal_beam_energy);
cp_item->putAndInsertString (DCM_NominalBeamEnergy, s.c_str());
- s = PLM_to_string (cp->gantry_angle);
- cp_item->putAndInsertString (DCM_GantryAngle, s.c_str());
- cp_item->putAndInsertString (DCM_GantryRotationDirection,
- cp->gantry_rotation_direction.c_str());
+
s = PLM_to_string (cp->number_of_paintings);
cp_item->putAndInsertString (DCM_NumberOfPaintings,
s.c_str());
- cp_item->putAndInsertString (DCM_ScanSpotTuneID, cp->scan_spot_tune_id.c_str());
+ cp_item->putAndInsertString (DCM_ScanSpotTuneID,
+ cp->scan_spot_tune_id.c_str());
s = string_format ("%f\\%f", cp->scanning_spot_size[0],
cp->scanning_spot_size[1]);
cp_item->putAndInsertString (DCM_ScanningSpotSize,
diff --git a/src/plastimatch/base/dcmtk_rtss.cxx b/src/plastimatch/base/dcmtk_rtss.cxx
old mode 100755
new mode 100644
index 34ec7f1..8886d18
--- a/src/plastimatch/base/dcmtk_rtss.cxx
+++ b/src/plastimatch/base/dcmtk_rtss.cxx
@@ -14,6 +14,7 @@
#include "dcmtk_rt_study_p.h"
#include "dcmtk_series.h"
#include "dcmtk_slice_data.h"
+#include "dcmtk_util.h"
#include "file_util.h"
#include "logfile.h"
#include "metadata.h"
@@ -72,6 +73,10 @@ Dcmtk_rt_study::rtss_load (void)
}
/* FIX: load metadata such as patient name, etc. */
+ if (d_ptr->rt_study_metadata) {
+ d_ptr->rt_study_metadata->set_rtstruct_instance_uid (
+ ds_rtss->get_cstr (DCM_SOPInstanceUID));
+ }
/* ReferencedFrameOfReferenceSequence */
DcmSequenceOfItems *seq = 0;
@@ -269,7 +274,7 @@ Dcmtk_rt_study::save_rtss (const char *dicom_dir)
dataset->putAndInsertOFStringArray(DCM_InstanceCreatorUID,
PLM_UID_PREFIX);
dataset->putAndInsertString (DCM_SOPClassUID, UID_RTStructureSetStorage);
- dataset->putAndInsertString (DCM_SOPInstanceUID,
+ dcmtk_put (dataset, DCM_SOPInstanceUID,
d_ptr->rt_study_metadata->get_rtstruct_instance_uid());
dataset->putAndInsertOFStringArray (DCM_StudyDate,
d_ptr->rt_study_metadata->get_study_date());
diff --git a/src/plastimatch/base/dcmtk_rtss.h b/src/plastimatch/base/dcmtk_rtss.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/dcmtk_series.cxx b/src/plastimatch/base/dcmtk_series.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/dcmtk_series.h b/src/plastimatch/base/dcmtk_series.h
index 17617aa..cd6717b 100755
--- a/src/plastimatch/base/dcmtk_series.h
+++ b/src/plastimatch/base/dcmtk_series.h
@@ -21,7 +21,7 @@ class Plm_image;
typedef std::list<Dcmtk_file::Pointer> Dcmtk_file_list;
-class Dcmtk_series
+class PLMBASE_API Dcmtk_series
{
public:
Dcmtk_series ();
diff --git a/src/plastimatch/base/dcmtk_slice_data.h b/src/plastimatch/base/dcmtk_slice_data.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/dcmtk_uid.cxx b/src/plastimatch/base/dcmtk_uid.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/dcmtk_uid.h b/src/plastimatch/base/dcmtk_uid.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/dcmtk_util.cxx b/src/plastimatch/base/dcmtk_util.cxx
old mode 100755
new mode 100644
index fc747f6..6a9f49b
--- a/src/plastimatch/base/dcmtk_util.cxx
+++ b/src/plastimatch/base/dcmtk_util.cxx
@@ -46,6 +46,12 @@ dcmtk_put (DcmItem* item, const DcmTag &tag, const std::string& s)
return item->putAndInsertString (tag, s.c_str());
}
+OFCondition
+dcmtk_put (DcmItem* item, const DcmTag &tag, const char* s)
+{
+ return item->putAndInsertString (tag, s);
+}
+
template PLMBASE_API OFCondition dcmtk_put (DcmItem*, const DcmTag &, int);
template PLMBASE_API OFCondition dcmtk_put (DcmItem*, const DcmTag &, size_t);
template PLMBASE_API OFCondition dcmtk_put (DcmItem*, const DcmTag &, float);
diff --git a/src/plastimatch/base/dcmtk_util.h b/src/plastimatch/base/dcmtk_util.h
old mode 100755
new mode 100644
index 048abab..79250fa
--- a/src/plastimatch/base/dcmtk_util.h
+++ b/src/plastimatch/base/dcmtk_util.h
@@ -19,5 +19,7 @@ template<class T> PLMBASE_API OFCondition
dcmtk_put (DcmItem*, const DcmTag &, T);
PLMBASE_API OFCondition
dcmtk_put (DcmItem*, const DcmTag &, const std::string&);
+PLMBASE_API OFCondition
+dcmtk_put (DcmItem*, const DcmTag &, const char*);
#endif
diff --git a/src/plastimatch/base/dicom.dic b/src/plastimatch/base/dicom.dic
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/dicom_util.cxx b/src/plastimatch/base/dicom_util.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/dicom_util.h b/src/plastimatch/base/dicom_util.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/direction_cosines.cxx b/src/plastimatch/base/direction_cosines.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/direction_cosines.h b/src/plastimatch/base/direction_cosines.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/direction_matrices.cxx b/src/plastimatch/base/direction_matrices.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/direction_matrices.h b/src/plastimatch/base/direction_matrices.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/float_pair_list.cxx b/src/plastimatch/base/float_pair_list.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/float_pair_list.h b/src/plastimatch/base/float_pair_list.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/gaussian.cxx b/src/plastimatch/base/gaussian.cxx
old mode 100755
new mode 100644
index a45982b..4ccebaa
--- a/src/plastimatch/base/gaussian.cxx
+++ b/src/plastimatch/base/gaussian.cxx
@@ -32,7 +32,6 @@ create_ker (float coeff, int half_width)
for (i = 0; i < width; i++) {
ker[i] = ker[i] / sum;
}
-
return ker;
}
diff --git a/src/plastimatch/base/gaussian.h b/src/plastimatch/base/gaussian.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/gdcm1_dose.cxx b/src/plastimatch/base/gdcm1_dose.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/gdcm1_dose.h b/src/plastimatch/base/gdcm1_dose.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/gdcm1_file.cxx b/src/plastimatch/base/gdcm1_file.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/gdcm1_file.h b/src/plastimatch/base/gdcm1_file.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/gdcm1_rdd.cxx b/src/plastimatch/base/gdcm1_rdd.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/gdcm1_rdd.h b/src/plastimatch/base/gdcm1_rdd.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/gdcm1_rtss.cxx b/src/plastimatch/base/gdcm1_rtss.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/gdcm1_rtss.h b/src/plastimatch/base/gdcm1_rtss.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/gdcm1_series.cxx b/src/plastimatch/base/gdcm1_series.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/gdcm1_series.h b/src/plastimatch/base/gdcm1_series.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/gdcm1_series_helper_2.cxx b/src/plastimatch/base/gdcm1_series_helper_2.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/gdcm1_series_helper_2.h b/src/plastimatch/base/gdcm1_series_helper_2.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/gdcm1_util.cxx b/src/plastimatch/base/gdcm1_util.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/gdcm1_util.h b/src/plastimatch/base/gdcm1_util.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/gdcm2_util.cxx b/src/plastimatch/base/gdcm2_util.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/gdcm2_util.h b/src/plastimatch/base/gdcm2_util.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/hnd_io.cxx b/src/plastimatch/base/hnd_io.cxx
old mode 100644
new mode 100755
index 823ba66..3749c56
--- a/src/plastimatch/base/hnd_io.cxx
+++ b/src/plastimatch/base/hnd_io.cxx
@@ -85,7 +85,7 @@ hnd_set_proj_matrix (
vec3_copy (cam, tgt);
vec3_sub2 (cam, tmp);
- pmat->set (cam, tgt, vup, sid, pmat->ic, ps, proj->dim);
+ pmat->set (cam, tgt, vup, sid, pmat->ic, ps);
}
/* -----------------------------------------------------------------------
diff --git a/src/plastimatch/base/interpolate.cxx b/src/plastimatch/base/interpolate.cxx
old mode 100644
new mode 100755
index c355718..39305b7
--- a/src/plastimatch/base/interpolate.cxx
+++ b/src/plastimatch/base/interpolate.cxx
@@ -40,6 +40,50 @@ li_clamp (
*fa1 = 1.0f - *fa2;
}
+/* Clipping is done by setting fractional values to 0.f */
+static void
+li_noclamp (
+ plm_long* f, /* Output: x, y, or z coord of "floor" pixel */
+ float* fa1, /* Output: Fraction of interpolant for lower index voxel */
+ float* fa2, /* Output: Fraction of interpolant for upper index voxel */
+ float idx, /* Input: (Unrounded) pixel coordinate (in vox) */
+ plm_long dmax /* Input: Maximum coordinate in this dimension */
+)
+{
+ *f = FLOOR_PLM_LONG (idx);
+ *fa2 = idx - *f;
+ *fa1 = 1.0f - *fa2;
+ if (*f < 0) {
+ *fa1 = 0.f;
+ if (*f < -1) {
+ *fa2 = 0.f;
+ return;
+ }
+ }
+ if (*f > dmax - 2) {
+ *fa2 = 0.f;
+ if (*f > dmax - 1) {
+ *fa1 = 0.f;
+ return;
+ }
+ }
+}
+
+/* Simple li, with no processing */
+static void
+li (
+ plm_long* f, /* Output: x, y, or z coord of "floor" pixel */
+ float* fa1, /* Output: Fraction of interpolant for lower index voxel */
+ float* fa2, /* Output: Fraction of interpolant for upper index voxel */
+ float idx, /* Input: (Unrounded) pixel coordinate (in vox) */
+ plm_long dmax /* Input: Maximum coordinate in this dimension */
+)
+{
+ *f = FLOOR_PLM_LONG (idx);
+ *fa2 = idx - *f;
+ *fa1 = 1.0f - *fa2;
+}
+
void
li_clamp_3d (
const float mijk[3], /* Input: Unrounded pixel coordinates in vox */
@@ -47,7 +91,7 @@ li_clamp_3d (
plm_long mijk_r[3], /* Ouptut: "round" pixel in moving img in vox*/
float li_frac_1[3], /* Output: Fraction for upper index voxel */
float li_frac_2[3], /* Output: Fraction for lower index voxel */
- Volume *moving /* Input: Volume (for dims) */
+ const Volume *moving /* Input: Volume (for dims) */
)
{
li_clamp (mijk[0], moving->dim[0]-1, &mijk_f[0],
@@ -58,6 +102,36 @@ li_clamp_3d (
&mijk_r[2], &li_frac_1[2], &li_frac_2[2]);
}
+void
+li_noclamp_3d (
+ plm_long ijk_f[3],
+ float li_frac_1[3],
+ float li_frac_2[3],
+ const float ijk[3],
+ const plm_long dim[3]
+)
+{
+ li_noclamp (&ijk_f[0], &li_frac_1[0], &li_frac_2[0],
+ ijk[0], dim[0]);
+ li_noclamp (&ijk_f[1], &li_frac_1[1], &li_frac_2[1],
+ ijk[1], dim[1]);
+ li_noclamp (&ijk_f[2], &li_frac_1[2], &li_frac_2[2],
+ ijk[2], dim[2]);
+}
+
+void
+li_2d (
+ plm_long *ijk_f,
+ float *li_frac_1,
+ float *li_frac_2,
+ const float *ijk,
+ const plm_long *dim
+)
+{
+ li (&ijk_f[0], &li_frac_1[0], &li_frac_2[0], ijk[0], dim[0]);
+ li (&ijk_f[1], &li_frac_1[1], &li_frac_2[1], ijk[1], dim[1]);
+}
+
float
li_value (
float fx1, float fx2, /* Input: Fraction of upper, lower x voxel */
diff --git a/src/plastimatch/base/interpolate.h b/src/plastimatch/base/interpolate.h
old mode 100644
new mode 100755
index d6cb63a..85aba70
--- a/src/plastimatch/base/interpolate.h
+++ b/src/plastimatch/base/interpolate.h
@@ -16,14 +16,35 @@ PLMBASE_C_API void li_clamp (
plm_long* mar,
float* fa1, float* fa2
);
+
PLMBASE_C_API void li_clamp_3d (
const float mijk[3],
plm_long mijk_f[3],
plm_long mijk_r[3],
float li_frac_1[3],
float li_frac_2[3],
- Volume *moving
+ const Volume *moving
);
+
+/* Compute only fractional components, do not solve for value.
+ Clamping is not done; instead, fractions are set to 0.f if xyz
+ lies outside limits of dim. */
+PLMBASE_C_API void li_noclamp_3d (
+ plm_long ijk_f[3],
+ float li_frac_1[3],
+ float li_frac_2[3],
+ const float ijk[3],
+ const plm_long dim[3]
+);
+
+PLMBASE_C_API void li_2d (
+ plm_long *ijk_f,
+ float *li_frac_1,
+ float *li_frac_2,
+ const float *ijk,
+ const plm_long *dim
+);
+
PLMBASE_C_API float li_value (
float fx1, float fx2,
float fy1, float fy2,
diff --git a/src/plastimatch/base/itkClampCastImageFilter.h b/src/plastimatch/base/itkClampCastImageFilter.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/itkClampCastImageFilter.txx b/src/plastimatch/base/itkClampCastImageFilter.txx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/itk_bbox.cxx b/src/plastimatch/base/itk_bbox.cxx
new file mode 100644
index 0000000..9b89407
--- /dev/null
+++ b/src/plastimatch/base/itk_bbox.cxx
@@ -0,0 +1,50 @@
+/* -----------------------------------------------------------------------
+ See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
+ ----------------------------------------------------------------------- */
+#include "plmbase_config.h"
+#include <float.h>
+#include "itkContinuousIndex.h"
+#include "itkImageRegionConstIteratorWithIndex.h"
+
+#include "itk_bbox.h"
+#include "itk_image.h"
+
+void
+itk_bbox (UCharImageType::Pointer img, float *bbox)
+{
+ for (int d = 0; d < 3; d++)
+ {
+ bbox[2*d+0] = FLT_MAX;
+ bbox[2*d+1] = -FLT_MAX;
+ }
+
+ UCharImageType::RegionType region = img->GetLargestPossibleRegion();
+ itk::ImageRegionConstIteratorWithIndex< UCharImageType >
+ it (img, region);
+
+ for (it.GoToBegin(); !it.IsAtEnd(); ++it) {
+ unsigned char c = it.Get();
+ if (!c) {
+ continue;
+ }
+ /* If voxel is non-zero, loop through the eight corners of the
+ voxels, find their position, and set bounding box to contain */
+ itk::ContinuousIndex<float,3> cidx = it.GetIndex();
+ for (int i = 0; i < 8; i++) {
+ itk::ContinuousIndex<float,3> cidx_corner = cidx;
+ cidx_corner[0] += (i % 2) - 0.5;
+ cidx_corner[1] += ((i / 2) % 2) - 0.5;
+ cidx_corner[2] += (i / 4) - 0.5;
+ FloatPoint3DType point;
+ img->TransformContinuousIndexToPhysicalPoint (cidx_corner, point);
+ for (int d = 0; d < 3; d++) {
+ if (point[d] < bbox[2*d+0]) {
+ bbox[2*d+0] = point[d];
+ }
+ if (point[d] > bbox[2*d+1]) {
+ bbox[2*d+1] = point[d];
+ }
+ }
+ }
+ }
+}
diff --git a/src/plastimatch/base/dcmtk_uid.h b/src/plastimatch/base/itk_bbox.h
old mode 100755
new mode 100644
similarity index 64%
copy from src/plastimatch/base/dcmtk_uid.h
copy to src/plastimatch/base/itk_bbox.h
index ed97eb0..9aa97bc
--- a/src/plastimatch/base/dcmtk_uid.h
+++ b/src/plastimatch/base/itk_bbox.h
@@ -1,12 +1,13 @@
/* -----------------------------------------------------------------------
See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
----------------------------------------------------------------------- */
-#ifndef __dcmtk_uid_h__
-#define __dcmtk_uid_h__
+#ifndef _itk_bbox_h_
+#define _itk_bbox_h_
#include "plmbase_config.h"
+#include "itk_image_type.h"
-PLMBASE_API char*
-dcmtk_uid (char *uid, const char *uid_root);
+PLMBASE_API void
+itk_bbox (const UCharImageType::Pointer img, float *bbox);
#endif
diff --git a/src/plastimatch/base/itk_dicom_load.cxx b/src/plastimatch/base/itk_dicom_load.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/itk_dicom_load.h b/src/plastimatch/base/itk_dicom_load.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/itk_dicom_save.cxx b/src/plastimatch/base/itk_dicom_save.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/itk_dicom_save.h b/src/plastimatch/base/itk_dicom_save.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/itk_directions.cxx b/src/plastimatch/base/itk_directions.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/itk_directions.h b/src/plastimatch/base/itk_directions.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/itk_image_clone.cxx b/src/plastimatch/base/itk_image_clone.cxx
index ca771b3..ecacb31 100644
--- a/src/plastimatch/base/itk_image_clone.cxx
+++ b/src/plastimatch/base/itk_image_clone.cxx
@@ -7,11 +7,10 @@
#include "itkImageDuplicator.h"
#include "itk_image_clone.h"
+#include "itk_image_create.h"
#include "itk_image_type.h"
+#include "plm_image_header.h"
-/* -----------------------------------------------------------------------
- Casting image types
- ----------------------------------------------------------------------- */
template<class T>
T
itk_image_clone (T image)
@@ -25,6 +24,23 @@ itk_image_clone (T image)
return duplicator->GetOutput();
}
+template<class T>
+T
+itk_image_clone_empty (T image)
+{
+ T img = T::ObjectType::New ();
+ img->SetOrigin (image->GetOrigin());
+ img->SetSpacing (image->GetSpacing());
+ img->SetDirection (image->GetDirection());
+ img->SetRegions (image->GetLargestPossibleRegion());
+ img->Allocate ();
+ img->FillBuffer (static_cast<typename T::ObjectType::PixelType>(0));
+
+ return img;
+}
+
/* Explicit instantiations */
template PLMBASE_API FloatImageType::Pointer itk_image_clone (FloatImageType::Pointer);
+
+template PLMBASE_API UCharImageType::Pointer itk_image_clone_empty (UCharImageType::Pointer);
diff --git a/src/plastimatch/base/itk_image_clone.h b/src/plastimatch/base/itk_image_clone.h
index 2995214..6a13ab2 100644
--- a/src/plastimatch/base/itk_image_clone.h
+++ b/src/plastimatch/base/itk_image_clone.h
@@ -11,4 +11,6 @@
Function prototypes
----------------------------------------------------------------------- */
template<class T> PLMBASE_API T itk_image_clone (T image);
+template<class T> PLMBASE_API T itk_image_clone_empty (T image);
+
#endif
diff --git a/src/plastimatch/base/itk_image_load_char.cxx b/src/plastimatch/base/itk_image_load_char.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/itk_image_load_double.cxx b/src/plastimatch/base/itk_image_load_double.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/itk_image_type.h b/src/plastimatch/base/itk_image_type.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/itk_metadata.cxx b/src/plastimatch/base/itk_metadata.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/itk_metadata.h b/src/plastimatch/base/itk_metadata.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/itk_pointset.cxx b/src/plastimatch/base/itk_pointset.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/itk_pointset.h b/src/plastimatch/base/itk_pointset.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/parameter_parser.cxx b/src/plastimatch/base/parameter_parser.cxx
index 7cf55c8..4097e95 100644
--- a/src/plastimatch/base/parameter_parser.cxx
+++ b/src/plastimatch/base/parameter_parser.cxx
@@ -18,6 +18,7 @@
Parameter_parser::Parameter_parser () {
key_regularization = true;
+ default_index = "";
}
Plm_return_code
@@ -69,16 +70,10 @@ Parameter_parser::parse_config_string (
/* Process "key=value" */
std::string key;
std::string val;
- size_t key_loc = buf.find ("=");
- if (key_loc == std::string::npos) {
- key = buf;
- val = "";
- } else {
- key = buf.substr (0, key_loc);
- val = buf.substr (key_loc+1);
+ if (!split_key_val (buf, key, val)) {
+ lprintf ("Parse error: %s\n", buf_ori.c_str());
+ return PLM_ERROR;
}
- key = string_trim (key);
- val = string_trim (val);
/* Key becomes lowercase, with "_" & "-" unified */
if (this->key_regularization) {
@@ -96,10 +91,21 @@ Parameter_parser::parse_config_string (
continue;
}
- Plm_return_code rc = this->set_key_value (section, key, val);
+ /* Handle key[index]=value */
+ std::string array;
+ std::string index;
+ if (!split_array_index (key, array, index)) {
+ lprintf ("Parse error: %s\n", buf_ori.c_str());
+ return PLM_ERROR;
+ }
+ if (index == "") {
+ index = default_index;
+ }
+
+ Plm_return_code rc = this->set_key_value (section, array, index, val);
if (rc != PLM_SUCCESS) {
lprintf ("Parse error: %s\n", buf_ori.c_str());
- return rc;
+ return PLM_ERROR;
}
}
@@ -117,6 +123,20 @@ Parameter_parser::enable_key_regularization (
this->key_regularization = enable;
}
+void
+Parameter_parser::set_default_index (
+ std::string& default_index)
+{
+ this->default_index = default_index;
+}
+
+void
+Parameter_parser::set_default_index (
+ const char *default_index)
+{
+ this->default_index = std::string(default_index);
+}
+
Plm_return_code
Parameter_parser::parse_config_string (
const std::string& config_string
diff --git a/src/plastimatch/base/parameter_parser.h b/src/plastimatch/base/parameter_parser.h
index f21bbdc..5725abe 100644
--- a/src/plastimatch/base/parameter_parser.h
+++ b/src/plastimatch/base/parameter_parser.h
@@ -7,11 +7,17 @@
#include "plmbase_config.h"
#include "plm_return_code.h"
+/*! \brief
+ * The Parameter_parser class is an abstract base class which is used
+ * to parse ini-style file formats that control the registration, mabs,
+ * and dose calculation codes.
+ */
class PLMBASE_API Parameter_parser {
public:
Parameter_parser ();
public:
bool key_regularization;
+ std::string default_index;
public:
/* Callbacks */
virtual Plm_return_code begin_section (
@@ -21,6 +27,7 @@ public:
virtual Plm_return_code set_key_value (
const std::string& section,
const std::string& key,
+ const std::string& index,
const std::string& val) = 0;
/* Pass in "true" to enable key regularization, or "false" to
@@ -29,6 +36,11 @@ public:
bool enable
);
+ /*! \brief Choose what index is passed to set_key_value()
+ when no index is found in the file. Default is "". */
+ void set_default_index (std::string& default_index);
+ void set_default_index (const char *default_index);
+
/* Return zero if config string is correctly parsed */
Plm_return_code parse_config_string (
const char* config_string
diff --git a/src/plastimatch/base/plm_file_format.cxx b/src/plastimatch/base/plm_file_format.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/plm_file_format.h b/src/plastimatch/base/plm_file_format.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/plm_image_header.cxx b/src/plastimatch/base/plm_image_header.cxx
index 8c3cfd7..7ae4ef3 100644
--- a/src/plastimatch/base/plm_image_header.cxx
+++ b/src/plastimatch/base/plm_image_header.cxx
@@ -82,6 +82,12 @@ Plm_image_header::Plm_image_header (const Volume_header& vh)
this->set (vh);
}
+Plm_image_header::Plm_image_header (const Volume::Pointer& vol)
+{
+ d_ptr = new Plm_image_header_private;
+ this->set (vol);
+}
+
Plm_image_header::Plm_image_header (const Volume& vol)
{
d_ptr = new Plm_image_header_private;
@@ -322,6 +328,13 @@ Plm_image_header::set_from_volume_header (const Volume_header& vh)
}
void
+Plm_image_header::set (const Volume::Pointer& vol)
+{
+ this->set_from_gpuit (vol->dim, vol->origin,
+ vol->spacing, vol->direction_cosines);
+}
+
+void
Plm_image_header::set (const Volume& vol)
{
this->set_from_gpuit (vol.dim, vol.origin,
diff --git a/src/plastimatch/base/plm_image_header.h b/src/plastimatch/base/plm_image_header.h
index 871d562..dfeb880 100644
--- a/src/plastimatch/base/plm_image_header.h
+++ b/src/plastimatch/base/plm_image_header.h
@@ -42,6 +42,7 @@ public:
Plm_image_header (const Plm_image& pli);
Plm_image_header (const Plm_image::Pointer& pli);
Plm_image_header (const Volume_header& vh);
+ Plm_image_header (const Volume::Pointer& vol);
Plm_image_header (const Volume& vol);
Plm_image_header (const Volume* vol);
Plm_image_header (Volume* vol);
@@ -86,6 +87,7 @@ public:
void set_from_plm_image (const Plm_image::Pointer& pli);
void set_from_volume_header (const Volume_header& vh);
void set (const Volume_header& vh);
+ void set (const Volume::Pointer& vol);
void set (const Volume& vol);
void set (const Volume* vol);
void set (const RegionType& region, const OriginType& origin,
diff --git a/src/plastimatch/base/plm_image_type.cxx b/src/plastimatch/base/plm_image_type.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/proj_image.cxx b/src/plastimatch/base/proj_image.cxx
index f076da8..da40555 100644
--- a/src/plastimatch/base/proj_image.cxx
+++ b/src/plastimatch/base/proj_image.cxx
@@ -146,7 +146,7 @@ raw_save (Proj_image *proj, const char* img_filename)
{
FILE* fp;
- fp = fopen (img_filename, "wb");
+ fp = plm_fopen (img_filename, "wb");
if (!fp) {
fprintf (stderr, "Can't open file %s for write\n", img_filename);
exit (-1);
@@ -212,7 +212,7 @@ pfm_save (Proj_image *proj, const char* img_filename)
FILE* fp;
make_parent_directories (img_filename);
- fp = fopen (img_filename, "wb");
+ fp = plm_fopen (img_filename, "wb");
if (!fp) {
fprintf (stderr, "Can't open file %s for write\n", img_filename);
exit (-1);
@@ -235,7 +235,7 @@ pgm_save (Proj_image *proj, const char* img_filename)
int i;
make_parent_directories (img_filename);
- fp = fopen (img_filename, "wb");
+ fp = plm_fopen (img_filename, "wb");
if (!fp) {
fprintf (stderr, "Can't open file %s for write\n", img_filename);
exit (-1);
diff --git a/src/plastimatch/base/proj_matrix.cxx b/src/plastimatch/base/proj_matrix.cxx
old mode 100644
new mode 100755
index 1cd1c17..790cd60
--- a/src/plastimatch/base/proj_matrix.cxx
+++ b/src/plastimatch/base/proj_matrix.cxx
@@ -140,8 +140,7 @@ Proj_matrix::set (
const double* vup,
double sid,
const double* ic,
- const double* ps,
- const int* ires
+ const double* ps
)
{
const int cols = 4;
@@ -151,7 +150,7 @@ Proj_matrix::set (
vec3_copy (this->cam, cam);
this->sid = sid;
- this->sad = vec3_len (cam);
+ this->sad = vec3_dist (cam, tgt);
this->ic[0] = ic[0];
this->ic[1] = ic[1];
@@ -249,3 +248,19 @@ Proj_matrix::get_prt (
{
vec3_copy (prt, &this->extrinsic[0]);
}
+
+void
+Proj_matrix::project_h (double* ij, const double* xyz) const
+{
+ mat43_mult_vec4 (ij, this->matrix, xyz);
+}
+
+void
+Proj_matrix::project (double* ij, const double* xyz) const
+{
+ ij[0] = vec3_dot(&this->matrix[0], xyz) + this->matrix[3];
+ ij[1] = vec3_dot(&this->matrix[4], xyz) + this->matrix[7];
+ double h = vec3_dot(&this->matrix[8], xyz) + this->matrix[11];
+ ij[0] = this->ic[0] + ij[0] / h;
+ ij[1] = this->ic[1] + ij[1] / h;
+}
diff --git a/src/plastimatch/base/proj_matrix.h b/src/plastimatch/base/proj_matrix.h
old mode 100644
new mode 100755
index 2ab757f..793b871
--- a/src/plastimatch/base/proj_matrix.h
+++ b/src/plastimatch/base/proj_matrix.h
@@ -34,11 +34,21 @@ public:
const double* vup,
double sid,
const double* ic,
- const double* ps,
- const int* ires
+ const double* ps
);
void set (const std::string& s);
+ /* Project 3D coordinate xyz of cartesian space
+ into 2D coordinate ij coordinate on projection plane.
+ In this version, the inputs and outputs are homogenous,
+ not cartesian. */
+ void project_h (double* ij, const double* xyz) const;
+ /* Project 3D coordinate xyz of cartesian space
+ into 2D coordinate ij coordinate on projection plane.
+ In this version, the inputs and outputs are cartesian,
+ not homogenous. */
+ void project (double* ij, const double* xyz) const;
+
void save (const char *fn);
void debug ();
Proj_matrix* clone ();
diff --git a/src/plastimatch/base/proj_volume.cxx b/src/plastimatch/base/proj_volume.cxx
old mode 100644
new mode 100755
index 9dd611d..e07f499
--- a/src/plastimatch/base/proj_volume.cxx
+++ b/src/plastimatch/base/proj_volume.cxx
@@ -40,9 +40,9 @@ public:
public:
Volume::Pointer vol;
Proj_matrix *pmat;
- int num_steps;
+ plm_long num_steps;
double step_length;
- int image_dim[2];
+ plm_long image_dim[2];
double image_spacing[2];
double clipping_dist[2];
double nrm[3];
@@ -78,7 +78,7 @@ Proj_volume::set_geometry (
const double iso[3], // position of isocenter (mm)
const double vup[3], // dir to "top" of projection plane
double sid, // dist from proj plane to source (mm)
- const int image_dim[2], // resolution of image
+ const plm_long image_dim[2], // resolution of image
const double image_center[2], // image center (pixels)
const double image_spacing[2], // pixel size (mm)
const double clipping_dist[2], // dist from src to clipping planes (mm)
@@ -90,8 +90,8 @@ Proj_volume::set_geometry (
/* save input settings */
d_ptr->image_dim[0] = image_dim[0];
d_ptr->image_dim[1] = image_dim[1];
- d_ptr->image_spacing[0] = image_spacing[0];
- d_ptr->image_spacing[1] = image_spacing[1];
+ d_ptr->image_spacing[0] = image_spacing[0];
+ d_ptr->image_spacing[1] = image_spacing[1];
d_ptr->src[0] = src[0];
d_ptr->src[1] = src[1];
d_ptr->src[2] = src[2];
@@ -107,8 +107,7 @@ Proj_volume::set_geometry (
vup,
sid,
image_center,
- image_spacing,
- image_dim
+ image_spacing
);
/* populate aperture orientation unit vectors */
@@ -161,7 +160,7 @@ Proj_volume::set_clipping_dist (const double clipping_dist[2])
{
d_ptr->clipping_dist[0] = clipping_dist[0];
d_ptr->clipping_dist[1] = clipping_dist[1];
- d_ptr->num_steps = (int) ceil (
+ d_ptr->num_steps = (plm_long) ceil (
(clipping_dist[1] - clipping_dist[0]) / d_ptr->step_length);
}
@@ -179,18 +178,24 @@ Proj_volume::allocate ()
direction_cosines, PT_FLOAT, 1);
}
-const int*
+const plm_long*
Proj_volume::get_image_dim ()
{
return d_ptr->image_dim;
}
-int
+plm_long
Proj_volume::get_image_dim (int dim)
{
return d_ptr->image_dim [dim];
}
+plm_long
+Proj_volume::get_num_steps ()
+{
+ return d_ptr->num_steps;
+}
+
const double*
Proj_volume::get_incr_c ()
{
@@ -217,7 +222,7 @@ Proj_volume::get_proj_matrix ()
}
const double*
-Proj_volume::get_src ()
+Proj_volume::get_src () const
{
return d_ptr->src;
}
@@ -235,7 +240,7 @@ Proj_volume::get_clipping_dist ()
}
double
-Proj_volume::get_step_length ()
+Proj_volume::get_step_length () const
{
return d_ptr->step_length;
}
@@ -259,6 +264,18 @@ Proj_volume::get_vol () const
}
void
+Proj_volume::project_h (double* ij, const double* xyz) const
+{
+ d_ptr->pmat->project_h (ij, xyz);
+}
+
+void
+Proj_volume::project (double* ij, const double* xyz) const
+{
+ d_ptr->pmat->project (ij, xyz);
+}
+
+void
Proj_volume::save_img (const char *filename)
{
Plm_image(d_ptr->vol).save_image(filename);
@@ -355,24 +372,24 @@ Proj_volume::load_header (const char* filename)
break;
}
- std::string tag, val;
- if (!split_tag_val (line, tag, val)) {
+ if (line.find('=') == std::string::npos) {
/* No "=" found. */
break;
}
+ int a, b;
+ float f, g;
int rc;
- rc = sscanf (line.c_str(), "num_steps = %d\n", &d_ptr->num_steps);
+ rc = sscanf (line.c_str(), "num_steps = %d\n", &a);
+ d_ptr->num_steps = a;
if (rc == 1) continue;
- float f, g;
rc = sscanf (line.c_str(), "step_length = %f\n", &f);
if (rc == 1) {
d_ptr->step_length = f;
continue;
}
- int a, b;
rc = sscanf (line.c_str(), "image_dim = %d %d\n", &a, &b);
if (rc == 3) {
d_ptr->image_dim[0] = a;
diff --git a/src/plastimatch/base/proj_volume.h b/src/plastimatch/base/proj_volume.h
old mode 100644
new mode 100755
index 2b43a74..a62e419
--- a/src/plastimatch/base/proj_volume.h
+++ b/src/plastimatch/base/proj_volume.h
@@ -6,6 +6,7 @@
#include "plmbase_config.h"
#include <string>
+#include "plm_int.h"
class Proj_matrix;
class Proj_volume_private;
@@ -30,23 +31,24 @@ public:
const double iso[3], // position of isocenter (mm)
const double vup[3], // dir to "top" of projection plane
double sid, // dist from proj plane to source (mm)
- const int image_dim[2], // resolution of image
+ const plm_long image_dim[2], // resolution of image
const double image_center[2], // image center (pixels)
const double image_spacing[2], // pixel size (mm)
const double clipping_dist[2], // dist from src to clipping planes (mm)
const double step_length // spacing between planes
);
void set_clipping_dist (const double clipping_dist[2]);
- const int* get_image_dim ();
- int get_image_dim (int dim);
+ const plm_long* get_image_dim ();
+ plm_long get_image_dim (int dim);
+ plm_long get_num_steps ();
const double* get_incr_c ();
const double* get_incr_r ();
Proj_matrix *get_proj_matrix ();
const double* get_nrm ();
- const double* get_src ();
+ const double* get_src () const;
const double* get_iso ();
const double* get_clipping_dist();
- double get_step_length ();
+ double get_step_length () const;
const double* get_ul_room ();
Volume *get_vol ();
const Volume *get_vol () const;
@@ -66,6 +68,17 @@ public:
void load_projv (const char* filename);
void load_projv (const std::string& filename);
+ /* Project 3D coordinate xyz of cartesian space
+ into 2D coordinate ij coordinate on projection plane.
+ In this version, the inputs and outputs are homogenous,
+ not cartesian. */
+ void project_h (double* ij, const double* xyz) const;
+ /* Project 3D coordinate xyz of cartesian space
+ into 2D coordinate ij coordinate on projection plane.
+ In this version, the inputs and outputs are cartesian,
+ not homogenous. */
+ void project (double* ij, const double* xyz) const;
+
void debug ();
};
diff --git a/src/plastimatch/base/pwlut.cxx b/src/plastimatch/base/pwlut.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/pwlut.h b/src/plastimatch/base/pwlut.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/ray_trace.h b/src/plastimatch/base/ray_trace.h
index 7cea27e..df2cc6e 100644
--- a/src/plastimatch/base/ray_trace.h
+++ b/src/plastimatch/base/ray_trace.h
@@ -15,10 +15,15 @@ class Volume_limit;
#define DRR_PLANE_RAY_TOLERANCE 1e-8
#define DRR_STRIDE_TOLERANCE 1e-10
#define DRR_HUGE_DOUBLE 1e10
-#define DRR_LEN_TOLERANCE 1e-6
#define DRR_TOPLANE_TOLERANCE 1e-7
#define DRR_BOUNDARY_TOLERANCE 1e-6
+/* GCS FIX: "Temporary" fix against overshooting image boundary
+ when ray tracing. This fix should be replaced with something
+ more robust, such as an explicit bounds check. */
+//#define DRR_LEN_TOLERANCE 1e-6
+#define DRR_LEN_TOLERANCE 2e-5
+
#define DRR_MSD_NUM_BINS 60
#define DRR_PREPROCESS_ATTENUATION 1
diff --git a/src/plastimatch/base/ray_trace_uniform.cxx b/src/plastimatch/base/ray_trace_uniform.cxx
index aaeca65..38fc824 100644
--- a/src/plastimatch/base/ray_trace_uniform.cxx
+++ b/src/plastimatch/base/ray_trace_uniform.cxx
@@ -33,9 +33,6 @@ ray_trace_uniform (
double ip2[3];
double phy_step[3];
- int ai[3]={0,0,0};
- double frac[3]={0.0, 0.0, 0.0};
-
float pix_density;
double pt;
double rlen;
@@ -54,7 +51,6 @@ ray_trace_uniform (
if (!volume_limit_clip_segment (vol_limit, ip1, ip2, ip1in, ip2in)) {
return;
}
-
ps[0] = vol->spacing[0];
ps[1] = vol->spacing[1];
@@ -80,8 +76,6 @@ ray_trace_uniform (
ipx[1] = ip1[1] + phy_step[1] * z;
ipx[2] = ip1[2] + phy_step[2] * z;
- // NEW VERSION - Compute CT volume indices and their fraction @ point + interpolation
-
mijk[0] = (float) ((ipx[0] - vol->origin[0])/ps[0]);
mijk[1] = (float) ((ipx[1] - vol->origin[1])/ps[1]);
mijk[2] = (float) ((ipx[2] - vol->origin[2])/ps[2]);
diff --git a/src/plastimatch/base/rpl_volume.cxx b/src/plastimatch/base/rpl_volume.cxx
old mode 100644
new mode 100755
index 90c62e2..412eb8f
--- a/src/plastimatch/base/rpl_volume.cxx
+++ b/src/plastimatch/base/rpl_volume.cxx
@@ -35,6 +35,27 @@
static bool global_debug = false;
#endif
+//20140827_YKP
+//col0 = HU, col1 = Relative stopping power
+//Table: XiO, ctedproton 2007 provided by Yoost
+extern const double lookup_PrSTPR_XiO_MGH[][2] ={
+ -1000.0, 0.01,
+ 0.0, 1.0,
+ 40.0, 1.04,
+ 1000.0, 1.52,
+ 2000.0, 2.02,
+ 3000.0, 2.55,
+};
+
+extern const double lookup_PrSTPR_XiO_MGH[][2];
+
+static void rpl_callback_accum (
+ void *callback_data, size_t vox_index,
+ double vox_len, float vox_value);
+static void rpl_callback_sample (
+ void *callback_data, size_t vox_index,
+ double vox_len, float vox_value);
+
static void rpl_ray_trace_callback_ct_density (
void *callback_data,
size_t vox_index,
@@ -77,14 +98,12 @@ public:
Plm_image::Pointer ct;
Volume_limit ct_limit;
Ray_data *ray_data;
+ // Clipping distances are computed from aperture plane, not from source
double front_clipping_dist;
double back_clipping_dist;
-
Aperture::Pointer aperture;
- double max_wed;
- double min_wed;
- double min_distance_target;
-
+ Rpl_volume_ray_trace_start rvrts;
+
public:
Rpl_volume_private () {
proj_vol = new Proj_volume;
@@ -93,9 +112,7 @@ public:
front_clipping_dist = DBL_MAX;
back_clipping_dist = -DBL_MAX;
aperture = Aperture::New ();
- min_wed = 0.;
- max_wed = 0.;
- min_distance_target = 0.;
+ rvrts = RAY_TRACE_START_AT_RAY_VOLUME_INTERSECTION;
}
~Rpl_volume_private () {
delete proj_vol;
@@ -119,7 +136,7 @@ Rpl_volume::set_geometry (
const double iso[3], // position of isocenter (mm)
const double vup[3], // dir to "top" of projection plane
double sid, // dist from proj plane to source (mm)
- const int image_dim[2], // resolution of image
+ const plm_long image_dim[2], // resolution of image
const double image_center[2], // image center (pixels)
const double image_spacing[2], // pixel size (mm)
const double step_length // spacing between planes
@@ -146,6 +163,27 @@ Rpl_volume::set_geometry (
}
void
+Rpl_volume::clone_geometry (const Rpl_volume *rv)
+{
+ this->set_geometry (
+ rv->d_ptr->proj_vol->get_src(),
+ rv->d_ptr->proj_vol->get_iso(),
+ rv->get_aperture()->vup,
+ rv->get_aperture()->get_distance(),
+ rv->get_aperture()->get_dim(),
+ rv->get_aperture()->get_center(),
+ rv->get_aperture()->get_spacing(),
+ rv->d_ptr->proj_vol->get_step_length());
+}
+
+void
+Rpl_volume::set_ray_trace_start (Rpl_volume_ray_trace_start rvrts)
+{
+ printf ("Setting RVRTS = %d\n", (int) rvrts);
+ d_ptr->rvrts = rvrts;
+}
+
+void
Rpl_volume::set_ct_volume (Plm_image::Pointer& ct_volume)
{
d_ptr->ct = ct_volume;
@@ -172,18 +210,30 @@ Rpl_volume::set_aperture (Aperture::Pointer& ap)
d_ptr->aperture = ap;
}
+const plm_long*
+Rpl_volume::get_image_dim ()
+{
+ return d_ptr->proj_vol->get_image_dim();
+}
+
+plm_long
+Rpl_volume::get_num_steps ()
+{
+ return d_ptr->proj_vol->get_num_steps();
+}
+
/* 1D interpolation */
double
-Rpl_volume::get_rgdepth (
- int ap_ij[2], /* I: aperture index */
- double dist /* I: distance from aperture in mm */
-)
+Rpl_volume::get_value (
+ plm_long ap_ij[2], /* I: aperture index */
+ double dist /* I: distance from aperture in mm */
+) const
{
plm_long idx1, idx2;
plm_long ijk[3];
double rg1, rg2, rgdepth, frac;
- Proj_volume *proj_vol = this->get_proj_volume ();
- Volume *vol = this->get_vol();
+ const Proj_volume *proj_vol = this->get_proj_volume ();
+ const Volume *vol = this->get_vol();
float* d_img = (float*) vol->img;
if (dist < 0) {
@@ -223,13 +273,13 @@ Rpl_volume::get_rgdepth (
/* 3D interpolation */
double
-Rpl_volume::get_rgdepth (
+Rpl_volume::get_value (
double ap_ij[2], /* I: aperture index */
double dist /* I: distance from aperture in mm */
-)
+) const
{
- Proj_volume *proj_vol = this->get_proj_volume ();
- Volume *vol = this->get_vol();
+ const Proj_volume *proj_vol = this->get_proj_volume ();
+ const Volume *vol = this->get_vol();
if (dist < 0) {
return 0.0;
@@ -246,17 +296,17 @@ Rpl_volume::get_rgdepth (
/* Lookup radiological path length to a voxel in world space */
double
-Rpl_volume::get_rgdepth (
+Rpl_volume::get_value (
const double* ct_xyz /* I: location of voxel in world space */
-)
+) const
{
int ap_ij[2], ap_idx;
double ap_xy[3];
double dist, rgdepth = 0.;
- int debug = 0;
+ bool debug = false;
/* A couple of abbreviations */
- const int *ires = d_ptr->proj_vol->get_image_dim();
+ const plm_long *ires = d_ptr->proj_vol->get_image_dim();
Proj_matrix *pmat = d_ptr->proj_vol->get_proj_matrix();
if (debug) {
@@ -264,9 +314,7 @@ Rpl_volume::get_rgdepth (
}
/* Back project the voxel to the aperture plane */
- mat43_mult_vec3 (ap_xy, pmat->matrix, ct_xyz);
- ap_xy[0] = pmat->ic[0] + ap_xy[0] / ap_xy[2];
- ap_xy[1] = pmat->ic[1] + ap_xy[1] / ap_xy[2];
+ d_ptr->proj_vol->project (ap_xy, ct_xyz);
/* Make sure value is not inf or NaN */
if (!is_number (ap_xy[0]) || !is_number (ap_xy[1])) {
@@ -287,9 +335,8 @@ Rpl_volume::get_rgdepth (
return -1;
}
- ap_idx = ap_ij[1] * ires[0] + ap_ij[0];
-
/* Look up pre-computed data for this ray */
+ ap_idx = ap_ij[1] * ires[0] + ap_ij[0];
Ray_data *ray_data = &d_ptr->ray_data[ap_idx];
double *ap_xyz = ray_data->p2;
@@ -300,11 +347,16 @@ Rpl_volume::get_rgdepth (
/* Compute distance from aperture to voxel */
dist = vec3_dist (ap_xyz, ct_xyz);
- /* Subtract off standoff distance */
- dist -= d_ptr->front_clipping_dist;
+ // Subtract off standoff distance. Nearest neighbor aperture index
+ // is used for this calculation.
+ if (d_ptr->rvrts == RAY_TRACE_START_AT_RAY_VOLUME_INTERSECTION) {
+ dist -= ray_data->front_dist;
+ } else {
+ dist -= d_ptr->front_clipping_dist;
+ }
/* Retrieve the radiographic depth */
- rgdepth = this->get_rgdepth (ap_xy, dist);
+ rgdepth = this->get_value (ap_xy, dist);
return rgdepth;
}
@@ -334,16 +386,17 @@ Volume_limit* Rpl_volume::get_ct_limit()
return &d_ptr->ct_limit;
}
-void Rpl_volume::set_ray(Ray_data *ray)
+void Rpl_volume::set_ray_data (Ray_data *ray)
{
d_ptr->ray_data = ray;
}
-Ray_data* Rpl_volume::get_Ray_data()
+
+Ray_data* Rpl_volume::get_ray_data()
{
return d_ptr->ray_data;
}
-void Rpl_volume::set_front_clipping_plane(double front_clip)
+void Rpl_volume::set_front_clipping_plane (double front_clip)
{
d_ptr->front_clipping_dist = front_clip;
}
@@ -357,33 +410,16 @@ void Rpl_volume::set_back_clipping_plane(double back_clip)
{
d_ptr->back_clipping_dist = back_clip;
}
+
double Rpl_volume::get_back_clipping_plane() const
{
return d_ptr->back_clipping_dist;
}
-void
-Rpl_volume::set_minimum_distance_target(double min)
-{
- d_ptr->min_distance_target = min;
-}
-
-double
-Rpl_volume::get_minimum_distance_target()
-{
- return d_ptr->min_distance_target;
-}
-
double
-Rpl_volume::get_max_wed ()
+Rpl_volume::get_step_length () const
{
- return d_ptr->max_wed;
-}
-
-double
-Rpl_volume::get_min_wed ()
-{
- return d_ptr->min_wed;
+ return d_ptr->proj_vol->get_step_length ();
}
void
@@ -393,14 +429,9 @@ Rpl_volume::compute_ray_data ()
Proj_volume *proj_vol = d_ptr->proj_vol;
const double *src = proj_vol->get_src();
const double *nrm = proj_vol->get_nrm();
- const int *ires = d_ptr->proj_vol->get_image_dim();
+ const plm_long *ires = d_ptr->proj_vol->get_image_dim();
Volume *ct_vol = d_ptr->ct->get_vol();
- lprintf ("Proj vol:\n");
- proj_vol->debug ();
- lprintf ("Ref vol:\n");
- ct_vol->debug ();
-
/* Allocate data for each ray */
if (d_ptr->ray_data) delete[] d_ptr->ray_data;
d_ptr->ray_data = new Ray_data[ires[0]*ires[1]];
@@ -487,9 +518,15 @@ Rpl_volume::compute_ray_data ()
ray_data->front_dist = vec3_dist (p2, ip1);
}
if (ray_data->front_dist < d_ptr->front_clipping_dist) {
+#if defined (commentout)
/* GCS FIX. This should not be here. */
- // - 0.001 mm to avoid the closest ray to intersect the volume with a step inferior to its neighbours. The minimal ray will be the only one to touch the volume when offset_step = 0.
+ // - 0.001 mm to avoid the closest ray to intersect
+ // the volume with a step inferior to its neighbours.
+ // The minimal ray will be the only one to touch
+ // the volume when offset_step = 0.
d_ptr->front_clipping_dist = ray_data->front_dist - 0.001;
+#endif
+ d_ptr->front_clipping_dist = ray_data->front_dist;
}
/* Compute distance to back intersection point, and set
@@ -508,8 +545,101 @@ Rpl_volume::compute_ray_data ()
}
}
+void
+Rpl_volume::compute_rpl (
+ bool use_aperture, Ray_trace_callback callback)
+{
+ /* A couple of abbreviations */
+ Proj_volume *proj_vol = d_ptr->proj_vol;
+ const double *src = proj_vol->get_src();
+ int ires[2];
+ ires[0] = d_ptr->proj_vol->get_image_dim (0);
+ ires[1] = d_ptr->proj_vol->get_image_dim (1);
+
+ unsigned char *ap_img = 0;
+ if (use_aperture && d_ptr->aperture->have_aperture_image()) {
+ Volume::Pointer ap_vol = d_ptr->aperture->get_aperture_volume ();
+ ap_img = (unsigned char*) ap_vol->img;
+ }
+ Volume *ct_vol = d_ptr->ct->get_vol();
+
+ /* Preprocess data by clipping against volume */
+ this->compute_ray_data ();
+
+ if (d_ptr->front_clipping_dist == DBL_MAX) {
+ lprintf ("Sorry, total failure intersecting volume\n");
+ return;
+ }
+
+ lprintf ("FPD = %f, BPD = %f\n",
+ d_ptr->front_clipping_dist, d_ptr->back_clipping_dist);
+
+ /* Ahh. Now we can set the clipping planes and allocate the
+ actual volume. */
+ double clipping_dist[2] = {
+ d_ptr->front_clipping_dist, d_ptr->back_clipping_dist};
+ d_ptr->proj_vol->set_clipping_dist (clipping_dist);
+ d_ptr->proj_vol->allocate ();
+
+ /* Scan through the aperture -- second pass */
+ for (int r = 0; r < ires[1]; r++) {
+ for (int c = 0; c < ires[0]; c++) {
+
+ /* Compute index of aperture pixel */
+ plm_long ap_idx = r * ires[0] + c;
+
+ /* Make some aliases */
+ Ray_data *ray_data = &d_ptr->ray_data[ap_idx];
+
+ /* Compute intersection with front clipping plane */
+ vec3_scale3 (ray_data->cp, ray_data->ray,
+ d_ptr->front_clipping_dist);
+ vec3_add2 (ray_data->cp, ray_data->p2);
+
+#if VERBOSE
+ global_debug = false;
+ if (r == 49 && (c == 49 || c == 50)) {
+ global_debug = true;
+ }
+ if (global_debug) {
+ printf ("Tracing ray (%d,%d)\n", r, c);
+ }
+#endif
+
+ /* Check if beamlet is inside aperture, if not
+ we skip ray tracing */
+ if (ap_img && ap_img[r*ires[0]+c] == 0) {
+ continue;
+ }
+
+ this->rpl_ray_trace (
+ ct_vol,
+ ray_data,
+ callback,
+ &d_ptr->ct_limit,
+ src,
+ 0,
+ ires
+ );
+ }
+ }
+}
+
+void
+Rpl_volume::compute_rpl_sample (bool use_aperture)
+{
+ this->compute_rpl (use_aperture, rpl_callback_sample);
+}
+
+void
+Rpl_volume::compute_rpl_accum (bool use_aperture)
+{
+ this->compute_rpl (use_aperture, rpl_callback_accum);
+}
+
/* This function samples the CT into a RPL equivalent geometry.
The rpl_volume should be in proj_wed format, not in proj_ct format. */
+/* GCS Note: Why do others call compute_ray_data(), but this one does not?*/
void
Rpl_volume::compute_rpl_ct_density ()
{
@@ -536,9 +666,6 @@ Rpl_volume::compute_rpl_ct_density ()
/* Scan through the aperture -- second pass */
for (int r = 0; r < ires[1]; r++) {
-
- //if (r % 50 == 0) printf ("Row: %4d/%d\n", r, rows);
-
for (int c = 0; c < ires[0]; c++) {
/* Compute index of aperture pixel */
@@ -582,6 +709,7 @@ Rpl_volume::compute_rpl_ct_density ()
}
/* This function samples the CT in rpl geometry with HU units */
+/* GCS NOTE: It does not check the aperture */
void
Rpl_volume::compute_rpl_HU ()
{
@@ -640,6 +768,8 @@ Rpl_volume::compute_rpl_HU ()
}
}
+/* GCS Note: This is different from compute_rpl() functions.
+ It calls compute_ray_data(), allocates, and computes ray_data->cp. */
void
Rpl_volume::compute_rpl_void ()
{
@@ -682,6 +812,7 @@ Rpl_volume::compute_rpl_void ()
}
}
+/* GCS Note: The rgc should be added after ray tracing */
void
Rpl_volume::compute_rpl_range_length_rgc ()
{
@@ -760,17 +891,19 @@ Rpl_volume::compute_rpl_range_length_rgc ()
}
}
+/* GCS NOTE: This also does not check the aperture */
void
Rpl_volume::compute_rpl_PrSTRP_no_rgc ()
{
- int ires[2];
/* A couple of abbreviations */
Proj_volume *proj_vol = d_ptr->proj_vol;
const double *src = proj_vol->get_src();
+ int ires[2];
ires[0] = d_ptr->proj_vol->get_image_dim (0);
ires[1] = d_ptr->proj_vol->get_image_dim (1);
Volume *ct_vol = d_ptr->ct->get_vol();
+
/* Preprocess data by clipping against volume */
this->compute_ray_data ();
@@ -783,12 +916,9 @@ Rpl_volume::compute_rpl_PrSTRP_no_rgc ()
/* Ahh. Now we can set the clipping planes and allocate the
actual volume. */
-
double clipping_dist[2] = {
d_ptr->front_clipping_dist, d_ptr->back_clipping_dist};
-
d_ptr->proj_vol->set_clipping_dist (clipping_dist);
-
d_ptr->proj_vol->allocate ();
/* Scan through the aperture -- second pass */
@@ -815,6 +945,7 @@ Rpl_volume::compute_rpl_PrSTRP_no_rgc ()
printf ("Tracing ray (%d,%d)\n", r, c);
}
#endif
+
this->rpl_ray_trace (
ct_vol, /* I: CT volume */
ray_data, /* I: Pre-computed data for this ray */
@@ -845,17 +976,17 @@ double Rpl_volume::compute_farthest_penetrating_ray_on_nrm(float range)
for (int apert_idx = 0; apert_idx < dim[0] * dim[1]; apert_idx++)
{
- Ray_data* ray_data = (Ray_data*) &this->get_Ray_data()[apert_idx];
+ Ray_data* ray_data = (Ray_data*) &this->get_ray_data()[apert_idx];
for (int s = 0; s < dim[2]; s++)
{
idx = s * dim[0] * dim[1] + apert_idx;
- if (s == dim[2]-1 || dim[2] == 0)
- {
- max_dist = offset + (double) dim[2] * this->get_vol()->spacing[2];
- printf("Warning: Range > ray_length in volume => Some rays might stop outside of the volume image.\n");
- printf("position of the maximal range on the z axis: z = %lg\n", max_dist);
- return max_dist;
- }
+ if (s == dim[2]-1 || dim[2] == 0)
+ {
+ max_dist = offset + (double) dim[2] * this->get_vol()->spacing[2];
+ printf("Warning: Range > ray_length in volume => Some rays might stop outside of the volume image.\n");
+ printf("position of the maximal range on the z axis: z = %lg\n", max_dist);
+ return max_dist;
+ }
if (img[idx] > range)
{
@@ -907,14 +1038,14 @@ Rpl_volume::compute_proj_wed_volume (
//each geometric distance should increase, due to divergence.
const double base_dist = proj_vol->get_proj_matrix()->sid; //distance from source to aperture
- const int *ires = proj_vol->get_image_dim();
+ const plm_long *ires = proj_vol->get_image_dim();
- int ap_ij[2]; //ray index of rvol
+ plm_long ap_ij[2]; //ray index of rvol
plm_long ap_idx = 0; //ray number
Ray_data *ray_data;
double ray_ap[3]; //vector from src to ray intersection with ap plane
double ray_ap_length; //length of vector from src to ray intersection with ap plane
- double rglength; //length that we insert into get_rgdepth for each ray
+ double rglength; //length that we insert into get_value for each ray
for (ap_ij[1] = 0; ap_ij[1] < ires[1]; ap_ij[1]++) {
for (ap_ij[0] = 0; ap_ij[0] < ires[0]; ap_ij[0]++) {
@@ -933,7 +1064,7 @@ Rpl_volume::compute_proj_wed_volume (
rglength = base_rg_dist*(ray_ap_length/base_dist);
- proj_wed_vol_img[ap_idx] = (float) (this->get_rgdepth(ap_ij,rglength));
+ proj_wed_vol_img[ap_idx] = (float) (this->get_value(ap_ij,rglength));
}
}
@@ -950,7 +1081,7 @@ Rpl_volume::compute_wed_volume (
float *rvol_img = (float*) rvol->img;
float *in_vol_img = (float*) in_vol->img;
float *wed_vol_img = (float*) wed_vol->img;
- const int *ires = proj_vol->get_image_dim();
+ const plm_long *ires = proj_vol->get_image_dim();
plm_long wijk[3]; /* Index within wed_volume */
@@ -968,8 +1099,6 @@ Rpl_volume::compute_wed_volume (
// printf ("DEBUGGING %d %d\n", ires[1], ires[0]);
// debug = true;
}
-#if defined (commentout)
-#endif
/* Nothing to do if ray misses volume */
Ray_data *ray_data = &d_ptr->ray_data[ap_idx];
@@ -1080,7 +1209,7 @@ Rpl_volume::compute_dew_volume (
const plm_long *dew_dim = dew_vol->dim;
//Get some parameters from the proj volume
- const int *ires = proj_vol->get_image_dim();
+ const plm_long *ires = proj_vol->get_image_dim();
const double *src = proj_vol->get_src();
const double dist = proj_vol->get_proj_matrix()->sid; //distance from source to aperture
double src_iso_vec[3]; //vector from source to isocenter
@@ -1116,7 +1245,7 @@ Rpl_volume::compute_dew_volume (
double ray_end[3];
plm_long wijk[3]; //index within wed_volume
- int ap_ij[2]; //ray indox of rvol
+ plm_long ap_ij[2]; //ray indox of rvol
plm_long dijk[3]; //Index within dew_volume
plm_long didx; //image index within dew_volume
@@ -1237,14 +1366,13 @@ Rpl_volume::compute_dew_volume (
//Now look up the radiation length, using the provided function,
//knowing the ray and the length along it.
- ap_ij[0] = (int) ray_lookup[i][0];
- ap_ij[1] = (int) ray_lookup[i][1];
+ ap_ij[0] = ray_lookup[i][0];
+ ap_ij[1] = ray_lookup[i][1];
/* GCS FIX: I think the ray_lookup stuff is
3D interpolation, should reduce this code to
- use the 3D interpolated version of get_rgdepth() */
+ use the 3D interpolated version of get_value() */
- ray_rad_len[i] = this->get_rgdepth (
- ap_ij, rad_depth_input);
+ ray_rad_len[i] = this->get_value (ap_ij, rad_depth_input);
//Set each corner to background.
master_square[i/2][i%2] = background;
@@ -1299,123 +1427,6 @@ Rpl_volume::compute_dew_volume (
}
}
-void
-Rpl_volume::apply_smearing_to_target(float smearing, std::vector <double>& map_min_distance, std::vector <double>& map_max_distance)
-{
- printf("Apply smearing to the target.\nThe smearing width is defined at the minimum depth of the target.\n");
- /* Create a structured element of the right size */
- int strel_half_size[2];
- int strel_size[2];
-
- /* Found the min of the target to be sure the smearing (margins) at the minimal depth */
- double min = DBL_MAX;
- for (size_t i = 0; i < map_min_distance.size(); i++) {
- if (map_min_distance[i] > 0 && map_min_distance[i] < min) {
- min = map_min_distance[i];
- }
- }
- if (min == DBL_MAX)
- {
- printf("***ERROR: Target depth min is null for each ray. Smearing not applied\n");
- return;
- }
- d_ptr->min_distance_target = min + d_ptr->aperture->get_distance() + d_ptr->front_clipping_dist;
-
-
- /* The smearing width is scaled to the aperture */
- strel_half_size[0] = ROUND_INT(smearing * d_ptr->aperture->get_distance() / (d_ptr->min_distance_target * d_ptr->aperture->get_spacing()[0]));
- strel_half_size[1] = ROUND_INT(smearing * d_ptr->aperture->get_distance() / (d_ptr->min_distance_target * d_ptr->aperture->get_spacing()[1]));
-
- strel_size[0] = 1 + 2 * strel_half_size[0];
- strel_size[1] = 1 + 2 * strel_half_size[1];
- float smearing_ap = smearing * d_ptr->aperture->get_distance() / (min + d_ptr->aperture->get_distance() + d_ptr->front_clipping_dist);
-
- int *strel = new int[strel_size[0]*strel_size[1]];
- /* (rf, cf) center of the smearing */
- for (int r = 0; r < strel_size[1]; r++) {
- float rf = (float) (r - strel_half_size[1]) * d_ptr->aperture->get_spacing()[0];
- for (int c = 0; c < strel_size[0]; c++) {
- float cf = (float) (c - strel_half_size[0]) * d_ptr->aperture->get_spacing()[1];
-
- int idx = r*strel_size[0] + c;
-
- strel[idx] = 0;
- if ((rf*rf + cf*cf) <= smearing_ap*smearing_ap) {
- strel[idx] = 1;
- }
- }
- }
-
- /* Debugging information */
- for (int r = 0; r < strel_size[1]; r++) {
- for (int c = 0; c < strel_size[0]; c++) {
- int idx = r*strel_size[0] + c;
- printf ("%d ", strel[idx]);
- }
- printf ("\n");
- }
-
- /* Apply smear to target maps */
- double distance_min;
- double distance_max;
- std::vector<double> min_distance_tmp (map_min_distance.size(), 0);
- std::vector<double> max_distance_tmp (map_max_distance.size(), 0);
-
- for (int ar = 0; ar < d_ptr->aperture->get_dim()[1]; ar++) {
- for (int ac = 0; ac < d_ptr->aperture->get_dim()[0]; ac++) {
- int aidx = ar * d_ptr->aperture->get_dim()[0] + ac;
-
- /* Reset the limit values */
- distance_min = DBL_MAX;
- distance_max = 0;
-
- for (int sr = 0; sr < strel_size[1]; sr++) {
- int pr = ar + sr - strel_half_size[1];
- if (pr < 0 || pr >= d_ptr->aperture->get_dim()[1]) {
- continue;
- }
- for (int sc = 0; sc < strel_size[0]; sc++) {
- int pc = ac + sc - strel_half_size[0];
- if (pc < 0 || pc >= d_ptr->aperture->get_dim()[0]) {
- continue;
- }
-
- int sidx = sr * strel_size[0] + sc;
- if (strel[sidx] == 0) {
- continue;
- }
-
- int pidx = pr * d_ptr->aperture->get_dim()[0] + pc;
- if (map_min_distance[pidx] > 0 && map_min_distance[pidx] < distance_min) {
- distance_min = map_min_distance[pidx];
- }
- if (map_max_distance[pidx] > distance_max) {
- distance_max = map_max_distance[pidx];
- }
- }
- }
- if (distance_min == DBL_MAX)
- {
- min_distance_tmp[aidx] = 0;
- }
- else
- {
- min_distance_tmp[aidx] = distance_min;
- }
- max_distance_tmp[aidx] = distance_max;
- }
- }
-
- /* update the initial distance map */
- for (size_t i = 0; i < map_min_distance.size(); i++) {
- map_min_distance[i] = min_distance_tmp[i];
- map_max_distance[i] = max_distance_tmp[i];
- }
-
- /* Clean up */
- delete[] strel;
-}
-
void
Rpl_volume::compute_volume_aperture(Aperture::Pointer ap)
{
@@ -1445,8 +1456,9 @@ Rpl_volume::compute_volume_aperture(Aperture::Pointer ap)
}
}
+// In this new version the range compensator is added later in the code depending on the algorithm
void
-Rpl_volume::apply_beam_modifiers () // In this new version the range compensator is added later in the code depending on the algorithm
+Rpl_volume::apply_beam_modifiers ()
{
Volume::Pointer ap_vol = d_ptr->aperture->get_aperture_volume ();
unsigned char *ap_img = (unsigned char*) ap_vol->img;
@@ -1454,7 +1466,7 @@ Rpl_volume::apply_beam_modifiers () // In this new version the range compensator
float *proj_img = (float*) proj_vol->img;
/* For each ray in aperture */
- const int *ires = d_ptr->proj_vol->get_image_dim();
+ const plm_long *ires = d_ptr->proj_vol->get_image_dim();
printf ("ires = %d %d\n", ires[0], ires[1]);
printf ("proj_vol dim = %d %d %d\n", (int) proj_vol->dim[0],
@@ -1479,65 +1491,6 @@ Rpl_volume::apply_beam_modifiers () // In this new version the range compensator
}
}
-void
-Rpl_volume::compute_beam_modifiers_passive_scattering (Volume *seg_vol)
-{
- std::vector<double> min;
- std::vector<double> max;
- compute_beam_modifiers_core (seg_vol, false, 0, 0, 0, min, max);
- return;
-}
-
-void
-Rpl_volume::compute_beam_modifiers_active_scanning (Volume *seg_vol)
-{
- std::vector<double> min;
- std::vector<double> max;
- compute_beam_modifiers_core (seg_vol, true, 0, 0, 0, min, max);
- return;
-}
-
-void
-Rpl_volume::compute_beam_modifiers_passive_scattering (Volume *seg_vol, float smearing, float proximal_margin, float distal_margin)
-{
- std::vector<double> min;
- std::vector<double> max;
- compute_beam_modifiers_core (seg_vol, false, smearing, proximal_margin, distal_margin, min, max);
- return;
-}
-
-void
-Rpl_volume::compute_beam_modifiers_passive_scattering_slicerRt (Plm_image::Pointer& plmTgt, float smearing, float proximal_margin, float distal_margin)
-{
- std::vector<double> min;
- std::vector<double> max;
- compute_beam_modifiers_core_slicerRt (plmTgt, false, smearing, proximal_margin, distal_margin, min, max);
- return;
-}
-
-void
-Rpl_volume::compute_beam_modifiers_active_scanning (Volume *seg_vol, float smearing, float proximal_margin, float distal_margin)
-{
- std::vector<double> min;
- std::vector<double> max;
- compute_beam_modifiers_core (seg_vol, true, smearing, proximal_margin, distal_margin, min, max);
- return;
-}
-
-void
-Rpl_volume::compute_beam_modifiers_passive_scattering (Volume *seg_vol, float smearing, float proximal_margin, float distal_margin, std::vector<double>& map_wed_min, std::vector<double>& map_wed_max)
-{
- compute_beam_modifiers_core (seg_vol, false, smearing, proximal_margin, distal_margin, map_wed_min, map_wed_max);
- return;
-}
-
-void
-Rpl_volume::compute_beam_modifiers_active_scanning (Volume *seg_vol, float smearing, float proximal_margin, float distal_margin, std::vector<double>& map_wed_min, std::vector<double>& map_wed_max)
-{
- compute_beam_modifiers_core (seg_vol, true, smearing, proximal_margin, distal_margin, map_wed_min, map_wed_max);
- return;
-}
-
Volume*
Rpl_volume::get_vol ()
{
@@ -1556,6 +1509,12 @@ Rpl_volume::get_proj_volume ()
return d_ptr->proj_vol;
}
+const Proj_volume*
+Rpl_volume::get_proj_volume () const
+{
+ return d_ptr->proj_vol;
+}
+
void
Rpl_volume::save (const char *filename)
{
@@ -1570,7 +1529,7 @@ Rpl_volume::save (const char *filename)
if (d_ptr->ray_data) {
std::string raydata_fn = fn_base + ".raydata";
FILE *fp = plm_fopen (raydata_fn, "wb");
- const int *ires = d_ptr->proj_vol->get_image_dim();
+ const plm_long *ires = d_ptr->proj_vol->get_image_dim();
for (int r = 0; r < ires[1]; r++) {
for (int c = 0; c < ires[0]; c++) {
int ap_idx = r * ires[0] + c;
@@ -1609,9 +1568,6 @@ Rpl_volume::save (const char *filename)
d_ptr->ct_limit.dir[0],
d_ptr->ct_limit.dir[1],
d_ptr->ct_limit.dir[2]);
- fprintf (fp, "min_wed = %g\n", d_ptr->min_wed);
- fprintf (fp, "max_wed = %g\n", d_ptr->max_wed);
- fprintf (fp, "min_distance_target = %g\n", d_ptr->min_distance_target);
fclose (fp);
}
@@ -1781,13 +1737,17 @@ Rpl_volume::rpl_ray_trace (
cd.accum = rc_thk;
cd.ires = ires;
- /* Figure out how many steps to first step within volume */
- cd.step_offset = 0;
- ray_data->step_offset = cd.step_offset;
-
- /* Find location of first step within volume */
- double tmp[3];
+ // Figure out location of, and number of steps to first step within volume
double first_loc[3];
+ if (d_ptr->rvrts == RAY_TRACE_START_AT_RAY_VOLUME_INTERSECTION) {
+ ray_data->step_offset = cd.step_offset = 0;
+ } else {
+ ray_data->step_offset
+ = cd.step_offset
+ = (int) floor (ray_data->front_dist - d_ptr->front_clipping_dist)
+ / d_ptr->proj_vol->get_step_length ();
+ }
+ double tmp[3];
vec3_scale3 (tmp, ray_data->ray,
cd.step_offset * d_ptr->proj_vol->get_step_length ());
vec3_add3 (first_loc, ray_data->p2, tmp);
@@ -1810,7 +1770,7 @@ Rpl_volume::rpl_ray_trace (
ray_trace_uniform (
ct_vol, // INPUT: CT volume
vol_limit, // INPUT: CT volume bounding box
- callback, // INPUT: step action cbFunction
+ callback, // INPUT: step action Function
&cd, // INPUT: callback data
first_loc, // INPUT: ray starting point
ray_data->ip2, // INPUT: ray ending point
@@ -1831,7 +1791,7 @@ Rpl_volume::rpl_ray_trace (
static
void
-rpl_ray_trace_callback_ct_HU (
+rpl_callback_accum (
void *callback_data,
size_t vox_index,
double vox_len,
@@ -1846,7 +1806,7 @@ rpl_ray_trace_callback_ct_HU (
int ap_area = cd->ires[0] * cd->ires[1];
size_t step_num = vox_index + cd->step_offset;
- cd->accum = 0;
+ cd->accum += vox_len * vox_value;
#if VERBOSE
if (global_debug) {
@@ -1870,12 +1830,12 @@ rpl_ray_trace_callback_ct_HU (
return;
}
- depth_img[ap_area*step_num + ap_idx] = vox_value;
+ depth_img[ap_area*step_num + ap_idx] = cd->accum;
}
static
void
-rpl_ray_trace_callback_ct_density (
+rpl_callback_sample (
void *callback_data,
size_t vox_index,
double vox_len,
@@ -1914,12 +1874,12 @@ rpl_ray_trace_callback_ct_density (
return;
}
- depth_img[ap_area*step_num + ap_idx] = compute_density_from_HU(vox_value);
+ depth_img[ap_area*step_num + ap_idx] = vox_value;
}
static
void
-rpl_ray_trace_callback_PrSTPR (
+rpl_ray_trace_callback_ct_HU (
void *callback_data,
size_t vox_index,
double vox_len,
@@ -1934,7 +1894,7 @@ rpl_ray_trace_callback_PrSTPR (
int ap_area = cd->ires[0] * cd->ires[1];
size_t step_num = vox_index + cd->step_offset;
- cd->accum += vox_len * compute_PrSTPR_from_HU (vox_value); //vox_value = CT_HU
+ cd->accum = 0;
#if VERBOSE
if (global_debug) {
@@ -1958,12 +1918,12 @@ rpl_ray_trace_callback_PrSTPR (
return;
}
- depth_img[ap_area*step_num + ap_idx] = cd->accum;
+ depth_img[ap_area*step_num + ap_idx] = vox_value;
}
static
void
-rpl_ray_trace_callback_range_length (
+rpl_ray_trace_callback_ct_density (
void *callback_data,
size_t vox_index,
double vox_len,
@@ -1978,7 +1938,7 @@ rpl_ray_trace_callback_range_length (
int ap_area = cd->ires[0] * cd->ires[1];
size_t step_num = vox_index + cd->step_offset;
- cd->accum += vox_len * compute_density_from_HU (vox_value); //vox_value = CT_HU
+ cd->accum = 0;
#if VERBOSE
if (global_debug) {
@@ -2002,14 +1962,12 @@ rpl_ray_trace_callback_range_length (
return;
}
- depth_img[ap_area*step_num + ap_idx] = cd->accum;
+ depth_img[ap_area*step_num + ap_idx] = compute_density_from_HU(vox_value);
}
-//Added by YKPark. Relative stopping power-based water eq. path length. Valid for 20 MeV ~ 240 MeV proton beam
-//t_w = t_m * rel. density * SP ratio(m to w) = t_m*RSP
static
void
-rpl_ray_trace_callback_RSP (
+rpl_ray_trace_callback_PrSTPR (
void *callback_data,
size_t vox_index,
double vox_len,
@@ -2024,7 +1982,7 @@ rpl_ray_trace_callback_RSP (
int ap_area = cd->ires[0] * cd->ires[1];
size_t step_num = vox_index + cd->step_offset;
- cd->accum += vox_len * compute_PrSTRP_XiO_MGH_weq_from_HU (vox_value); //vox_value = CT_HU
+ cd->accum += vox_len * compute_PrSTPR_from_HU (vox_value); //vox_value = CT_HU
#if VERBOSE
if (global_debug) {
@@ -2051,462 +2009,93 @@ rpl_ray_trace_callback_RSP (
depth_img[ap_area*step_num + ap_idx] = cd->accum;
}
+static
void
-Rpl_volume::compute_beam_modifiers_core (Volume *seg_vol, bool active, float smearing, float proximal_margin, float distal_margin, std::vector<double>& map_wed_min, std::vector<double>& map_wed_max)
-{
- printf("Compute target distance limits...\n");
- /* compute the target min and max distance (not wed!) map in the aperture */
- compute_target_distance_limits (seg_vol, map_wed_min, map_wed_max);
-
- printf("Apply smearing to the target...\n");
- /* widen the min/max distance maps */
- if (smearing > 0)
- {
- apply_smearing_to_target(smearing, map_wed_min, map_wed_max);
- }
-
- printf("Apply longitudinal margins...\n");
- /* add the margins */
- for (size_t i = 0; i < map_wed_min.size(); i++) {
- map_wed_min[i] -= proximal_margin;
- if (map_wed_min[i] < 0) {
- map_wed_min[i] = 0;
- }
- if (map_wed_max[i] > 0) {
- map_wed_max[i] += distal_margin;
- }
- }
-
- printf("Compute max wed...\n");
- /* compute wed limits from depth limits and compute max wed of the target + margins */
- int idx = 0;
- double max_wed = 0;
- int i[2] = {0, 0};
- for (i[0] = 0; i[0] < d_ptr->aperture->get_aperture_volume()->dim[0]; i[0]++){
- for (i[1] = 0; i[1] < d_ptr->aperture->get_aperture_volume()->dim[1]; i[1]++){
- idx = i[0] + i[1] * d_ptr->aperture->get_aperture_volume()->dim[0];
- if (map_wed_max[idx] <= 0)
- {
- continue;
- }
- map_wed_min[idx] = this->get_rgdepth(i, map_wed_min[idx]);
- map_wed_max[idx] = this->get_rgdepth(i, map_wed_max[idx]);
- if (map_wed_max[idx] > max_wed) {
- max_wed = map_wed_max[idx];
- }
- }
- }
-
- printf("Compute the aperture...\n");
- /* compute the aperture */
- /* This assumes that dim & spacing are correctly set in aperture */
- d_ptr->aperture->allocate_aperture_images ();
-
- Volume::Pointer aperture_vol = d_ptr->aperture->get_aperture_volume ();
- unsigned char *aperture_img = (unsigned char*) aperture_vol->img;
- for (int i = 0; i < aperture_vol->dim[0] * aperture_vol->dim[1]; i++)
- {
- if (map_wed_min[i] > 0) {
- aperture_img[i] = 1;
- }
- else {
- aperture_img[i] = 0;
- }
- }
-
- /* compute the range compensator if passive beam line -- PMMA range compensator */
- Volume::Pointer range_comp_vol = d_ptr->aperture->get_range_compensator_volume ();
- float *range_comp_img = (float*) range_comp_vol->img;
-
- if (active == false)
- {
- printf("Compute range compensator...\n");
- }
-
- for (int i = 0; i < aperture_vol->dim[0] * aperture_vol->dim[1]; i++)
- {
- if (active == true)
- {
- range_comp_img[i] = 0;
- }
- else
- {
- range_comp_img[i] = (max_wed - map_wed_max[i]) / (PMMA_STPR * PMMA_DENSITY);
- }
- }
-
- /* compute the max/min wed of the entire target + margins + range_comp*/
- double total_min_wed = 0;
- double total_max_wed = 0;
- // Max should be the same as the max in the target as for this ray rgcomp is null
- for (int i = 0; i < aperture_vol->dim[0] * aperture_vol->dim[1]; i++)
- {
- if (range_comp_img[i] * PMMA_STPR * PMMA_DENSITY + map_wed_max[i] > total_max_wed) { // if active beam line, range comp is null
- total_max_wed = range_comp_img[i] * PMMA_STPR * PMMA_DENSITY + map_wed_max[i];
- }
- }
- total_min_wed = total_max_wed;
- for (int i = 0; i < aperture_vol->dim[0] * aperture_vol->dim[1]; i++)
- {
- if ((range_comp_img[i] * PMMA_STPR * PMMA_DENSITY + map_wed_max[i] > 0) && (range_comp_img[i] * PMMA_STPR * PMMA_DENSITY + map_wed_min[i] < total_min_wed)) {
- total_min_wed = range_comp_img[i] * PMMA_STPR * PMMA_DENSITY + map_wed_min[i];
- }
- }
-
- printf("Max wed in the target is %lg mm.\n", total_max_wed);
- printf("Min wed in the target is %lg mm.\n", total_min_wed);
-
- /* Save these values in private data store */
- d_ptr->max_wed = total_max_wed;
- d_ptr->min_wed = total_min_wed;
- return;
-}
-
-void
-Rpl_volume::compute_beam_modifiers_core_slicerRt (Plm_image::Pointer& plmTgt, bool active, float smearing, float proximal_margin, float distal_margin, std::vector<double>& map_wed_min, std::vector<double>& map_wed_max)
+rpl_ray_trace_callback_range_length (
+ void *callback_data,
+ size_t vox_index,
+ double vox_len,
+ float vox_value
+)
{
- printf("Compute target distance limits...\n");
-
- /* compute the target min and max distance (not wed!) map in the aperture */
- compute_target_distance_limits_slicerRt(plmTgt, map_wed_min, map_wed_max);
-
- printf("Apply smearing to the target...\n");
- /* widen the min/max distance maps */
- if (smearing > 0)
- {
- apply_smearing_to_target(smearing, map_wed_min, map_wed_max);
- }
-
- printf("Apply longitudinal margins...\n");
- /* add the margins */
- for (size_t i = 0; i < map_wed_min.size(); i++) {
- map_wed_min[i] -= proximal_margin;
- if (map_wed_min[i] < 0) {
- map_wed_min[i] = 0;
- }
- if (map_wed_max[i] > 0) {
- map_wed_max[i] += distal_margin;
- }
- }
-
- printf("Compute max wed...\n");
- /* compute wed limits from depth limits and compute max wed of the target + margins */
- int idx = 0;
- double max_wed = 0;
- int i[2] = {0, 0};
- for (i[0] = 0; i[0] < d_ptr->aperture->get_aperture_volume()->dim[0]; i[0]++){
- for (i[1] = 0; i[1] < d_ptr->aperture->get_aperture_volume()->dim[1]; i[1]++){
- idx = i[0] + i[1] * d_ptr->aperture->get_aperture_volume()->dim[0];
- if (map_wed_max[idx] <= 0)
- {
- continue;
- }
- map_wed_min[idx] = this->get_rgdepth(i, map_wed_min[idx]);
- map_wed_max[idx] = this->get_rgdepth(i, map_wed_max[idx]);
- if (map_wed_max[idx] > max_wed) {
- max_wed = map_wed_max[idx];
- }
- }
- }
+ Callback_data *cd = (Callback_data *) callback_data;
+ Rpl_volume *rpl_vol = cd->rpl_vol;
+ Ray_data *ray_data = cd->ray_data;
+ float *depth_img = (float*) rpl_vol->get_vol()->img;
+ int ap_idx = ray_data->ap_idx;
+ int ap_area = cd->ires[0] * cd->ires[1];
+ size_t step_num = vox_index + cd->step_offset;
- printf("Compute the aperture...\n");
- /* compute the aperture */
- /* This assumes that dim & spacing are correctly set in aperture */
- d_ptr->aperture->allocate_aperture_images ();
+ cd->accum += vox_len * compute_density_from_HU (vox_value); //vox_value = CT_HU
- Volume::Pointer aperture_vol = d_ptr->aperture->get_aperture_volume ();
- unsigned char *aperture_img = (unsigned char*) aperture_vol->img;
- for (int i = 0; i < aperture_vol->dim[0] * aperture_vol->dim[1]; i++)
- {
- if (map_wed_min[i] > 0) {
- aperture_img[i] = 1;
- }
- else {
- aperture_img[i] = 0;
- }
- }
-
- /* compute the range compensator if passive beam line -- PMMA range compensator */
- Volume::Pointer range_comp_vol = d_ptr->aperture->get_range_compensator_volume ();
- float *range_comp_img = (float*) range_comp_vol->img;
-
- if (active == false)
- {
- printf("Compute range compensator...\n");
+#if VERBOSE
+ if (global_debug) {
+ printf ("%d %4d: %20g %20g\n", ap_idx, (int) step_num,
+ vox_value, cd->accum);
+ printf ("dim = %d %d %d\n",
+ (int) rpl_vol->get_vol()->dim[0],
+ (int) rpl_vol->get_vol()->dim[1],
+ (int) rpl_vol->get_vol()->dim[2]);
+ printf ("ap_area = %d, ap_idx = %d, vox_len = %g\n",
+ ap_area, (int) ap_idx, vox_len);
}
+#endif
- for (int i = 0; i < aperture_vol->dim[0] * aperture_vol->dim[1]; i++)
- {
- if (active == true)
- {
- range_comp_img[i] = 0;
- }
- else
- {
- range_comp_img[i] = (max_wed - map_wed_max[i]) / (PMMA_STPR * PMMA_DENSITY);
- }
- }
+ cd->last_step_completed = step_num;
- /* compute the max/min wed of the entire target + margins + range_comp*/
- double total_min_wed = 0;
- double total_max_wed = 0;
- // Max should be the same as the max in the target as for this ray rgcomp is null
- for (int i = 0; i < aperture_vol->dim[0] * aperture_vol->dim[1]; i++)
- {
- if (range_comp_img[i] * PMMA_STPR * PMMA_DENSITY + map_wed_max[i] > total_max_wed) { // if active beam line, range comp is null
- total_max_wed = range_comp_img[i] * PMMA_STPR * PMMA_DENSITY + map_wed_max[i];
- }
- }
- total_min_wed = total_max_wed;
- for (int i = 0; i < aperture_vol->dim[0] * aperture_vol->dim[1]; i++)
- {
- if ((range_comp_img[i] * PMMA_STPR * PMMA_DENSITY + map_wed_max[i] > 0) && (range_comp_img[i] * PMMA_STPR * PMMA_DENSITY + map_wed_min[i] < total_min_wed)) {
- total_min_wed = range_comp_img[i] * PMMA_STPR * PMMA_DENSITY + map_wed_min[i];
- }
+ /* GCS FIX: I have a rounding error somewhere -- maybe step_num
+ starts at 1? Or maybe proj_vol is not big enough?
+ This is a workaround until I can fix. */
+ if ((plm_long) step_num >= rpl_vol->get_vol()->dim[2]) {
+ return;
}
- printf("Max wed in the target is %lg mm.\n", total_max_wed);
- printf("Min wed in the target is %lg mm.\n", total_min_wed);
-
- /* Save these values in private data store */
- d_ptr->max_wed = total_max_wed;
- d_ptr->min_wed = total_min_wed;
- return;
+ depth_img[ap_area*step_num + ap_idx] = cd->accum;
}
+//Added by YKPark. Relative stopping power-based water eq. path length. Valid for 20 MeV ~ 240 MeV proton beam
+//t_w = t_m * rel. density * SP ratio(m to w) = t_m*RSP
+static
void
-Rpl_volume::compute_target_distance_limits(Volume* seg_vol, std::vector <double>& map_min_distance, std::vector <double>& map_max_distance)
+rpl_ray_trace_callback_RSP (
+ void *callback_data,
+ size_t vox_index,
+ double vox_len,
+ float vox_value
+)
{
- double threshold = .2; //theshold for interpolated, segmented volume
- d_ptr->aperture->allocate_aperture_images();
-
- Volume::Pointer aperture_vol = d_ptr->aperture->get_aperture_volume ();
- Proj_volume *proj_vol = d_ptr->proj_vol;
- Volume *rvol = proj_vol->get_vol();
- float *seg_img = (float*) seg_vol->img;
-
- //const int *ires = proj_vol->get_image_dim(); //resolution of the 2-D proj vol aperture
- int ires2[2]; //resolution of the output - user defined aperuture and segdepth_vol
- ires2[0] = aperture_vol->dim[0];
- ires2[1] = aperture_vol->dim[1];
-
- //plm_long rijk[3]; /* Index with rvol */
- double k = 0; /* index with rvol */
- double seg_long_ray[3] = {0, 0, 0}; // vector in the rvol volume
- float final_index[3]; //index of final vector
-
- //Trilinear interpoloation variables
- plm_long ijk_floor[3]; //floor of rounded
- plm_long ijk_round[3]; //ceiling of rounded
- float li_1[3], li_2[3]; //upper/lower fractions
- plm_long idx_floor;
-
- //Interpolated seg_volume value
- double interp_seg_value;
-
- double previous_depth; //previous wed depth
- bool intersect_seg; //boolean that checks whether or not ray intersects with seg. volume
- bool first_seg_check; //first point along a ray in the seg volume, to determine min energy
-
- Ray_data *seg_ray;
-
- for(int i = 0; i < ires2[0] * ires2[1]; i++)
- {
- map_min_distance.push_back(0);
- map_max_distance.push_back(0);
- }
-
- for (int i = 0; i < ires2[0] * ires2[1]; i++)
- {
- seg_ray = &d_ptr->ray_data[i];
- k = 0.;
- vec3_copy(seg_long_ray, seg_ray->cp);
-
- /* reset variables */
- previous_depth = 0;
- first_seg_check = true;
- intersect_seg = false;
-
- while (k < (double) rvol->dim[2])
- {
- if (k != 0)
- {
- vec3_add2(seg_long_ray, seg_ray->ray);
- }
-
- final_index[0] = (seg_long_ray[0]-seg_vol->origin[0])/seg_vol->spacing[0];
- final_index[1] = (seg_long_ray[1]-seg_vol->origin[1])/seg_vol->spacing[1];
- final_index[2] = (seg_long_ray[2]-seg_vol->origin[2])/seg_vol->spacing[2];
-
- li_clamp_3d (final_index, ijk_floor, ijk_round,li_1,li_2,seg_vol);
- idx_floor = volume_index(seg_vol->dim, ijk_floor);
- interp_seg_value = li_value(li_1[0], li_2[0],li_1[1], li_2[1],li_1[2], li_2[2],idx_floor,seg_img,seg_vol);
+ Callback_data *cd = (Callback_data *) callback_data;
+ Rpl_volume *rpl_vol = cd->rpl_vol;
+ Ray_data *ray_data = cd->ray_data;
+ float *depth_img = (float*) rpl_vol->get_vol()->img;
+ int ap_idx = ray_data->ap_idx;
+ int ap_area = cd->ires[0] * cd->ires[1];
+ size_t step_num = vox_index + cd->step_offset;
- if (interp_seg_value > threshold)
- {
- intersect_seg = true; //this ray intersects the segmentation volume
+ cd->accum += vox_len * compute_PrSTRP_XiO_MGH_weq_from_HU (vox_value); //vox_value = CT_HU
- /* If point is within segmentation volume, set distance to the map_min matrix */
- if (first_seg_check)
- {
- map_min_distance[i] = k;
- first_seg_check = false;
- }
- previous_depth = k;
- }
- else
- {
- if (intersect_seg)
- {
- /* while we aren't currently in the seg. volume, this ray has been,
- so check if we just exited to set the max_seg_depth */
- if (previous_depth > 0)
- {
- map_max_distance[i] = previous_depth;
- previous_depth = 0;
- }
- }
- }
- k++;
- }
+#if VERBOSE
+ if (global_debug) {
+ printf ("%d %4d: %20g %20g\n", ap_idx, (int) step_num,
+ vox_value, cd->accum);
+ printf ("dim = %d %d %d\n",
+ (int) rpl_vol->get_vol()->dim[0],
+ (int) rpl_vol->get_vol()->dim[1],
+ (int) rpl_vol->get_vol()->dim[2]);
+ printf ("ap_area = %d, ap_idx = %d, vox_len = %g\n",
+ ap_area, (int) ap_idx, vox_len);
}
- return;
-}
-
-void
-Rpl_volume::compute_target_distance_limits_slicerRt(Plm_image::Pointer& plmTgt, std::vector <double>& map_min_distance, std::vector <double>& map_max_distance)
-{
- double threshold = .2; //theshold for interpolated, segmented volume
- d_ptr->aperture->allocate_aperture_images();
-
- Volume::Pointer aperture_vol = d_ptr->aperture->get_aperture_volume ();
- Proj_volume *proj_vol = d_ptr->proj_vol;
- Volume *rvol = proj_vol->get_vol();
- unsigned char* seg_img = (unsigned char*) plmTgt->get_volume_uchar()->img;
-
- //const int *ires = proj_vol->get_image_dim(); //resolution of the 2-D proj vol aperture
- int ires2[2]; //resolution of the output - user defined aperuture and segdepth_vol
- ires2[0] = aperture_vol->dim[0];
- ires2[1] = aperture_vol->dim[1];
-
- //plm_long rijk[3]; /* Index with rvol */
- double k = 0; /* index with rvol */
- double seg_long_ray[3] = {0, 0, 0}; // vector in the rvol volume
- float final_index[3]; //index of final vector
-
- //Trilinear interpoloation variables
- plm_long ijk_floor[3]; //floor of rounded
- plm_long ijk_round[3]; //ceiling of rounded
- float li_1[3], li_2[3]; //upper/lower fractions
- plm_long idx_floor;
- double A = 0; double B = 0; double C = 0; double D = 0; double E = 0; double F = 0; double G = 0; double H = 0;
-
- //Interpolated seg_volume value
- double interp_seg_value;
-
- lprintf ("tgt dim = %d,%d,%d\n", (int) plmTgt->dim(0), (int) plmTgt->dim(1), (int) plmTgt->dim(2));
- lprintf ("tgt origin = %g,%g,%g\n", plmTgt->origin(0), plmTgt->origin(1), plmTgt->origin(2));
- lprintf ("tgt spacing = %g,%g,%g\n", plmTgt->spacing(0), plmTgt->spacing(1), plmTgt->spacing(2));
- fflush (stdout);
- plm_long dim[3] = {(plm_long) plmTgt->dim(0), (plm_long) plmTgt->dim(1), (plm_long) plmTgt->dim(2)};
-
- double previous_depth; //previous wed depth
- bool intersect_seg; //boolean that checks whether or not ray intersects with seg. volume
- bool first_seg_check; //first point along a ray in the seg volume, to determine min energy
+#endif
- Ray_data *seg_ray;
+ cd->last_step_completed = step_num;
- for(int i = 0; i < ires2[0] * ires2[1]; i++)
- {
- map_min_distance.push_back(0);
- map_max_distance.push_back(0);
+ /* GCS FIX: I have a rounding error somewhere -- maybe step_num
+ starts at 1? Or maybe proj_vol is not big enough?
+ This is a workaround until I can fix. */
+ if ((plm_long) step_num >= rpl_vol->get_vol()->dim[2]) {
+ return;
}
- for (int i = 0; i < ires2[0] * ires2[1]; i++)
- {
- seg_ray = &d_ptr->ray_data[i];
- k = 0.;
- vec3_copy(seg_long_ray, seg_ray->cp);
-
- /* reset variables */
- previous_depth = 0;
- first_seg_check = true;
- intersect_seg = false;
-
- while (k < (double) rvol->dim[2])
- {
- if (k != 0)
- {
- vec3_add2(seg_long_ray, seg_ray->ray);
- }
-
- final_index[0] = (seg_long_ray[0] - plmTgt->origin(0))/plmTgt->spacing(0);
- final_index[1] = (seg_long_ray[1] - plmTgt->origin(1))/plmTgt->spacing(1);
- final_index[2] = (seg_long_ray[2] - plmTgt->origin(2))/plmTgt->spacing(2);
- if (final_index[0] < 0 || final_index[0] > (float) plmTgt->dim(0) || final_index[1] < 0 || final_index[1] > (float) plmTgt->dim(1) || final_index[2] < 0 || final_index[2] > (float) plmTgt->dim(2))
- {
- interp_seg_value = 0;
- }
- else
- {
- /* Li_clamp_3D */
- li_clamp (final_index[0], plmTgt->dim(0)-1, &ijk_floor[0], &ijk_round[0], &li_1[0], &li_2[0]);
- li_clamp (final_index[1], plmTgt->dim(1)-1, &ijk_floor[1], &ijk_round[1], &li_1[1], &li_2[1]);
- li_clamp (final_index[2], plmTgt->dim(2)-1, &ijk_floor[2], &ijk_round[2], &li_1[2], &li_2[2]);
-
- idx_floor = volume_index (dim, ijk_floor);
-
- /* li_value for Volume* */
- A = li_1[0] * li_1[1] * li_1[2] * (double)seg_img[idx_floor];
- B = li_2[0] * li_1[1] * li_1[2] * (double)seg_img[idx_floor+1];
- C = li_1[0] * li_2[1] * li_1[2] * (double)seg_img[idx_floor+dim[0] ];
- D = li_2[0] * li_2[1] * li_1[2] * (double)seg_img[idx_floor+dim[0]+1];
- E = li_1[0] * li_1[1] * li_2[2] * (double)seg_img[idx_floor+dim[1]*dim[0] ];
- F = li_2[0] * li_1[1] * li_2[2] * (double)seg_img[idx_floor+dim[1]*dim[0]+1];
- G = li_1[0] * li_2[1] * li_2[2] * (double)seg_img[idx_floor+dim[1]*dim[0]+dim[0] ];
- H = li_2[0] * li_2[1] * li_2[2] * (double)seg_img[idx_floor+dim[1]*dim[0]+dim[0]+1];
- interp_seg_value = A + B + C + D + E + F + F + G + H;
- }
-
- if (interp_seg_value > threshold)
- {
- intersect_seg = true; //this ray intersects the segmentation volume
-
- /* If point is within segmentation volume, set distance to the map_min matrix */
- if (first_seg_check)
- {
- map_min_distance[i] = k;
- first_seg_check = false;
- }
- previous_depth = k;
- }
- else
- {
- if (intersect_seg)
- {
- /* while we aren't currently in the seg. volume, this ray has been,
- so check if we just exited to set the max_seg_depth */
- if (previous_depth > 0)
- {
- map_max_distance[i] = previous_depth;
- previous_depth = 0;
- }
- }
- }
- k++;
- }
- }
- return;
+ depth_img[ap_area*step_num + ap_idx] = cd->accum;
}
-//20140827_YKP
-//col0 = HU, col1 = Relative stopping power
-//Table: XiO, ctedproton 2007 provided by Yoost
-extern const double lookup_PrSTPR_XiO_MGH[][2] ={
- -1000.0, 0.01,
- 0.0, 1.0,
- 40.0, 1.04,
- 1000.0, 1.52,
- 2000.0, 2.02,
- 3000.0, 2.55,
-};
diff --git a/src/plastimatch/base/rpl_volume.h b/src/plastimatch/base/rpl_volume.h
old mode 100644
new mode 100755
index 02f1423..96701fa
--- a/src/plastimatch/base/rpl_volume.h
+++ b/src/plastimatch/base/rpl_volume.h
@@ -16,11 +16,7 @@
PLMBASE_API float compute_PrSTPR_from_HU(float);
PLMBASE_API float compute_PrSTPR_Schneider_weq_from_HU (float CT_HU); // Stopping Power Ratio - Schneider's model
-PLMBASE_API float compute_PrSTRP_XiO_MGH_weq_from_HU (float CT_HU); // Stopping power Ratio - XiO values from MGH
PLMBASE_API float compute_PrWER_from_HU(float CT_HU); // WER = STRP / density
-
-extern const double lookup_PrSTPR_XiO_MGH[][2];
-
PLMBASE_API float compute_density_from_HU (float CT_HU); // density VS HU - Schneider's model: broken curve
class Proj_volume;
@@ -29,6 +25,11 @@ class Rpl_volume_private;
class Volume;
class Volume_limit;
+enum Rpl_volume_ray_trace_start {
+ RAY_TRACE_START_AT_RAY_VOLUME_INTERSECTION,
+ RAY_TRACE_START_AT_CLIPPING_PLANE
+};
+
class PLMBASE_API Rpl_volume
{
public:
@@ -43,13 +44,14 @@ public:
const double iso[3], // position of isocenter (mm)
const double vup[3], // dir to "top" of projection plane
double sid, // dist from proj plane to source (mm)
- const int image_dim[2], // resolution of image
+ const plm_long image_dim[2], // resolution of image
const double image_center[2], // image center (pixels)
const double image_spacing[2], // pixel size (mm)
const double step_length // spacing between planes
);
+ void clone_geometry (const Rpl_volume *rv);
- void set_ct_volume (Plm_image::Pointer& ct_volume);
+ void set_ray_trace_start (Rpl_volume_ray_trace_start rvrtt);
Aperture::Pointer& get_aperture ();
const Aperture::Pointer& get_aperture () const;
@@ -58,31 +60,41 @@ public:
Volume* get_vol ();
const Volume* get_vol () const;
Proj_volume* get_proj_volume ();
+ void set_ct_volume (Plm_image::Pointer& ct_volume);
+
+ const Proj_volume* get_proj_volume () const;
+
+ const plm_long *get_image_dim ();
+ plm_long get_num_steps ();
- double get_rgdepth (int ap_ij[2], double dist);
- double get_rgdepth (double ap_ij[2], double dist);
- double get_rgdepth (const double *xyz);
+ double get_value (plm_long ap_ij[2], double dist) const;
+ double get_value (double ap_ij[2], double dist) const;
+ double get_value (const double *xyz) const;
void set_ct (const Plm_image::Pointer& ct_volume);
Plm_image::Pointer get_ct();
+
void set_ct_limit(Volume_limit* ct_limit);
Volume_limit* get_ct_limit();
- void set_ray(Ray_data *ray);
- Ray_data* get_Ray_data();
+
+ Ray_data* get_ray_data();
+ const Ray_data* get_ray_data() const;
+ void set_ray_data (Ray_data *ray);
+
void set_front_clipping_plane(double front_clip);
double get_front_clipping_plane () const;
void set_back_clipping_plane(double back_clip);
double get_back_clipping_plane () const;
- void set_minimum_distance_target(double min);
- double get_minimum_distance_target();
-
- double get_max_wed ();
- double get_min_wed ();
+ double get_step_length () const;
void compute_rpl_ct_density (); // compute density volume
void compute_rpl_HU (); // compute HU volume
void compute_rpl_void (); // compute void volume
+ void compute_rpl (bool use_aperture, Ray_trace_callback callback);
+ void compute_rpl_sample (bool use_aperture);
+ void compute_rpl_accum (bool use_aperture);
+
void compute_rpl_range_length_rgc(); // range length volume creation taking into account the range compensator
void compute_rpl_PrSTRP_no_rgc (); // compute Proton Stopping Power Ratio volume without considering the range compensator
@@ -92,14 +104,6 @@ public:
void compute_dew_volume (Volume *wed_vol, Volume *dew_vol, float background);
void compute_proj_wed_volume (Volume *proj_wed_vol, float background);
- void compute_beam_modifiers_passive_scattering (Volume *seg_vol);
- void compute_beam_modifiers_active_scanning (Volume *seg_vol);
- void compute_beam_modifiers_passive_scattering (Volume *seg_vol, float smearing, float proximal_margin, float distal_margin);
- void compute_beam_modifiers_passive_scattering_slicerRt(Plm_image::Pointer& plmTgt, float smearing, float proximal_margin, float distal_margin);
- void compute_beam_modifiers_active_scanning (Volume *seg_vol, float smearing, float proximal_margin, float distal_margin);
- void compute_beam_modifiers_passive_scattering (Volume *seg_vol, float smearing, float proximal_margin, float distal_margin, std::vector<double>& map_wed_min, std::vector<double>& map_wed_max); // returns also the wed max and min maps
- void compute_beam_modifiers_active_scanning (Volume *seg_vol, float smearing, float proximal_margin, float distal_margin, std::vector<double>& map_wed_min, std::vector<double>& map_wed_max); // returns also the wed max and min maps
-
void compute_volume_aperture(Aperture::Pointer ap);
void apply_beam_modifiers ();
@@ -112,14 +116,8 @@ public:
void load_img (const std::string& filename);
void compute_ray_data ();
- void compute_beam_modifiers_core_slicerRt (Plm_image::Pointer& plmTgt, bool active, float smearing, float proximal_margin, float distal_margin, std::vector<double>& map_wed_min, std::vector<double>& map_wed_max);
protected:
- void compute_beam_modifiers_core (Volume *seg_vol, bool active, float smearing, float proximal_margin, float distal_margin, std::vector<double>& map_wed_min, std::vector<double>& map_wed_max);
- void compute_target_distance_limits (Volume* seg_vol, std::vector <double>& map_min_distance, std::vector <double>& map_max_distance);
- void compute_target_distance_limits_slicerRt (Plm_image::Pointer& plmTgt, std::vector <double>& map_min_distance, std::vector <double>& map_max_distance);
- void apply_smearing_to_target (float smearing, std::vector <double>& map_min_distance, std::vector <double>& map_max_distance);
-
void rpl_ray_trace (
Volume *ct_vol, /* I: CT volume */
Ray_data *ray_data, /* I: Pre-computed data for this ray */
diff --git a/src/plastimatch/base/rpl_volume_lut.cxx b/src/plastimatch/base/rpl_volume_lut.cxx
new file mode 100755
index 0000000..3258843
--- /dev/null
+++ b/src/plastimatch/base/rpl_volume_lut.cxx
@@ -0,0 +1,163 @@
+/* -----------------------------------------------------------------------
+ See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
+ ----------------------------------------------------------------------- */
+#include "plmbase_config.h"
+
+#include "interpolate.h"
+#include "proj_volume.h"
+#include "ray_data.h"
+#include "rpl_volume.h"
+#include "rpl_volume_lut.h"
+#include "volume.h"
+
+class Lut_entry
+{
+public:
+ Lut_entry() {
+ for (int i = 0; i < 8; i++) {
+ idx[i] = -i;
+ weight[i] = 0.f;
+ }
+ }
+public:
+ plm_long idx[8];
+ float weight[8];
+};
+
+class PLMBASE_API Rpl_volume_lut_private
+{
+public:
+ Rpl_volume_lut_private (Rpl_volume *rv, Volume *vol)
+ : rv(rv), vol(vol), lut(0)
+ {
+ }
+ ~Rpl_volume_lut_private ()
+ {
+ delete[] lut;
+ }
+public:
+ Rpl_volume *rv;
+ Volume *vol;
+ Lut_entry *lut;
+};
+
+Rpl_volume_lut::Rpl_volume_lut ()
+{
+ d_ptr = new Rpl_volume_lut_private (0, 0);
+}
+
+Rpl_volume_lut::Rpl_volume_lut (Rpl_volume *rv, Volume *vol)
+{
+ d_ptr = new Rpl_volume_lut_private (rv, vol);
+}
+
+Rpl_volume_lut::~Rpl_volume_lut ()
+{
+ delete d_ptr;
+}
+
+void
+Rpl_volume_lut::set_lut_entry (
+ const Ray_data* ray_data,
+ plm_long vox_idx,
+ const float *vox_ray,
+ plm_long ap_idx,
+ float li_frac,
+ float step_length,
+ int lut_entry_idx
+)
+{
+ // Make sure this ray has positive weight
+ if (li_frac <= 0.f) {
+ return;
+ }
+
+ // Project voxel vector onto unit vector of aperture ray
+ // This assumes that
+ // d_ptr->rvrts == RAY_TRACE_START_AT_RAY_VOLUME_INTERSECTION
+ // We omit the check for speed.
+ const double *ap_ray = ray_data[ap_idx].ray;
+ float dist = vec3_dot (vox_ray, ap_ray);
+ dist -= ray_data->front_dist;
+ if (dist < 0) {
+ return;
+ }
+
+ // Compute number of steps
+ plm_long steps_f = (plm_long) floorf (dist / step_length);
+ float dist_frac = (dist - steps_f * step_length) / step_length;
+ if (steps_f >= d_ptr->rv->get_num_steps()) {
+ return;
+ }
+
+ // Compute lut entries
+ const Aperture::Pointer ap = d_ptr->rv->get_aperture ();
+ plm_long lut_idx = ap_idx + steps_f * ap->get_dim(0) * ap->get_dim(1);
+ d_ptr->lut[lut_idx].idx[lut_entry_idx] = lut_idx;
+ d_ptr->lut[lut_idx].weight[lut_entry_idx] = dist_frac * li_frac;
+
+ if (steps_f >= d_ptr->rv->get_num_steps() - 1) {
+ return;
+ }
+ lut_idx = lut_idx + ap->get_dim(0) * ap->get_dim(1);
+ d_ptr->lut[lut_idx].idx[4+lut_entry_idx] = lut_idx;
+ d_ptr->lut[lut_idx].weight[4+lut_entry_idx] = (1. - dist_frac) * li_frac;
+}
+
+void
+Rpl_volume_lut::build_lut ()
+{
+ const Proj_volume *pv = d_ptr->rv->get_proj_volume ();
+ const double *src = pv->get_src ();
+ const Aperture::Pointer ap = d_ptr->rv->get_aperture ();
+ const plm_long *ap_dim = ap->get_dim ();
+ const Ray_data* ray_data = d_ptr->rv->get_ray_data();
+
+ /* Allocate memory for lut */
+ d_ptr->lut = new Lut_entry[d_ptr->vol->npix];
+
+ plm_long ijk[3];
+ double xyz[3];
+ LOOP_Z (ijk, xyz, d_ptr->vol) {
+ LOOP_Y (ijk, xyz, d_ptr->vol) {
+ LOOP_X (ijk, xyz, d_ptr->vol) {
+ plm_long idx = d_ptr->vol->index (ijk);
+
+ /* Project the voxel to the aperture plane */
+ double ap_xy[2];
+ pv->project (ap_xy, xyz);
+ if (!is_number (ap_xy[0]) || !is_number (ap_xy[1])) {
+ continue;
+ }
+
+ /* Check if voxel is completely outside aperture boundary */
+ if (ap_xy[0] <= -1.f || ap_xy[0] >= ap_dim[0]
+ || ap_xy[1] <= -1.f || ap_xy[1] >= ap_dim[1])
+ {
+ continue;
+ }
+
+ /* Get vector from source to voxel */
+ float vox_ray[3];
+ vec3_sub3 (vox_ray, xyz, src);
+
+ /* Solve for interpolation fractions on aperture planes */
+ plm_long ijk_f[3];
+ float li_frac_1[3], li_frac_2[3];
+ float ap_xy_float[2] = { ap_xy[0], ap_xy[1] };
+ li_2d (ijk_f, li_frac_1, li_frac_2, ap_xy_float, ap_dim);
+
+ /* Inspect four interpolant aperture pixels.
+ For each pixel, calculate distance to point
+ on ray closest to voxel center */
+ plm_long ap_ij[2], ap_idx;
+ ap_ij[0] = ijk_f[0], ap_ij[1] = ijk_f[1];
+ ap_idx = ap_ij[0] + ap_ij[1] * ap_dim[0];
+
+ set_lut_entry (ray_data, idx, vox_ray,
+ ap_idx, li_frac_1[0], li_frac_2[0], 0);
+
+ }
+ }
+ }
+}
diff --git a/src/plastimatch/base/rpl_volume_lut.h b/src/plastimatch/base/rpl_volume_lut.h
new file mode 100755
index 0000000..fcc8087
--- /dev/null
+++ b/src/plastimatch/base/rpl_volume_lut.h
@@ -0,0 +1,37 @@
+/* -----------------------------------------------------------------------
+ See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
+ ----------------------------------------------------------------------- */
+#ifndef _rpl_volume_lut_h_
+#define _rpl_volume_lut_h_
+
+#include "plmbase_config.h"
+#include "smart_pointer.h"
+
+class Rpl_volume;
+class Rpl_volume_lut_private;
+class Volume;
+
+class PLMBASE_API Rpl_volume_lut
+{
+public:
+ SMART_POINTER_SUPPORT (Rpl_volume_lut);
+ Rpl_volume_lut_private *d_ptr;
+public:
+ Rpl_volume_lut ();
+ Rpl_volume_lut (Rpl_volume *rv, Volume *vol);
+ ~Rpl_volume_lut ();
+public:
+ void build_lut ();
+protected:
+ void set_lut_entry (
+ const Ray_data* ray_data,
+ plm_long vox_idx,
+ const float *vox_ray,
+ plm_long ap_idx,
+ float li_frac,
+ float step_length,
+ int lut_entry_idx
+ );
+};
+
+#endif
diff --git a/src/plastimatch/base/rt_study_metadata.cxx b/src/plastimatch/base/rt_study_metadata.cxx
old mode 100755
new mode 100644
index ce41c13..093b959
--- a/src/plastimatch/base/rt_study_metadata.cxx
+++ b/src/plastimatch/base/rt_study_metadata.cxx
@@ -15,12 +15,17 @@
class Rt_study_metadata_private {
public:
std::string date_string;
+ std::string description_string;
+ std::string referring_physician_name_string;
+ std::string accession_number_string;
std::string time_string;
std::string study_id_string;
std::string study_uid;
std::string for_uid;
+ std::string position_reference_indicator_string;
+
std::string ct_series_uid;
std::string dose_instance_uid;
std::string dose_series_uid;
@@ -112,9 +117,15 @@ Rt_study_metadata::set_ct_series_uid (const char* uid)
}
const char*
+Rt_study_metadata::get_ct_series_description () const
+{
+ return this->get_image_metadata (0x0008, 0x103E).c_str();
+}
+
+const std::string&
Rt_study_metadata::get_dose_instance_uid () const
{
- return d_ptr->dose_instance_uid.c_str();
+ return d_ptr->dose_instance_uid;
}
const char*
@@ -142,10 +153,17 @@ Rt_study_metadata::get_plan_instance_uid () const
return d_ptr->plan_instance_uid.c_str();
}
-const char*
+const std::string&
Rt_study_metadata::get_rtstruct_instance_uid () const
{
- return d_ptr->rtstruct_instance_uid.c_str();
+ return d_ptr->rtstruct_instance_uid;
+}
+
+void
+Rt_study_metadata::set_rtstruct_instance_uid (const char* rtstruct_instance_uid)
+{
+ if (!rtstruct_instance_uid) return;
+ d_ptr->rtstruct_instance_uid = rtstruct_instance_uid;
}
const char*
@@ -155,6 +173,82 @@ Rt_study_metadata::get_rtstruct_series_uid () const
}
const char*
+Rt_study_metadata::get_referring_physician_name () const
+{
+ return d_ptr->referring_physician_name_string.c_str();
+}
+
+void
+Rt_study_metadata::set_referring_physician_name (const char* referring_physician_name)
+{
+ if (!referring_physician_name) return;
+ d_ptr->referring_physician_name_string = referring_physician_name;
+}
+
+void
+Rt_study_metadata::set_referring_physician_name (const std::string& referring_physician_name)
+{
+ d_ptr->referring_physician_name_string = referring_physician_name;
+}
+
+const char*
+Rt_study_metadata::get_position_reference_indicator () const
+{
+ return d_ptr->position_reference_indicator_string.c_str();
+}
+
+void
+Rt_study_metadata::set_position_reference_indicator (const char* position_reference_indicator)
+{
+ if (!position_reference_indicator) return;
+ d_ptr->position_reference_indicator_string = position_reference_indicator;
+}
+
+void
+Rt_study_metadata::set_position_reference_indicator (const std::string& position_reference_indicator)
+{
+ d_ptr->position_reference_indicator_string = position_reference_indicator;
+}
+
+const char*
+Rt_study_metadata::get_accession_number () const
+{
+ return d_ptr->accession_number_string.c_str();
+}
+
+void
+Rt_study_metadata::set_accession_number (const char* accession_number)
+{
+ if (!accession_number) return;
+ d_ptr->accession_number_string = accession_number;
+}
+
+void
+Rt_study_metadata::set_accession_number (const std::string& accession_number)
+{
+ d_ptr->accession_number_string = accession_number;
+}
+
+const char*
+Rt_study_metadata::get_study_description () const
+{
+ return d_ptr->description_string.c_str();
+}
+
+void
+Rt_study_metadata::set_study_description (const char* description)
+{
+ if (!description) return;
+ d_ptr->description_string = description;
+}
+
+void
+Rt_study_metadata::set_study_description (const std::string& description)
+{
+ d_ptr->description_string = description;
+}
+
+const char*
Rt_study_metadata::get_study_date () const
{
return d_ptr->date_string.c_str();
@@ -182,8 +276,10 @@ Rt_study_metadata::get_study_time () const
void
Rt_study_metadata::set_study_time (const char* time)
{
- if (!time) return;
- d_ptr->time_string = time;
+ if (!time)
+ d_ptr->time_string.clear();
+ else
+ d_ptr->time_string = time;
}
void
@@ -404,7 +500,8 @@ const std::string&
Rt_study_metadata::get_image_metadata (
unsigned short key1,
unsigned short key2
-) {
+) const
+{
return d_ptr->image_metadata->get_metadata (key1, key2);
}
diff --git a/src/plastimatch/base/rt_study_metadata.h b/src/plastimatch/base/rt_study_metadata.h
old mode 100755
new mode 100644
index 0efd8ab..77e0615
--- a/src/plastimatch/base/rt_study_metadata.h
+++ b/src/plastimatch/base/rt_study_metadata.h
@@ -38,18 +38,36 @@ public:
public:
const char* get_ct_series_uid () const;
void set_ct_series_uid (const char* uid);
- const char* get_dose_instance_uid () const;
+ const char* get_ct_series_description () const;
+ const std::string& get_dose_instance_uid () const;
const char* get_dose_series_uid () const;
const char* get_frame_of_reference_uid () const;
void set_frame_of_reference_uid (const char* uid);
const char* get_plan_instance_uid () const;
- const char* get_rtstruct_instance_uid () const;
+ const std::string& get_rtstruct_instance_uid () const;
+ void set_rtstruct_instance_uid (const char* rtstruct_instance_uid);
const char* get_rtstruct_series_uid () const;
+ const char* get_position_reference_indicator () const;
+ void set_position_reference_indicator (const char* position_reference_indicator);
+ void set_position_reference_indicator (const std::string& position_reference_indicator);
+
+ const char* get_referring_physician_name () const;
+ void set_referring_physician_name (const char* referring_physician_name);
+ void set_referring_physician_name (const std::string& referring_physician_name);
+
+ const char* get_accession_number () const;
+ void set_accession_number (const char* accession_number);
+ void set_accession_number (const std::string& accession_number);
+
const char* get_study_date () const;
void set_study_date (const char* date);
void set_study_date (const std::string& date);
+ const char* get_study_description () const;
+ void set_study_description (const char* description);
+ void set_study_description (const std::string& description);
+
const char* get_study_time () const;
void set_study_time (const char* time);
void set_study_time (const std::string& time);
@@ -98,7 +116,7 @@ public:
Metadata::Pointer& get_image_metadata ();
const Metadata::Pointer& get_image_metadata () const;
const std::string& get_image_metadata (unsigned short key1,
- unsigned short key2);
+ unsigned short key2) const;
void set_image_metadata (unsigned short key1, unsigned short key2,
const std::string& val);
Metadata::Pointer& get_rtstruct_metadata ();
diff --git a/src/plastimatch/base/rt_study_p.h b/src/plastimatch/base/rt_study_p.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/rtplan.cxx b/src/plastimatch/base/rtplan.cxx
index bc90eca..096c2ca 100644
--- a/src/plastimatch/base/rtplan.cxx
+++ b/src/plastimatch/base/rtplan.cxx
@@ -37,6 +37,7 @@ void
Rtplan::clear(void)
{
this->number_of_fractions_planned = 0;
+ this->patient_position = "HFS";
this->snout_id = "";
this->general_accessory_id = "";
this->general_accessory_code = "";
@@ -44,12 +45,22 @@ Rtplan::clear(void)
this->range_shifter_code = "";
this->range_modulator_id = "";
this->range_modulator_code = "";
+ this->rt_plan_label = "";
+ this->rt_plan_name = "";
+ this->rt_plan_date = "";
+ this->rt_plan_time = "";
+ this->fraction_group_description = "";
+ this->number_of_fraction_pattern_digits_per_day = "";
+ this->repeat_fraction_cycle_length = "";
+ this->fraction_pattern = "";
this->tolerance_table_label = "";
this->tolerance_gantry_angle = "";
this->tolerance_patient_support_angle = "";
this->tolerance_table_top_vertical = "";
this->tolerance_table_top_longitudinal = "";
this->tolerance_table_top_lateral = "";
+ this->tolerance_table_top_pitch = "";
+ this->tolerance_table_top_roll = "";
this->tolerance_snout_position = "";
for (size_t i = 0; i < this->beamlist.size(); i++) {
delete this->beamlist[i];
diff --git a/src/plastimatch/base/rtplan.h b/src/plastimatch/base/rtplan.h
index ecf87ff..75bed18 100644
--- a/src/plastimatch/base/rtplan.h
+++ b/src/plastimatch/base/rtplan.h
@@ -22,19 +22,35 @@ public:
SMART_POINTER_SUPPORT(Rtplan);
public:
size_t number_of_fractions_planned;
+ std::string patient_position;
std::string snout_id;
std::string general_accessory_id;
std::string general_accessory_code;
+ std::string number_of_range_shifters;
std::string range_shifter_id;
+ std::string range_shifter_number;
std::string range_shifter_code;
+ std::string range_shifter_type;
std::string range_modulator_id;
std::string range_modulator_code;
+ std::string patient_support_id;
+ std::string patient_support_accessory_code;
+ std::string rt_plan_label;
+ std::string rt_plan_name;
+ std::string rt_plan_date;
+ std::string rt_plan_time;
+ std::string fraction_group_description;
+ std::string number_of_fraction_pattern_digits_per_day;
+ std::string repeat_fraction_cycle_length;
+ std::string fraction_pattern;
std::string tolerance_table_label;
std::string tolerance_gantry_angle;
std::string tolerance_patient_support_angle;
std::string tolerance_table_top_vertical;
std::string tolerance_table_top_longitudinal;
std::string tolerance_table_top_lateral;
+ std::string tolerance_table_top_pitch;
+ std::string tolerance_table_top_roll;
std::string tolerance_snout_position;
std::vector<Rtplan_beam*> beamlist;
public:
diff --git a/src/plastimatch/base/rtplan_beam.cxx b/src/plastimatch/base/rtplan_beam.cxx
index ce143c4..621317e 100644
--- a/src/plastimatch/base/rtplan_beam.cxx
+++ b/src/plastimatch/base/rtplan_beam.cxx
@@ -27,8 +27,28 @@ Rtplan_beam::clear()
{
this->name = "";
this->description = "";
+ this->treatment_machine_name = "";
+ this->treatment_delivery_type = "";
this->final_cumulative_meterset_weight = 0.f;
this->snout_position = 0.f;
+ this->gantry_angle = 0.f;
+ this->gantry_rotation_direction = "NONE";
+ this->beam_limiting_device_angle = 0.f;
+ this->beam_limiting_device_rotation_direction = "NONE";
+ this->patient_support_angle = 0.f;
+ this->patient_support_rotation_direction = "NONE";
+ this->table_top_vertical_position = 0.f;
+ this->table_top_longitudinal_position = 0.f;
+ this->table_top_lateral_position = 0.f;
+ this->table_top_pitch_angle = 0.f;
+ this->table_top_pitch_rotation_direction = "NONE";
+ this->table_top_roll_angle = 0.f;
+ this->table_top_roll_rotation_direction = "NONE";
+ this->gantry_pitch_angle = 0.f;
+ this->gantry_pitch_rotation_direction = "NONE";
+ this->isocenter_position[0] = 0.f;
+ this->isocenter_position[1] = 0.f;
+ this->isocenter_position[2] = 0.f;
for (size_t i = 0; i < this->cplist.size(); i++) {
delete this->cplist[i];
@@ -44,29 +64,6 @@ Rtplan_beam::add_control_pt ()
return new_control_pt;
}
-/* first beam isocenter position*/
-#if defined (commentout)
-float*
-Rtplan_beam::get_isocenter_pos()
-{
- float isopos[3];
-
- isopos[0] = 0.0;
- isopos[1] = 0.0;
- isopos[2] = 0.0;
-
- if (num_cp < 1)
- return isopos;
-
- /* Get First CP's isocenter position*/
- isopos[0] = cplist[0]->iso_pos[0];
- isopos[1] = cplist[0]->iso_pos[1];
- isopos[2] = cplist[0]->iso_pos[2];
-
- return isopos;
-}
-#endif
-
bool
Rtplan_beam::check_isocenter_identical()
{
diff --git a/src/plastimatch/base/rtplan_beam.h b/src/plastimatch/base/rtplan_beam.h
index 0b8e548..04c7ae7 100644
--- a/src/plastimatch/base/rtplan_beam.h
+++ b/src/plastimatch/base/rtplan_beam.h
@@ -18,6 +18,16 @@ public:
std::string name;
/*! \brief Beam description */
std::string description;
+ /*! \other brief descriptions */
+ std::string treatment_machine_name;
+ std::string treatment_delivery_type;
+ std::string manufacturer;
+ std::string institution_name;
+ std::string institution_address;
+ std::string institutional_department_name;
+ std::string manufacturer_model_name;
+ std::string virtual_source_axis_distances;
+
/*! \brief Meterset at end of all control points */
float final_cumulative_meterset_weight;
/*! \brief Coordiates of point where beam dose is specified */
@@ -25,10 +35,27 @@ public:
/*! \brief Dose in Gy at beam specification point */
float beam_dose;
float snout_position;
+ float gantry_angle;
+ std::string gantry_rotation_direction;
+ float beam_limiting_device_angle;
+ std::string beam_limiting_device_rotation_direction;
+ float patient_support_angle;
+ std::string patient_support_rotation_direction;
+ float table_top_vertical_position;
+ float table_top_longitudinal_position;
+ float table_top_lateral_position;
+ float table_top_pitch_angle;
+ std::string table_top_pitch_rotation_direction;
+ float table_top_roll_angle;
+ std::string table_top_roll_rotation_direction;
+ float gantry_pitch_angle;
+ std::string gantry_pitch_rotation_direction;
+ float isocenter_position[3];
/*! \brief Control point list */
std::vector<Rtplan_control_pt*> cplist;
+
public:
Rtplan_beam();
~Rtplan_beam();
@@ -36,9 +63,6 @@ public:
void clear ();
Rtplan_control_pt* add_control_pt ();
bool check_isocenter_identical ();
-#if defined (commentout)
- float* get_isocenter_pos (); //float[3], dicom coordinate
-#endif
};
diff --git a/src/plastimatch/base/rtplan_control_pt.h b/src/plastimatch/base/rtplan_control_pt.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/rtss.cxx b/src/plastimatch/base/rtss.cxx
index d7b846e..a82b61e 100644
--- a/src/plastimatch/base/rtss.cxx
+++ b/src/plastimatch/base/rtss.cxx
@@ -558,7 +558,7 @@ void
Rtss::keyholize (void)
{
/* Loop through structures */
- for (int i = 0; i < this->num_structures; i++) {
+ for (size_t i = 0; i < this->num_structures; i++) {
lprintf ("Keyholizing structure %d.\n", i);
Rtss_roi *curr_structure = this->slist[i];
@@ -567,7 +567,7 @@ Rtss::keyholize (void)
std::vector<bool> used_contours;
used_contours.assign (curr_structure->num_contours, false);
- for (int j = 0; j < curr_structure->num_contours; j++) {
+ for (size_t j = 0; j < curr_structure->num_contours; j++) {
std::vector<int> group_contours;
Rtss_contour *group_polyline = curr_structure->pslist[j];
if (group_polyline->num_vertices == 0) {
@@ -579,7 +579,7 @@ Rtss::keyholize (void)
}
float group_z = group_polyline->z[0];
group_contours.push_back (j);
- for (int k = j+1; k < curr_structure->num_contours; k++) {
+ for (size_t k = j+1; k < curr_structure->num_contours; k++) {
Rtss_contour *curr_polyline = curr_structure->pslist[k];
if (curr_polyline->num_vertices == 0) {
curr_polyline->slice_no = -1;
@@ -593,11 +593,13 @@ Rtss::keyholize (void)
}
/* We have now found a group */
+#if defined (commentout)
lprintf ("Keyholizing group:");
for (size_t k = 0; k < group_contours.size(); k++) {
lprintf (" %d", group_contours[k]);
}
lprintf ("\n");
+#endif
/* Find xmin for each contour in group */
std::vector<float> group_xmin;
@@ -605,7 +607,7 @@ Rtss::keyholize (void)
for (size_t k = 0; k < group_contours.size(); k++) {
int cidx = group_contours[k];
Rtss_contour *curr_polyline = curr_structure->pslist[cidx];
- for (int l = 0; l < curr_polyline->num_vertices; l++) {
+ for (size_t l = 0; l < curr_polyline->num_vertices; l++) {
if (curr_polyline->x[l] < group_xmin[k]) {
group_xmin[k] = curr_polyline->x[l];
}
@@ -620,7 +622,7 @@ Rtss::keyholize (void)
Rtss_contour *curr_polyline = curr_structure->pslist[cidx];
float curr_xmin = FLT_MAX;
- for (int l = 0; l < curr_polyline->num_vertices; l++) {
+ for (size_t l = 0; l < curr_polyline->num_vertices; l++) {
if (curr_polyline->x[l] < curr_xmin) {
curr_xmin = curr_polyline->x[l];
}
@@ -635,7 +637,9 @@ Rtss::keyholize (void)
#if defined (commentout)
Rtss_contour *outer_polyline = curr_structure->pslist[
#endif
+#if defined (commentout)
lprintf ("Outermost contour %d, x=%f\n", cidx_xmin, xmin);
+#endif
/* Loop through other contours, find contours contained
in this contour */
@@ -651,7 +655,7 @@ Rtss::keyholize (void)
if (contour_in_contour (curr_polyline, ...)
#endif
- for (int l = 0; l < curr_polyline->num_vertices; l++) {
+ for (size_t l = 0; l < curr_polyline->num_vertices; l++) {
float x = curr_polyline->x[0];
float y = curr_polyline->y[0];
diff --git a/src/plastimatch/base/slice_list.cxx b/src/plastimatch/base/slice_list.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/slice_list.h b/src/plastimatch/base/slice_list.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/thumbnail.cxx b/src/plastimatch/base/thumbnail.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/thumbnail.h b/src/plastimatch/base/thumbnail.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/vf.cxx b/src/plastimatch/base/vf.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/vf_convolve.cxx b/src/plastimatch/base/vf_convolve.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/volume.cxx b/src/plastimatch/base/volume.cxx
index 2076076..1502f85 100755
--- a/src/plastimatch/base/volume.cxx
+++ b/src/plastimatch/base/volume.cxx
@@ -774,7 +774,7 @@ Volume::clone (Volume_pixel_type new_type) const
#endif
float
-Volume::get_ijk_value (const float ijk[3])
+Volume::get_ijk_value (const float ijk[3]) const
{
plm_long ijk_f[3];
plm_long ijk_r[3];
diff --git a/src/plastimatch/base/volume.h b/src/plastimatch/base/volume.h
index 91eff55..c53d67b 100755
--- a/src/plastimatch/base/volume.h
+++ b/src/plastimatch/base/volume.h
@@ -80,17 +80,13 @@ public:
~Volume ();
public:
/*! \brief Return a linear index to a voxel */
- plm_long index (plm_long i, plm_long j, plm_long k) {
+ plm_long index (plm_long i, plm_long j, plm_long k) const {
return volume_index (this->dim, i, j, k);
}
/*! \brief Return a linear index to a voxel */
- plm_long index (plm_long ijk[3]) {
+ plm_long index (plm_long ijk[3]) const {
return volume_index (this->dim, ijk);
}
- /*! \brief Return a world coordinates of a voxel */
- void position (float xyz[3], const plm_long ijk[3]) {
- POSITION_FROM_COORDS (xyz, ijk, this->origin, this->step);
- }
/*! \brief Initialize and allocate memory for the image */
void create (
const plm_long new_dim[3],
@@ -132,6 +128,10 @@ public:
of the center of the first voxel in the volume.
*/
void set_origin (const float origin[3]);
+ /*! \brief Get a pointer to the volume dimensions */
+ const plm_long *get_dim (void) {
+ return dim;
+ }
/*! \brief Get a pointer to the direction cosines.
Direction cosines hold the orientation of a volume.
They are defined as the unit length direction vectors
@@ -175,10 +175,20 @@ public:
*/
const float* get_proj (void) const;
+ /*! \brief Return a world coordinates of a voxel */
+ void position (float xyz[3], const plm_long ijk[3]) {
+ POSITION_FROM_COORDS (xyz, ijk, this->origin, this->step);
+ }
+
+ /*! \brief Return coordinates from index */
+ void coordinates (plm_long ijk[3], plm_long idx) {
+ COORDS_FROM_INDEX(ijk, idx, this->dim);
+ }
+
/*! \brief Get the value at a voxel coordinate, clamped and
tri-linearly interpolated. Only applies to float volumes.
*/
- float get_ijk_value (const float xyz[3]);
+ float get_ijk_value (const float xyz[3]) const;
void get_xyz_from_ijk (double xyz[3], const int ijk[3]);
void get_ijk_from_xyz (int ijk[3], const float xyz[3], bool* in);
diff --git a/src/plastimatch/base/volume_boundary_behavior.h b/src/plastimatch/base/volume_boundary_behavior.h
new file mode 100644
index 0000000..0831bf5
--- /dev/null
+++ b/src/plastimatch/base/volume_boundary_behavior.h
@@ -0,0 +1,24 @@
+/* -----------------------------------------------------------------------
+ See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
+ ----------------------------------------------------------------------- */
+#ifndef _volume_boundary_behavior_h_
+#define _volume_boundary_behavior_h_
+
+#include "plmbase_config.h"
+
+/*! \brief This enum is used to control the algorithm behavior
+ for voxels at the edge of the volume. If ZERO_PADDING is
+ specified, all non-zero voxels at the edge of the volume
+ will be treated as boundary voxels. If EDGE_PADDING is
+ specified, non-zero voxels at the edge of the volume are
+ only treated as boundary voxels if they neighbor
+ a zero voxel. If ADAPTIVE_PADDING, it will use
+ EDGE_PADDING for dimensions of a single voxel, and ZERO_PADDING
+ for dimensions of multiple voxels. */
+enum Volume_boundary_behavior {
+ ZERO_PADDING,
+ EDGE_PADDING,
+ ADAPTIVE_PADDING
+};
+
+#endif
diff --git a/src/plastimatch/base/volume_fill.cxx b/src/plastimatch/base/volume_fill.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/volume_fill.h b/src/plastimatch/base/volume_fill.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/volume_grad.cxx b/src/plastimatch/base/volume_grad.cxx
old mode 100755
new mode 100644
index 9216fbc..7cd8ab4
--- a/src/plastimatch/base/volume_grad.cxx
+++ b/src/plastimatch/base/volume_grad.cxx
@@ -133,21 +133,19 @@ volume_calc_grad_mag (Volume* vout, const Volume* vref)
lprintf ("volume_calc_grad_mag complete.\n");
}
-#if defined (commentout)
Volume::Pointer
-volume_make_gradient (Volume* ref)
+volume_gradient (const Volume::Pointer& ref)
{
Volume::Pointer grad = Volume::New (
ref->dim, ref->origin, ref->spacing,
ref->direction_cosines, PT_VF_FLOAT_INTERLEAVED, 3);
- volume_calc_grad (grad.get(), ref);
+ volume_calc_grad (grad.get(), ref.get());
return grad;
}
-#endif
Volume*
-volume_make_gradient (Volume* ref)
+volume_make_gradient (const Volume* ref)
{
Volume* grad = new Volume (
ref->dim, ref->origin, ref->spacing,
diff --git a/src/plastimatch/base/volume_grad.h b/src/plastimatch/base/volume_grad.h
old mode 100755
new mode 100644
index 4bdbd8f..e4647ef
--- a/src/plastimatch/base/volume_grad.h
+++ b/src/plastimatch/base/volume_grad.h
@@ -8,8 +8,8 @@
#include "volume.h"
-PLMBASE_API Volume* volume_make_gradient (Volume* ref);
-//PLMBASE_API Volume::Pointer volume_make_gradient (Volume* ref);
+PLMBASE_API Volume* volume_make_gradient (const Volume* ref);
+PLMBASE_API Volume::Pointer volume_gradient (const Volume::Pointer& ref);
PLMBASE_API Volume::Pointer volume_gradient_magnitude (
const Volume::Pointer& ref);
diff --git a/src/plastimatch/base/volume_header.cxx b/src/plastimatch/base/volume_header.cxx
index 4ca32dc..43e6d7a 100644
--- a/src/plastimatch/base/volume_header.cxx
+++ b/src/plastimatch/base/volume_header.cxx
@@ -68,6 +68,17 @@ Volume_header::Volume_header (
d_ptr->m_direction_cosines.set (pih->GetDirection());
}
+Volume_header::Volume_header (
+ const Plm_image::Pointer& img)
+{
+ this->d_ptr = new Volume_header_private;
+ Plm_image_header pih (img);
+ pih.get_dim (d_ptr->m_dim);
+ pih.get_origin (d_ptr->m_origin);
+ pih.get_spacing (d_ptr->m_spacing);
+ d_ptr->m_direction_cosines.set (pih.GetDirection());
+}
+
Volume_header::~Volume_header ()
{
delete this->d_ptr;
diff --git a/src/plastimatch/base/volume_header.h b/src/plastimatch/base/volume_header.h
index 52d8e09..e4eede6 100644
--- a/src/plastimatch/base/volume_header.h
+++ b/src/plastimatch/base/volume_header.h
@@ -6,6 +6,7 @@
#include "plmbase_config.h"
#include "direction_cosines.h"
+#include "plm_image.h"
#include "volume.h"
class Bspline_xform;
@@ -24,6 +25,7 @@ public:
float direction_cosines[9]);
Volume_header (const Volume::Pointer& vol);
Volume_header (const Plm_image_header *pih);
+ Volume_header (const Plm_image::Pointer& img);
~Volume_header ();
public:
diff --git a/src/plastimatch/base/volume_limit.h b/src/plastimatch/base/volume_limit.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/volume_macros.h b/src/plastimatch/base/volume_macros.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/volume_resample.cxx b/src/plastimatch/base/volume_resample.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/volume_stats.cxx b/src/plastimatch/base/volume_stats.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/volume_stats.h b/src/plastimatch/base/volume_stats.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/xform_convert.cxx b/src/plastimatch/base/xform_convert.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/xform_convert.h b/src/plastimatch/base/xform_convert.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/xform_legacy.cxx b/src/plastimatch/base/xform_legacy.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/xform_legacy.h b/src/plastimatch/base/xform_legacy.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/xio_ct.cxx b/src/plastimatch/base/xio_ct.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/xio_ct_transform.cxx b/src/plastimatch/base/xio_ct_transform.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/xio_ct_transform.h b/src/plastimatch/base/xio_ct_transform.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/xio_demographic.cxx b/src/plastimatch/base/xio_demographic.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/xio_demographic.h b/src/plastimatch/base/xio_demographic.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/xio_dir.cxx b/src/plastimatch/base/xio_dir.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/xio_patient.cxx b/src/plastimatch/base/xio_patient.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/xio_patient.h b/src/plastimatch/base/xio_patient.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/base/xio_structures.cxx b/src/plastimatch/base/xio_structures.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/CMakeLists.txt b/src/plastimatch/cli/CMakeLists.txt
index 03c4cbf..f4d245f 100644
--- a/src/plastimatch/cli/CMakeLists.txt
+++ b/src/plastimatch/cli/CMakeLists.txt
@@ -23,14 +23,16 @@ set (PLASTIMATCH_SRC
pcmd_adjust.cxx
pcmd_autolabel_train.cxx
pcmd_autolabel.cxx
+ pcmd_bbox.cxx pcmd_bbox.h
pcmd_benchmark.cxx
- pcmd_boundary.cxx
+ pcmd_boundary.cxx pcmd_boundary.h
pcmd_compare.cxx
pcmd_compose.cxx
pcmd_crop.cxx
pcmd_dice.cxx
pcmd_diff.cxx
pcmd_dmap.cxx
+ pcmd_dose.cxx pcmd_dose.h
pcmd_drr.cxx
pcmd_dvh.cxx
pcmd_filter.cxx
@@ -55,6 +57,7 @@ set (PLASTIMATCH_SRC
pcmd_threshold.cxx
pcmd_thumbnail.cxx
pcmd_union.cxx
+ pcmd_vf_invert.cxx pcmd_vf_invert.h
pcmd_warp.cxx
pcmd_warp_dij.cxx
pcmd_warp_pointset.cxx
diff --git a/src/plastimatch/cli/pcmd_add.h b/src/plastimatch/cli/pcmd_add.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_adjust.cxx b/src/plastimatch/cli/pcmd_adjust.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_adjust.h b/src/plastimatch/cli/pcmd_adjust.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_autolabel.cxx b/src/plastimatch/cli/pcmd_autolabel.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_autolabel.h b/src/plastimatch/cli/pcmd_autolabel.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_autolabel_train.cxx b/src/plastimatch/cli/pcmd_autolabel_train.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_autolabel_train.h b/src/plastimatch/cli/pcmd_autolabel_train.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_bbox.cxx b/src/plastimatch/cli/pcmd_bbox.cxx
new file mode 100644
index 0000000..f9c1bd4
--- /dev/null
+++ b/src/plastimatch/cli/pcmd_bbox.cxx
@@ -0,0 +1,130 @@
+/* -----------------------------------------------------------------------
+ See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
+ ----------------------------------------------------------------------- */
+#include "plmcli_config.h"
+#include "itkImageRegionIteratorWithIndex.h"
+
+#include "itk_bbox.h"
+#include "itk_image_clone.h"
+#include "itk_image_save.h"
+#include "itk_image_type.h"
+#include "pcmd_bbox.h"
+#include "plm_clp.h"
+#include "plm_image.h"
+
+class Bbox_parms {
+public:
+ std::string input_fn;
+ std::string output_mask_fn;
+ float margin;
+ bool z_only;
+public:
+ Bbox_parms () {
+ margin = 0.f;
+ z_only = false;
+ }
+};
+
+void
+do_bbox (const Bbox_parms *parms)
+{
+ Plm_image pli (parms->input_fn);
+ UCharImageType::Pointer img = pli.itk_uchar();
+
+ float bbox[6];
+ itk_bbox (img, bbox);
+
+ bbox[0] -= parms->margin;
+ bbox[1] += parms->margin;
+ bbox[2] -= parms->margin;
+ bbox[3] += parms->margin;
+ bbox[4] -= parms->margin;
+ bbox[5] += parms->margin;
+
+ printf ("%f %f %f %f %f %f\n",
+ bbox[0], bbox[1], bbox[2], bbox[3], bbox[4], bbox[5]);
+
+ if (parms->output_mask_fn != "") {
+ UCharImageType::Pointer img_out = itk_image_clone_empty (img);
+ itk::ImageRegionIteratorWithIndex< UCharImageType >
+ it (img_out, img_out->GetLargestPossibleRegion());
+ for (it.GoToBegin(); !it.IsAtEnd(); ++it) {
+ FloatPoint3DType point;
+ UCharImageType::RegionType::IndexType idx = it.GetIndex();
+ img_out->TransformIndexToPhysicalPoint (idx, point);
+ if (point[2] < bbox[2*2+0] || point[2] > bbox[2*2+1])
+ {
+ continue;
+ }
+ if ((parms->z_only)
+ || (point[0] > bbox[0*2+0] && point[0] < bbox[0*2+1]
+ && point[1] > bbox[1*2+0] && point[1] < bbox[1*2+1]))
+ {
+ it.Set (1);
+ }
+ }
+ itk_image_save (img_out, parms->output_mask_fn);
+ }
+}
+
+static void
+usage_fn (dlib::Plm_clp* parser, int argc, char *argv[])
+{
+ std::cout << "Usage: plastimatch bbox [options] input-file\n";
+ parser->print_options (std::cout);
+ std::cout << std::endl;
+}
+
+static void
+parse_fn (
+ Bbox_parms* parms,
+ dlib::Plm_clp* parser,
+ int argc,
+ char* argv[]
+)
+{
+ /* Add --help, --version */
+ parser->add_default_options ();
+
+ /* Basic options */
+ parser->add_long_option ("", "output",
+ "Location of output image", 1, "");
+ parser->add_long_option ("", "margin",
+ "Expand bounding box by margin (mm, may be negative)", 1, "0");
+ parser->add_long_option ("", "z-only",
+ "When creating output image, only consider z axis", 0);
+
+ /* Parse options */
+ parser->parse (argc,argv);
+
+ /* Handle --help, --version */
+ parser->check_default_options ();
+
+ /* Check that all necessary inputs are given */
+ if (parser->number_of_arguments() != 1) {
+ throw (dlib::error (
+ "Error. A single input file must be given."));
+ }
+
+ /* Get input file */
+ parms->input_fn = (*parser)[0];
+
+ /* Copy remaining values into parameter struct */
+ parms->margin = parser->get_float ("margin");
+ if (parser->have_option ("output")) {
+ parms->output_mask_fn = parser->get_string ("output");
+ }
+ if (parser->have_option ("z-only")) {
+ parms->z_only = true;
+ }
+}
+
+void
+do_command_bbox (int argc, char *argv[])
+{
+ Bbox_parms bbox_parms;
+
+ plm_clp_parse (&bbox_parms, &parse_fn, &usage_fn, argc, argv, 1);
+
+ do_bbox (&bbox_parms);
+}
diff --git a/src/plastimatch/cli/pcmd_drr.h b/src/plastimatch/cli/pcmd_bbox.h
old mode 100755
new mode 100644
similarity index 73%
copy from src/plastimatch/cli/pcmd_drr.h
copy to src/plastimatch/cli/pcmd_bbox.h
index 91002cf..d5056db
--- a/src/plastimatch/cli/pcmd_drr.h
+++ b/src/plastimatch/cli/pcmd_bbox.h
@@ -1,10 +1,10 @@
/* -----------------------------------------------------------------------
See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
----------------------------------------------------------------------- */
-#ifndef _pcmd_drr_h_
-#define _pcmd_drr_h_
+#ifndef _pcmd_bbox_h_
+#define _pcmd_bbox_h_
void
-do_command_drr (int argc, char *argv[]);
+do_command_bbox (int argc, char *argv[]);
#endif
diff --git a/src/plastimatch/cli/pcmd_benchmark.cxx b/src/plastimatch/cli/pcmd_benchmark.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_benchmark.h b/src/plastimatch/cli/pcmd_benchmark.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_boundary.cxx b/src/plastimatch/cli/pcmd_boundary.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_boundary.h b/src/plastimatch/cli/pcmd_boundary.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_compare.cxx b/src/plastimatch/cli/pcmd_compare.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_compare.h b/src/plastimatch/cli/pcmd_compare.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_compose.cxx b/src/plastimatch/cli/pcmd_compose.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_compose.h b/src/plastimatch/cli/pcmd_compose.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_crop.cxx b/src/plastimatch/cli/pcmd_crop.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_crop.h b/src/plastimatch/cli/pcmd_crop.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_dice.cxx b/src/plastimatch/cli/pcmd_dice.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_dice.h b/src/plastimatch/cli/pcmd_dice.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_diff.cxx b/src/plastimatch/cli/pcmd_diff.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_diff.h b/src/plastimatch/cli/pcmd_diff.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_dmap.cxx b/src/plastimatch/cli/pcmd_dmap.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_dmap.h b/src/plastimatch/cli/pcmd_dmap.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_dose.cxx b/src/plastimatch/cli/pcmd_dose.cxx
new file mode 100644
index 0000000..abae3b5
--- /dev/null
+++ b/src/plastimatch/cli/pcmd_dose.cxx
@@ -0,0 +1,33 @@
+/* -----------------------------------------------------------------------
+ See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
+ ----------------------------------------------------------------------- */
+#include "plmcli_config.h"
+#include <stdlib.h>
+
+#include "logfile.h"
+#include "pcmd_dose.h"
+#include "plm_return_code.h"
+#include "plm_timer.h"
+#include "rt_plan.h"
+
+void
+do_command_dose (int argc, char* argv[])
+{
+
+ if (argc < 3) {
+ lprintf ("Usage: plastimatch dose command_file\n");
+ exit (1);
+ }
+
+ char *command_file = argv[2];
+
+ Plm_timer timer;
+ Rt_plan plan;
+ timer.start ();
+ if (plan.set_command_file (command_file) != PLM_SUCCESS) {
+ lprintf ("Error parsing command file.\n");
+ return;
+ }
+ plan.compute_plan ();
+ lprintf ("Total execution time : %f secondes.\n", timer.report ());
+}
diff --git a/src/plastimatch/cli/pcmd_add.h b/src/plastimatch/cli/pcmd_dose.h
old mode 100755
new mode 100644
similarity index 74%
copy from src/plastimatch/cli/pcmd_add.h
copy to src/plastimatch/cli/pcmd_dose.h
index d5b7913..9641386
--- a/src/plastimatch/cli/pcmd_add.h
+++ b/src/plastimatch/cli/pcmd_dose.h
@@ -1,11 +1,11 @@
/* -----------------------------------------------------------------------
See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
----------------------------------------------------------------------- */
-#ifndef _pcmd_add_h_
-#define _pcmd_add_h_
+#ifndef _pcmd_dose_h_
+#define _pcmd_dose_h_
#include "plmcli_config.h"
-void do_command_add (int argc, char *argv[]);
+void do_command_dose (int argc, char *argv[]);
#endif
diff --git a/src/plastimatch/cli/pcmd_drr.cxx b/src/plastimatch/cli/pcmd_drr.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_drr.h b/src/plastimatch/cli/pcmd_drr.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_dvh.cxx b/src/plastimatch/cli/pcmd_dvh.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_dvh.h b/src/plastimatch/cli/pcmd_dvh.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_filter.cxx b/src/plastimatch/cli/pcmd_filter.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_filter.h b/src/plastimatch/cli/pcmd_filter.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_gamma.cxx b/src/plastimatch/cli/pcmd_gamma.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_gamma.h b/src/plastimatch/cli/pcmd_gamma.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_header.cxx b/src/plastimatch/cli/pcmd_header.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_header.h b/src/plastimatch/cli/pcmd_header.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_mabs.cxx b/src/plastimatch/cli/pcmd_mabs.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_mabs.h b/src/plastimatch/cli/pcmd_mabs.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_mask.cxx b/src/plastimatch/cli/pcmd_mask.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_mask.h b/src/plastimatch/cli/pcmd_mask.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_probe.h b/src/plastimatch/cli/pcmd_probe.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_register.cxx b/src/plastimatch/cli/pcmd_register.cxx
index e226913..e69caed 100644
--- a/src/plastimatch/cli/pcmd_register.cxx
+++ b/src/plastimatch/cli/pcmd_register.cxx
@@ -3,7 +3,9 @@
----------------------------------------------------------------------- */
#include "plmcli_config.h"
+#include "logfile.h"
#include "pcmd_register.h"
+#include "plm_return_code.h"
#include "registration.h"
void
@@ -23,9 +25,12 @@ do_command_register (int argc, char* argv[])
}
Registration reg;
- if (reg.set_command_file (command_filename) < 0) {
- printf ("Error. could not load %s as command file.\n",
+ Plm_return_code rc = reg.set_command_file (command_filename);
+ if (rc != PLM_SUCCESS) {
+ logfile_printf ("Error. Could not load %s as command file.\n",
command_filename);
+ exit (1);
}
+
reg.do_registration ();
}
diff --git a/src/plastimatch/cli/pcmd_scale.h b/src/plastimatch/cli/pcmd_scale.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_segment.cxx b/src/plastimatch/cli/pcmd_segment.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_segment.h b/src/plastimatch/cli/pcmd_segment.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_sift.h b/src/plastimatch/cli/pcmd_sift.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_stats.cxx b/src/plastimatch/cli/pcmd_stats.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_stats.h b/src/plastimatch/cli/pcmd_stats.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_synth.cxx b/src/plastimatch/cli/pcmd_synth.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_synth.h b/src/plastimatch/cli/pcmd_synth.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_synth_vf.cxx b/src/plastimatch/cli/pcmd_synth_vf.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_synth_vf.h b/src/plastimatch/cli/pcmd_synth_vf.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_threshold.cxx b/src/plastimatch/cli/pcmd_threshold.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_threshold.h b/src/plastimatch/cli/pcmd_threshold.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_thumbnail.cxx b/src/plastimatch/cli/pcmd_thumbnail.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_thumbnail.h b/src/plastimatch/cli/pcmd_thumbnail.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_union.h b/src/plastimatch/cli/pcmd_union.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/standalone/vf_invert_main.cxx b/src/plastimatch/cli/pcmd_vf_invert.cxx
old mode 100755
new mode 100644
similarity index 88%
copy from src/plastimatch/standalone/vf_invert_main.cxx
copy to src/plastimatch/cli/pcmd_vf_invert.cxx
index e461c4e..e9527a6
--- a/src/plastimatch/standalone/vf_invert_main.cxx
+++ b/src/plastimatch/cli/pcmd_vf_invert.cxx
@@ -1,19 +1,15 @@
/* -----------------------------------------------------------------------
See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
----------------------------------------------------------------------- */
-#include "plm_config.h"
-#include "itkImage.h"
+#include "plmcli_config.h"
#include "itk_image_load.h"
#include "mha_io.h"
#include "plm_clp.h"
-#include "plm_int.h"
#include "plm_image.h"
#include "plm_image_header.h"
-#include "plm_math.h"
#include "vf_convolve.h"
#include "vf_invert.h"
-#include "volume.h"
class Vf_invert_parms {
public:
@@ -46,36 +42,6 @@ public:
}
};
-#if defined (commentout)
-void
-vf_invert_itk (Vf_Invert_Parms* parms)
-{
- typedef itk::InverseDeformationFieldImageFilter < DeformationFieldType, DeformationFieldType > FilterType;
-
- Plm_image_header pih;
-
- if (parms->fixed_img_fn[0]) {
- /* if given, use the parameters from user-supplied fixed image */
- FloatImageType::Pointer fixed = load_float (parms->fixed_img_fn);
- pih.set_from_itk_image (fixed);
- } else {
- pih.set_from_gpuit (parms->origin, parms->spacing, parms->dim);
- }
-
- FilterType::Pointer filter = FilterType::New ();
- DeformationFieldType::Pointer vf_in = load_float_field (parms->vf_in_fn);
- filter->SetInput (vf_in);
- filter->SetOutputOrigin (pih.origin);
- filter->SetOutputSpacing (pih.spacing);
- filter->SetSize (pih.m_region.GetSize());
-
- //filter->SetOutsideValue( 0 );
- filter->Update();
- DeformationFieldType::Pointer vf_out = filter->GetOutput();
- save_image (vf_out, parms->vf_out_fn);
-}
-#endif
-
void
do_vf_invert_old (Vf_invert_parms* parms)
{
@@ -245,7 +211,8 @@ do_vf_invert (Vf_invert_parms* parms)
static void
usage_fn (dlib::Plm_clp* parser, int argc, char *argv[])
{
- std::cout << "Usage: vf_invert [options]\n";
+ printf ("Usage: plastimatch %s [options] input_file [input_file ...]\n",
+ argv[1]);
parser->print_options (std::cout);
std::cout << std::endl;
}
@@ -335,14 +302,14 @@ parse_fn (
}
}
-int
-main (int argc, char *argv[])
+void
+do_command_vf_invert (int argc, char *argv[])
{
Vf_invert_parms parms;
- plm_clp_parse (&parms, &parse_fn, &usage_fn, argc, argv);
- do_vf_invert (&parms);
+ /* Parse command line parameters */
+ plm_clp_parse (&parms, &parse_fn, &usage_fn, argc, argv, 1);
- printf ("Finished!\n");
- return 0;
+ /* Do the work */
+ do_vf_invert (&parms);
}
diff --git a/src/plastimatch/cli/pcmd_add.h b/src/plastimatch/cli/pcmd_vf_invert.h
old mode 100755
new mode 100644
similarity index 71%
copy from src/plastimatch/cli/pcmd_add.h
copy to src/plastimatch/cli/pcmd_vf_invert.h
index d5b7913..d43f632
--- a/src/plastimatch/cli/pcmd_add.h
+++ b/src/plastimatch/cli/pcmd_vf_invert.h
@@ -1,11 +1,11 @@
/* -----------------------------------------------------------------------
See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
----------------------------------------------------------------------- */
-#ifndef _pcmd_add_h_
-#define _pcmd_add_h_
+#ifndef _pcmd_vf_invert_h_
+#define _pcmd_vf_invert_h_
#include "plmcli_config.h"
-void do_command_add (int argc, char *argv[]);
+void do_command_vf_invert (int argc, char *argv[]);
#endif
diff --git a/src/plastimatch/cli/pcmd_warp.cxx b/src/plastimatch/cli/pcmd_warp.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_warp.h b/src/plastimatch/cli/pcmd_warp.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_warp_pointset.cxx b/src/plastimatch/cli/pcmd_warp_pointset.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_xf_convert.cxx b/src/plastimatch/cli/pcmd_xf_convert.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_xf_convert.h b/src/plastimatch/cli/pcmd_xf_convert.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_xio_dvh.cxx b/src/plastimatch/cli/pcmd_xio_dvh.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/pcmd_xio_dvh.h b/src/plastimatch/cli/pcmd_xio_dvh.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cli/plastimatch_main.cxx b/src/plastimatch/cli/plastimatch_main.cxx
index 7c6a4f4..37ae1ae 100644
--- a/src/plastimatch/cli/plastimatch_main.cxx
+++ b/src/plastimatch/cli/plastimatch_main.cxx
@@ -10,6 +10,7 @@
#include "pcmd_adjust.h"
#include "pcmd_autolabel.h"
#include "pcmd_autolabel_train.h"
+#include "pcmd_bbox.h"
#include "pcmd_benchmark.h"
#include "pcmd_boundary.h"
#include "pcmd_compare.h"
@@ -18,6 +19,7 @@
#include "pcmd_dice.h"
#include "pcmd_diff.h"
#include "pcmd_dmap.h"
+#include "pcmd_dose.h"
#include "pcmd_drr.h"
#include "pcmd_dvh.h"
#include "pcmd_filter.h"
@@ -42,6 +44,7 @@
#include "pcmd_threshold.h"
#include "pcmd_thumbnail.h"
#include "pcmd_union.h"
+#include "pcmd_vf_invert.h"
#include "pcmd_warp.h"
#include "pcmd_xf_convert.h"
#include "pcmd_xio_dvh.h"
@@ -66,48 +69,52 @@ print_usage (int return_code)
" adjust "
// " autolabel "
" average "
+ " bbox "
// " benchmark "
" boundary "
- " crop "
"\n"
+ " crop "
" compare "
" compose "
" convert "
" dice "
- " diff "
"\n"
+ " diff "
" dmap "
+ " dose "
// " drr "
" dvh "
" fill "
+ "\n"
" filter "
" gamma "
- "\n"
" header "
" jacobian "
" mabs "
+ "\n"
" mask "
" maximum "
- "\n"
" ml-convert "
" multiply "
" probe "
+ "\n"
" register "
" resample "
- "\n"
" scale "
" segment "
// " sift "
" stats "
+ "\n"
" synth "
" synth-vf "
- "\n"
" threshold "
" thumbnail "
" union "
+ "\n"
+ " vf-invert "
" warp "
- " xf-convert "
// " xio-dvh "
+ " xf-convert "
"\n"
"\n"
"For detailed usage of a specific command, type:\n"
@@ -146,6 +153,9 @@ do_command (int argc, char* argv[])
else if (!strcmp (command, "autolabel-train")) {
do_command_autolabel_train (argc, argv);
}
+ else if (!strcmp (command, "bbox")) {
+ do_command_bbox (argc, argv);
+ }
else if (!strcmp (command, "benchmark")) {
do_command_benchmark (argc, argv);
}
@@ -171,6 +181,9 @@ do_command (int argc, char* argv[])
else if (!strcmp (command, "diff")) {
do_command_diff (argc, argv);
}
+ else if (!strcmp (command, "dose")) {
+ do_command_dose (argc, argv);
+ }
else if (!strcmp (command, "drr")) {
do_command_drr (argc, argv);
}
@@ -256,6 +269,9 @@ do_command (int argc, char* argv[])
else if (!strcmp (command, "union")) {
do_command_union (argc, argv);
}
+ else if (!strcmp (command, "vf-invert")) {
+ do_command_vf_invert (argc, argv);
+ }
else if (!strcmp (command, "warp")) {
/* convert and warp are the same */
do_command_warp (argc, argv);
diff --git a/src/plastimatch/clp/CMakeLists.txt b/src/plastimatch/clp/CMakeLists.txt
old mode 100755
new mode 100644
diff --git a/src/plastimatch/clp/plm_clp.cxx b/src/plastimatch/clp/plm_clp.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/clp/plm_clp.h b/src/plastimatch/clp/plm_clp.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/cuda/cuda_probe.h b/src/plastimatch/cuda/cuda_probe.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/dose/CMakeLists.txt b/src/plastimatch/dose/CMakeLists.txt
old mode 100644
new mode 100755
index 12582d0..9a0579c
--- a/src/plastimatch/dose/CMakeLists.txt
+++ b/src/plastimatch/dose/CMakeLists.txt
@@ -14,22 +14,27 @@ include_directories (BEFORE ${CMAKE_CURRENT_SOURCE_DIR})
## SOURCE FILES
##-----------------------------------------------------------------------------
set (PLMDOSE_LIBRARY_SRC
- bragg_curve.cxx
- dose_volume_functions.cxx
+ bragg_curve.cxx bragg_curve.h
+ dose_volume_functions.cxx dose_volume_functions.h
particle_type.cxx particle_type.h
- rt_beam.cxx
- rt_depth_dose.cxx
- rt_dose.cxx
- rt_lut.cxx
- rt_mebs.cxx
- rt_parms.cxx
- rt_plan.cxx
- rt_sigma.cxx
- wed_parms.cxx
+ rt_beam.cxx rt_beam.h
+ rt_beam_model.cxx rt_beam_model.h
+ rt_depth_dose.cxx rt_depth_dose.h
+ rt_dij.cxx rt_dij.h
+ rt_dose.cxx rt_dose.h
+ rt_dose_timing.h
+ rt_lut.cxx rt_lut.h
+ rt_spot_map.cxx rt_spot_map.h
+ rt_mebs.cxx rt_mebs.h
+ rt_parms.cxx rt_parms.h
+ rt_plan.cxx rt_plan.h
+ rt_sigma.cxx rt_sigma.h
+ wed_parms.cxx wed_parms.h
)
set (PLMDOSE_LIBRARY_DEPENDENCIES
plmbase
+ plmutil
plmsys
)
diff --git a/src/plastimatch/dose/dose_volume_functions.cxx b/src/plastimatch/dose/dose_volume_functions.cxx
old mode 100644
new mode 100755
index d27b49d..f6bf6bd
--- a/src/plastimatch/dose/dose_volume_functions.cxx
+++ b/src/plastimatch/dose/dose_volume_functions.cxx
@@ -1,13 +1,18 @@
/* -----------------------------------------------------------------------
See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
----------------------------------------------------------------------- */
-
+#include "plmdose_config.h"
#include "dose_volume_functions.h"
#include "proj_volume.h"
#include "ray_data.h"
#include "rt_lut.h"
-void dose_volume_create(Volume* dose_volume, float* sigma_max, Rpl_volume* volume, double range)
+void
+dose_volume_create (
+ Volume* dose_volume,
+ float* sigma_max,
+ Rpl_volume* volume,
+ double range)
{
/* we want to add extra margins around our volume take into account the dose that will be scattered outside of the rpl_volume */
/* A 3 sigma margin is applied to the front_back volume, and the size of our volume will be the projection of this shape on the back_clipping_plane */
@@ -18,7 +23,6 @@ void dose_volume_create(Volume* dose_volume, float* sigma_max, Rpl_volume* volum
plm_long dim[3] = {0,0,0};
float origin[3] = {0,0,0};
float spacing[3] = {0,0,0};
- plm_long npix = 0;
const float dc[9] = {
dose_volume->get_direction_cosines()[0], dose_volume->get_direction_cosines()[1], dose_volume->get_direction_cosines()[2],
dose_volume->get_direction_cosines()[3], dose_volume->get_direction_cosines()[4], dose_volume->get_direction_cosines()[5],
@@ -55,12 +59,13 @@ void dose_volume_create(Volume* dose_volume, float* sigma_max, Rpl_volume* volum
dim[i] = (plm_long) ((back_clip_useful - volume->get_front_clipping_plane())/spacing[i] + 1);
}
}
- npix = dim[0]*dim[1]*dim[2];
dose_volume->create(dim, origin, spacing, dc, PT_FLOAT,1);
}
void
-calculate_rpl_coordinates_xyz(std::vector<std:: vector<double> >* xyz_coordinates_volume, Rpl_volume* rpl_volume)
+calculate_rpl_coordinates_xyz (
+ std::vector<std:: vector<double> >* xyz_coordinates_volume,
+ Rpl_volume* rpl_volume)
{
double aperture[3] = {0.0,0.0,0.0};
double entrance[3] = {0.0,0.0,0.0};
@@ -75,7 +80,7 @@ calculate_rpl_coordinates_xyz(std::vector<std:: vector<double> >* xyz_coordinate
for (int j = 0; j < rpl_volume->get_vol()->dim[1];j++){
idx2d = j * dim[0] + i;
- Ray_data* ray_data = &rpl_volume->get_Ray_data()[idx2d];
+ Ray_data* ray_data = &rpl_volume->get_ray_data()[idx2d];
vec3_cross(vec_antibug_prt, rpl_volume->get_aperture()->pdn, rpl_volume->get_proj_volume()->get_nrm());
ray_bev[0] = vec3_dot(ray_data->ray, vec_antibug_prt);
@@ -100,7 +105,7 @@ calculate_rpl_coordinates_xyz(std::vector<std:: vector<double> >* xyz_coordinate
void
dose_volume_reconstruction (
- Rpl_volume* rpl_dose_vol,
+ Rpl_volume* dose_rv,
Volume::Pointer dose_vol
)
{
@@ -111,7 +116,7 @@ dose_volume_reconstruction (
double dose = 0;
float* dose_img = (float*) dose_vol->img;
-
+ bool first = true;
for (ct_ijk[2] = 0; ct_ijk[2] < dose_vol->dim[2]; ct_ijk[2]++) {
for (ct_ijk[1] = 0; ct_ijk[1] < dose_vol->dim[1]; ct_ijk[1]++) {
for (ct_ijk[0] = 0; ct_ijk[0] < dose_vol->dim[0]; ct_ijk[0]++) {
@@ -123,7 +128,7 @@ dose_volume_reconstruction (
ct_xyz[2] = (double) (dose_vol->origin[2] + ct_ijk[2] * dose_vol->spacing[2]);
ct_xyz[3] = (double) 1.0;
idx = volume_index (dose_vol->dim, ct_ijk);
- dose = rpl_dose_vol->get_rgdepth(ct_xyz);
+ dose = dose_rv->get_value(ct_xyz);
if (dose <= 0) {
continue;
@@ -136,7 +141,12 @@ dose_volume_reconstruction (
}
}
-void build_hong_grid(std::vector<double>* area, std::vector<double>* xy_grid, int radius_sample, int theta_sample)
+void
+build_hong_grid (
+ std::vector<double>* area,
+ std::vector<double>* xy_grid,
+ int radius_sample,
+ int theta_sample)
{
double dr = 1.0 / (double) radius_sample;
double dt = 2.0 * M_PI / (double) theta_sample;
@@ -197,7 +207,7 @@ find_xyz_from_ijk(double* xyz, Volume* volume, int* ijk)
xyz[2] = volume->origin[2] + ijk[2]*volume->spacing[2];
}
-double erf_gauss(double x)
+double erf_gauss (double x)
{
int sign = 1;
if (x < 0) {sign = -1;}
@@ -209,7 +219,9 @@ double erf_gauss(double x)
return sign*y;
}
-double double_gaussian_interpolation(double* gaussian_center, double* pixel_center, double sigma, double* spacing)
+double
+double_gaussian_interpolation (
+ double* gaussian_center, double* pixel_center, double sigma, double* spacing)
{
double x1 = pixel_center[0] - 0.5 * spacing[0];
double x2 = x1 + spacing[0];
@@ -230,50 +242,49 @@ double get_off_axis(double radius, double dr, double sigma)
/* MD Fix: don't consider any cosines directions */
void dose_normalization_to_dose(Volume::Pointer dose_volume, double dose, Rt_beam* beam)
{
- int idx = 0;
- double norm = 0;
- int ijk_max[3] = {0,0,0};
- float* img = (float*) dose_volume->img;
-
- for(int i = 0; i < dose_volume->dim[0]; i++)
- {
- for(int j = 0; j < dose_volume->dim[1]; j++)
- {
- for(int k = 0; k < dose_volume->dim[2]; k++)
- {
- idx = i + (dose_volume->dim[0] * (j + dose_volume->dim[1] * k));
-
- if (img[idx] > norm)
- {
- norm = img[idx];
- ijk_max[0] = i;
- ijk_max[1] = j;
- ijk_max[2] = k;
- }
- }
- }
- }
- if (norm > 0)
- {
- for (int i = 0; i < dose_volume->dim[0] * dose_volume->dim[1] * dose_volume->dim[2]; i++)
- {
- img[i] = img[i] / norm * dose;
- }
- int ap_dim[2] = {beam->get_aperture()->get_dim(0),beam->get_aperture()->get_dim(1)};
- beam->get_mebs()->scale_num_part(dose/norm, ap_dim);
-
- printf("Raw dose at the maximum (%lg, %lg, %lg) : %lg A.U.\nDose normalized at the maximum to ", dose_volume->origin[0] + ijk_max[0] * dose_volume->spacing[0], dose_volume->origin[1] + ijk_max[1] * dose_volume->spacing[1], dose_volume->origin[2] + ijk_max[2] * dose_volume->spacing[2], norm);
- }
- else
- {
- printf("Dose is null in the entire volume. Please check your input conditions.\n");
- }
+ int idx = 0;
+ double norm = 0;
+ int ijk_max[3] = {0,0,0};
+ float* img = (float*) dose_volume->img;
+
+ for(int i = 0; i < dose_volume->dim[0]; i++)
+ {
+ for(int j = 0; j < dose_volume->dim[1]; j++)
+ {
+ for(int k = 0; k < dose_volume->dim[2]; k++)
+ {
+ idx = i + (dose_volume->dim[0] * (j + dose_volume->dim[1] * k));
+
+ if (img[idx] > norm)
+ {
+ norm = img[idx];
+ ijk_max[0] = i;
+ ijk_max[1] = j;
+ ijk_max[2] = k;
+ }
+ }
+ }
+ }
+ if (norm > 0)
+ {
+ for (int i = 0; i < dose_volume->dim[0] * dose_volume->dim[1] * dose_volume->dim[2]; i++)
+ {
+ img[i] = img[i] / norm * dose;
+ }
+ int ap_dim[2] = {beam->get_aperture()->get_dim(0),beam->get_aperture()->get_dim(1)};
+ beam->get_mebs()->scale_num_part(dose/norm, ap_dim);
+
+ printf("Raw dose at the maximum (%lg, %lg, %lg) : %lg A.U.\nDose normalized at the maximum to ", dose_volume->origin[0] + ijk_max[0] * dose_volume->spacing[0], dose_volume->origin[1] + ijk_max[1] * dose_volume->spacing[1], dose_volume->origin[2] + ijk_max[2] * dose_volume->spacing[2], norm);
+ }
+ else
+ {
+ printf("Dose is null in the entire volume. Please check your input conditions.\n");
+ }
}
/* MD Fix: don't consider any cosines directions */
void dose_normalization_to_dose_and_point(Volume::Pointer dose_volume, double dose, const float* rdp_ijk, const float* rdp, Rt_beam* beam)
{
- std::vector<float>& num_part = beam->get_mebs()->get_num_particles();
double norm = dose_volume->get_ijk_value(rdp_ijk);
float* img = (float*) dose_volume->img;
@@ -289,7 +300,7 @@ void dose_normalization_to_dose_and_point(Volume::Pointer dose_volume, double do
}
else
{
- printf("***WARNING***\nDose null at the reference dose point.\nDose normalized to the dose maximum in the volume.\n");
+ printf("Dose null at the reference dose point.\nDose normalized to the dose maximum in the volume.\n");
dose_normalization_to_dose(dose_volume, dose,beam);
}
}
diff --git a/src/plastimatch/dose/dose_volume_functions.h b/src/plastimatch/dose/dose_volume_functions.h
old mode 100644
new mode 100755
index d17cad9..91b62c8
--- a/src/plastimatch/dose/dose_volume_functions.h
+++ b/src/plastimatch/dose/dose_volume_functions.h
@@ -11,7 +11,7 @@
void dose_volume_create(Volume* dose_volume, float* sigma_max, Rpl_volume* volume, double range);
void calculate_rpl_coordinates_xyz(std::vector<std::vector<double> >* xyz_coordinates_volume, Rpl_volume* rpl_volume);
-void dose_volume_reconstruction(Rpl_volume* rpl_dose_vol, Volume::Pointer dose_vol);
+void dose_volume_reconstruction(Rpl_volume* dose_rv, Volume::Pointer dose_vol);
void build_hong_grid(std::vector<double>* area, std::vector<double>* xy_grid, int radius_sample, int theta_sample);
@@ -29,4 +29,4 @@ double get_off_axis(double radius, double dr, double sigma);
void dose_normalization_to_dose(Volume::Pointer dose_volume, double dose, Rt_beam* beam);
void dose_normalization_to_dose_and_point(Volume::Pointer dose_volume, double dose, const float* rdp_ijk, const float* rdp, Rt_beam* beam);
-#endif
\ No newline at end of file
+#endif
diff --git a/src/plastimatch/dose/rt_beam.cxx b/src/plastimatch/dose/rt_beam.cxx
old mode 100644
new mode 100755
index 0841b45..a940ffd
--- a/src/plastimatch/dose/rt_beam.cxx
+++ b/src/plastimatch/dose/rt_beam.cxx
@@ -2,7 +2,6 @@
See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
----------------------------------------------------------------------- */
#include "plmdose_config.h"
-#include "proj_volume.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -10,8 +9,39 @@
#include <math.h>
#include "bragg_curve.h"
+#include "plm_math.h"
+#include "proj_volume.h"
#include "rt_beam.h"
+#include "rt_dose_timing.h"
#include "rt_plan.h"
+#include "rt_spot_map.h"
+
+static void
+save_vector_as_image (
+ const std::vector<double>& v,
+ const int dim2d[2],
+ const std::string& filename)
+{
+ plm_long dim[3] = { dim2d[0], dim2d[1], 1 };
+ float origin[3] = { 0.f, 0.f, 0.f };
+ float spacing[3] = { 1.f, 1.f, 1.f };
+ Volume::Pointer vol = Volume::New (
+ dim, origin, spacing, (float*) 0, PT_FLOAT, 1);
+ float *vol_img = vol->get_raw<float> ();
+
+ for (plm_long i = 0; i < vol->npix; i++)
+ {
+ if (std::isnan(v[i]) || std::isinf(v[i]) || v[i] == NLMAX(double)) {
+ vol_img[i] = -1;
+ } else {
+ vol_img[i] = (float) v[i];
+ }
+ }
+
+ Plm_image::Pointer img = Plm_image::New (vol);
+ img->save_image (filename);
+}
+
class Rt_beam_private {
public:
@@ -21,22 +51,29 @@ public:
double source[3];
double isocenter[3];
- char flavor;
+ std::string flavor;
char homo_approx;
float beamWeight;
+ Rt_spot_map::Pointer spot_map;
Rt_mebs::Pointer mebs;
std::string debug_dir;
float smearing;
char rc_MC_model;
float source_size;
-
float step_length;
- Aperture::Pointer aperture;
+ double max_wed;
+ double min_wed;
+
+ Plm_image::Pointer ct_hu;
+ Plm_image::Pointer ct_psp;
Plm_image::Pointer target;
+ Aperture::Pointer aperture;
+
+ Rt_dose_timing::Pointer rt_dose_timing;
std::string aperture_in;
std::string range_compensator_in;
@@ -44,9 +81,13 @@ public:
std::string aperture_out;
std::string proj_dose_out;
std::string proj_img_out;
+ std::string proj_target_out;
std::string range_compensator_out;
std::string sigma_out;
std::string wed_out;
+ std::string beam_dump_out;
+ std::string dij_out;
+
std::string beam_line_type;
public:
@@ -60,24 +101,29 @@ public:
this->isocenter[0] = 0.f;
this->isocenter[1] = 0.f;
this->isocenter[2] = 0.f;
- this->flavor = 'a';
+ this->flavor = "a";
this->homo_approx = 'n';
this->beamWeight = 1.f;
+ this->spot_map = Rt_spot_map::New();
this->mebs = Rt_mebs::New();
this->debug_dir = "";
this->smearing = 0.f;
this->rc_MC_model = 'n';
this->source_size = 0.f;
this->step_length = 1.f;
+ this->min_wed = 0.;
+ this->max_wed = 0.;
aperture = Aperture::New();
+ rt_dose_timing = Rt_dose_timing::New();
this->aperture_in = "";
this->range_compensator_in = "";
this->aperture_out = "";
this->proj_dose_out = "";
this->proj_img_out = "";
+ this->proj_target_out = "";
this->range_compensator_out = "";
this->sigma_out = "";
this->wed_out = "";
@@ -96,22 +142,30 @@ public:
this->flavor = rtbp->flavor;
this->homo_approx = rtbp->homo_approx;
- /* Copy the mebs object */
this->beamWeight = rtbp->beamWeight;
- this->mebs = Rt_mebs::New (rtbp->mebs);
+ // Clear the spot map
+ this->spot_map = Rt_spot_map::New();
+ // Copy the mebs object (?)
+ this->mebs = Rt_mebs::New(rtbp->mebs);
this->debug_dir = rtbp->debug_dir;
this->smearing = rtbp->smearing;
this->source_size = rtbp->source_size;
this->step_length = rtbp->step_length;
+ this->min_wed = rtbp->min_wed;
+ this->max_wed = rtbp->max_wed;
/* Copy the aperture object */
aperture = Aperture::New (rtbp->aperture);
+ /* Share same timing object */
+ rt_dose_timing = rtbp->rt_dose_timing;
+
this->aperture_in = rtbp->aperture_in;
this->range_compensator_in = rtbp->range_compensator_in;
this->aperture_out = rtbp->aperture_out;
this->proj_dose_out = rtbp->proj_dose_out;
this->proj_img_out = rtbp->proj_img_out;
+ this->proj_target_out = rtbp->proj_target_out;
this->range_compensator_out = rtbp->range_compensator_out;
this->sigma_out = rtbp->sigma_out;
this->wed_out = rtbp->wed_out;
@@ -122,35 +176,15 @@ public:
Rt_beam::Rt_beam ()
{
this->d_ptr = new Rt_beam_private();
- this->rpl_vol = new Rpl_volume();
/* Creation of the volumes useful for dose calculation */
-
- if (this->get_flavor() == 'f')
- {
- this->rpl_ct_vol_HU = new Rpl_volume();
- this->sigma_vol = new Rpl_volume();
- }
-
- if (this->get_flavor() == 'g')
- {
- this->rpl_ct_vol_HU = new Rpl_volume();
- this->sigma_vol = new Rpl_volume();
- this->rpl_vol_lg = new Rpl_volume();
- this->rpl_ct_vol_HU_lg = new Rpl_volume();
- this->sigma_vol_lg = new Rpl_volume();
- this->rpl_dose_vol = new Rpl_volume();
- }
-
- if (this->get_flavor() == 'h')
- {
- this->rpl_ct_vol_HU = new Rpl_volume();
- this->sigma_vol = new Rpl_volume();
- this->rpl_vol_lg = new Rpl_volume();
- this->rpl_ct_vol_HU_lg = new Rpl_volume();
- this->sigma_vol_lg = new Rpl_volume();
- this->rpl_dose_vol = new Rpl_volume();
- }
+ this->rsp_accum_vol = new Rpl_volume();
+ this->hu_samp_vol = 0;
+ this->sigma_vol = 0;
+ this->rpl_vol_lg = 0;
+ this->rpl_vol_samp_lg = 0;
+ this->sigma_vol_lg = 0;
+ this->dose_rv = 0;
}
Rt_beam::Rt_beam (const Rt_beam* rt_beam)
@@ -160,13 +194,13 @@ Rt_beam::Rt_beam (const Rt_beam* rt_beam)
/* The below calculation volumes don't need to be copied
from input beam */
- this->rpl_vol = 0;
- this->rpl_ct_vol_HU = 0;
+ this->rsp_accum_vol = 0;
+ this->hu_samp_vol = 0;
this->sigma_vol = 0;
this->rpl_vol_lg = 0;
- this->rpl_ct_vol_HU_lg = 0;
+ this->rpl_vol_samp_lg = 0;
this->sigma_vol_lg = 0;
- this->rpl_dose_vol = 0;
+ this->dose_rv = 0;
}
Rt_beam::~Rt_beam ()
@@ -256,14 +290,14 @@ Rt_beam::get_source_distance () const
return vec3_dist (d_ptr->isocenter, d_ptr->source);
}
-char
+const std::string&
Rt_beam::get_flavor (void) const
{
return d_ptr->flavor;
}
void
-Rt_beam::set_flavor (char flavor)
+Rt_beam::set_flavor (const std::string& flavor)
{
d_ptr->flavor = flavor;
}
@@ -277,13 +311,13 @@ Rt_beam::get_homo_approx () const
void
Rt_beam::set_homo_approx (char homo_approx)
{
- d_ptr->homo_approx = homo_approx;
+ d_ptr->homo_approx = homo_approx;
}
Rt_mebs::Pointer
Rt_beam::get_mebs()
{
- return d_ptr->mebs;
+ return d_ptr->mebs;
}
float
@@ -334,116 +368,235 @@ Rt_beam::dump (const char* dir)
d_ptr->mebs->dump (dir);
}
+void
+Rt_beam::dump (const std::string& dir)
+{
+ this->dump (dir.c_str());
+}
+
void
-Rt_beam::compute_prerequisites_beam_tools(Plm_image::Pointer& target)
+Rt_beam::add_spot (
+ float xpos,
+ float ypos,
+ float energy,
+ float sigma,
+ float weight)
{
- if (d_ptr->mebs->get_have_particle_number_map() == true && d_ptr->beam_line_type == "passive")
+ d_ptr->spot_map->add_spot (xpos, ypos, energy, sigma, weight);
+}
+
+bool
+Rt_beam::prepare_for_calc (
+ Plm_image::Pointer& ct_hu,
+ Plm_image::Pointer& ct_psp,
+ Plm_image::Pointer& target)
+{
+ if (!ct_hu) return false;
+ if (!ct_psp) return false;
+ d_ptr->ct_hu = ct_hu;
+ d_ptr->ct_psp = ct_psp;
+ d_ptr->target = target;
+
+ if (this->get_aperture()->get_distance() > this->get_source_distance ()) {
+ lprintf ("Source distance must be greater than aperture distance");
+ return false;
+ }
+
+ Rpl_volume_ray_trace_start rvrts = RAY_TRACE_START_AT_CLIPPING_PLANE;
+
+ // Create rsp_accum_vol */
+ if (!this->rsp_accum_vol) {
+ this->rsp_accum_vol = new Rpl_volume;
+ }
+ if (!this->rsp_accum_vol) return false;
+ this->rsp_accum_vol->set_geometry (
+ this->get_source_position(),
+ this->get_isocenter_position(),
+ this->get_aperture()->vup,
+ this->get_aperture()->get_distance(),
+ this->get_aperture()->get_dim(),
+ this->get_aperture()->get_center(),
+ this->get_aperture()->get_spacing(),
+ this->get_step_length());
+ this->rsp_accum_vol->set_aperture (this->get_aperture());
+ this->rsp_accum_vol->set_ray_trace_start (rvrts);
+ this->rsp_accum_vol->set_ct_volume (ct_psp);
+ if (!this->rsp_accum_vol->get_ct() || !this->rsp_accum_vol->get_ct_limit()) {
+ lprintf ("ray_data or clipping planes missing from rpl volume\n");
+ return false;
+ }
+ this->rsp_accum_vol->compute_rpl_accum (false);
+
+ // Create ct projective volume
+ // GCS FIX: The old code re-used the ray data. Is that really faster?
+ this->hu_samp_vol = new Rpl_volume;
+ if (!this->hu_samp_vol) return false;
+ this->hu_samp_vol->clone_geometry (this->rsp_accum_vol);
+ this->hu_samp_vol->set_ray_trace_start (rvrts);
+ this->hu_samp_vol->set_aperture (this->get_aperture());
+ this->hu_samp_vol->set_ct_volume (d_ptr->ct_hu);
+ this->hu_samp_vol->compute_rpl_sample (false);
+
+ // Prepare, but don't compute the sigma volume yet
+ if (this->get_flavor() == "d")
{
- printf("***WARNING*** Passively scattered beam line with spot map file detected: %s.\nBeam line set to active scanning.\n", d_ptr->mebs->get_particle_number_in().c_str());
- printf("Any manual peaks set, depth prescription, target or range compensator will not be considered.\n");
- this->compute_beam_data_from_spot_map();
- return;
+ this->sigma_vol = new Rpl_volume;
+ if (!this->sigma_vol) return false;
+ this->sigma_vol->clone_geometry (this->rsp_accum_vol);
+ this->sigma_vol->set_aperture (this->get_aperture());
+ this->sigma_vol->set_ct_volume (d_ptr->ct_hu);
+ this->sigma_vol->set_ct_limit(this->rsp_accum_vol->get_ct_limit());
+ this->sigma_vol->compute_ray_data();
+ this->sigma_vol->set_front_clipping_plane(this->rsp_accum_vol->get_front_clipping_plane());
+ this->sigma_vol->set_back_clipping_plane(this->rsp_accum_vol->get_back_clipping_plane());
+ this->sigma_vol->compute_rpl_void();
+ }
+
+ // Create target projective volume */
+ if (d_ptr->target) {
+ this->target_rv = Rpl_volume::New();
+ if (!this->target_rv) return false;
+ this->target_rv->clone_geometry (this->rsp_accum_vol);
+ this->target_rv->set_ray_trace_start (rvrts);
+ this->target_rv->set_aperture (this->get_aperture());
+ this->target_rv->set_ct_volume (d_ptr->target);
+ this->target_rv->compute_rpl_sample (false);
}
- /* The priority gets to spot map > manual peaks > dose prescription > target */
+ // Create and fill in rpl_dose_volume (actually proj dose)
+ if (this->get_flavor() == "b"
+ || this->get_flavor() == "ray_trace_dij_a"
+ || this->get_flavor() == "ray_trace_dij_b"
+ || this->get_flavor() == "d")
+ {
+ this->dose_rv = new Rpl_volume;
+ if (!this->dose_rv) return false;
+ this->dose_rv->clone_geometry (this->rsp_accum_vol);
+ this->dose_rv->set_ray_trace_start (rvrts);
+ this->dose_rv->set_aperture (this->get_aperture());
+ this->dose_rv->set_ct_volume (d_ptr->ct_hu);
+ this->dose_rv->set_ct_limit(this->rsp_accum_vol->get_ct_limit());
+ this->dose_rv->compute_ray_data();
+ this->dose_rv->set_front_clipping_plane(this->rsp_accum_vol->get_front_clipping_plane());
+ this->dose_rv->set_back_clipping_plane(this->rsp_accum_vol->get_back_clipping_plane());
+ this->dose_rv->compute_rpl_void();
+ }
+
+ /* The priority how to generate dose is:
+ 1. manual beamlet map
+ 2. manual spot map
+ 3. manual peaks
+ 4. dose prescription
+ 5. target
+ 6. 100 MeV sample beam */
if (d_ptr->mebs->get_have_particle_number_map() == true)
{
- printf("Spot map file detected: Any manual peaks set, depth prescription, target or range compensator will not be considered.\n");
- this->compute_beam_data_from_spot_map();
- return;
+ lprintf ("Beamlet map file detected: Any manual peaks set, depth prescription, target or range compensator will not be considered.\n");
+ this->compute_beam_data_from_beamlet_map ();
+ return true;
+ }
+ if (d_ptr->spot_map->num_spots() > 0)
+ {
+ lprintf ("Beam specified by spot map\n");
+ this->get_mebs()->set_have_manual_peaks(false);
+ this->get_mebs()->set_have_prescription(false);
+ this->compute_beam_data_from_spot_map ();
+ return true;
}
if (d_ptr->mebs->get_have_manual_peaks() == true)
{
- printf("Manual peaks detected [PEAKS]: Any prescription or target depth will not be considered.\n");
- this->get_mebs()->set_have_manual_peaks(true);
- this->compute_beam_data_from_manual_peaks(target);
- return;
+ lprintf("Manual peaks detected [PEAKS]: Any prescription or target depth will not be considered.\n");
+ this->get_mebs()->set_have_manual_peaks (true);
+ this->compute_beam_data_from_manual_peaks (target);
+ return true;
}
if (d_ptr->mebs->get_have_prescription() == true)
{
+ lprintf ("Prescription depths detected. Any target depth will not be considered.\n");
this->get_mebs()->set_have_prescription(true);
/* Apply margins */
- this->get_mebs()->set_target_depths(d_ptr->mebs->get_prescription_min(), d_ptr->mebs->get_prescription_max());
- printf("Prescription depths detected. Any target depth will not be considered.\n");
- this->compute_beam_data_from_prescription(target);
- return;
+ this->get_mebs()->set_target_depths (d_ptr->mebs->get_prescription_min(), d_ptr->mebs->get_prescription_max());
+ this->compute_beam_data_from_prescription (target);
+ return true;
}
- if (target->get_vol())
+ if (target && target->get_vol())
{
- printf("Target detected.\n");
+ lprintf("Target detected.\n");
this->get_mebs()->set_have_manual_peaks(false);
this->get_mebs()->set_have_prescription(false);
this->compute_beam_data_from_target(target);
- return;
+ return true;
}
-
+
/* If we arrive to this point, it is because no beam was defined
Creation of a default beam: 100 MeV */
- printf("***WARNING*** No spot map, manual peaks, depth prescription or target detected.\n");
- printf("Beam set to a 100 MeV mono-energetic beam. Proximal and distal margins not considered.\n");
- this->compute_default_beam();
- return;
+ lprintf("***WARNING*** No beamlet map, manual peaks, depth prescription or target detected.\n");
+ lprintf("Beam set to a 100 MeV mono-energetic beam. Proximal and distal margins not considered.\n");
+ this->compute_default_beam ();
+
+ return true;
}
void
-Rt_beam::compute_beam_data_from_spot_map()
+Rt_beam::compute_beam_data_from_beamlet_map()
{
- this->get_mebs()->clear_depth_dose();
- this->get_mebs()->extract_particle_number_map_from_txt(this->get_aperture());
+ this->get_mebs()->clear_depth_dose ();
+ this->get_mebs()->load_beamlet_map (this->get_aperture());
- /* If an aperture is defined in the input file, the aperture is erased.
- The range compensator is not considered if the beam line is defined as active scanning */
- this->update_aperture_and_range_compensator();
+ /* the automatic aperture and range compensator are erased and the
+ ones defined in the input file are considered */
+ this->update_aperture_and_range_compensator ();
}
void
-Rt_beam::compute_beam_data_from_manual_peaks(Plm_image::Pointer& target)
+Rt_beam::compute_beam_data_from_spot_map()
{
- /* The spot map will be identical for passive or scanning beam lines */
- int ap_dim[2] = {this->get_aperture()->get_dim()[0], this->get_aperture()->get_dim()[1]};
+ this->get_mebs()->set_from_spot_map (d_ptr->spot_map);
+}
+
+void
+Rt_beam::compute_beam_data_from_manual_peaks (Plm_image::Pointer& target)
+{
+ /* The beamlet map will be identical for passive or scanning beam lines */
+ const plm_long* ap_dim = this->get_aperture()->get_dim();
this->get_mebs()->generate_part_num_from_weight(ap_dim);
- if ((target->get_vol() && (d_ptr->aperture_in =="" || d_ptr->range_compensator_in =="")) && (d_ptr->mebs->get_have_manual_peaks() == true || d_ptr->mebs->get_have_prescription() == true)) // we build the associate range compensator and aperture
+ if ((target && (d_ptr->aperture_in =="" || d_ptr->range_compensator_in =="")) && (d_ptr->mebs->get_have_manual_peaks() == true || d_ptr->mebs->get_have_prescription() == true)) // we build the associate range compensator and aperture
{
if (d_ptr->beam_line_type == "active")
{
- this->rpl_vol->compute_beam_modifiers_active_scanning(target->get_vol(), d_ptr->smearing, d_ptr->mebs->get_proximal_margin(), d_ptr->mebs->get_distal_margin());
+ this->compute_beam_modifiers_active_scanning (
+ target->get_vol(), d_ptr->smearing,
+ d_ptr->mebs->get_proximal_margin(),
+ d_ptr->mebs->get_distal_margin());
}
else
{
- this->rpl_vol->compute_beam_modifiers_passive_scattering(target->get_vol(), d_ptr->smearing, d_ptr->mebs->get_proximal_margin(), d_ptr->mebs->get_distal_margin());
+ this->compute_beam_modifiers_passive_scattering (
+ target->get_vol(), d_ptr->smearing,
+ d_ptr->mebs->get_proximal_margin(),
+ d_ptr->mebs->get_distal_margin());
}
}
- /* the aperture and range compensator are erased and the ones defined in the input file are considered */
- this->update_aperture_and_range_compensator();
-}
-
-void
-Rt_beam::compute_beam_data_from_manual_peaks_passive_slicerRt(Plm_image::Pointer& target)
-{
- /* The spot map will be identical for passive or scanning beam lines */
- int ap_dim[2] = {this->get_aperture()->get_dim()[0], this->get_aperture()->get_dim()[1]};
- this->get_mebs()->generate_part_num_from_weight(ap_dim);
-
- this->rpl_vol->compute_beam_modifiers_passive_scattering_slicerRt(target, d_ptr->smearing, d_ptr->mebs->get_proximal_margin(), d_ptr->mebs->get_distal_margin());
-
- /* the aperture and range compensator are erased and the ones defined in the input file are considered */
+ /* the automatic aperture and range compensator are erased and the
+ ones defined in the input file are considered */
this->update_aperture_and_range_compensator();
}
void
Rt_beam::compute_beam_data_from_manual_peaks()
{
- /* The spot map will be identical for passive or scanning beam lines */
- int ap_dim[2] = {this->get_aperture()->get_dim()[0], this->get_aperture()->get_dim()[1]};
+ /* The beamlet map will be identical for passive or scanning beam lines */
+ const plm_long *ap_dim = this->get_aperture()->get_dim();
this->get_mebs()->generate_part_num_from_weight(ap_dim);
- /* the aperture and range compensator are erased and the ones defined in the input file are considered */
+ /* the automatic aperture and range compensator are erased and the
+ ones defined in the input file are considered */
this->update_aperture_and_range_compensator();
}
void
Rt_beam::compute_beam_data_from_prescription(Plm_image::Pointer& target)
{
- /* The spot map will be identical for passive or scanning beam lines */
+ /* The beamlet map will be identical for passive or scanning beam lines */
/* Identic to compute from manual peaks, with a preliminary optimization */
d_ptr->mebs->optimize_sobp();
this->compute_beam_data_from_manual_peaks(target);
@@ -454,24 +607,34 @@ Rt_beam::compute_beam_data_from_target(Plm_image::Pointer& target)
{
/* Compute beam aperture, range compensator
+ SOBP for passively scattered beam lines */
-
- if (this->get_beam_line_type() != "passive")
+ if (this->get_beam_line_type() == "passive")
{
- d_ptr->mebs->compute_particle_number_matrix_from_target_active(this->rpl_vol, this->get_target(), d_ptr->smearing);
+ this->compute_beam_modifiers (
+ d_ptr->target->get_vol(), this->get_mebs()->get_min_wed_map(),
+ this->get_mebs()->get_max_wed_map());
+ this->compute_beam_data_from_prescription (target);
}
else
{
- this->compute_beam_modifiers (d_ptr->target->get_vol(), this->get_mebs()->get_min_wed_map(), this->get_mebs()->get_max_wed_map());
- this->compute_beam_data_from_prescription(target);
+ std::vector <double> wepl_min;
+ std::vector <double> wepl_max;
+ this->compute_beam_modifiers_active_scanning (
+ target->get_vol(), d_ptr->smearing,
+ d_ptr->mebs->get_proximal_margin(),
+ d_ptr->mebs->get_distal_margin(),
+ wepl_min, wepl_max);
+
+ d_ptr->mebs->compute_particle_number_matrix_from_target_active (
+ this->rsp_accum_vol, wepl_min, wepl_max);
}
}
void
Rt_beam::compute_default_beam()
{
- /* Computes a default 100 MeV peak */
- this->get_mebs()->add_peak(100, 1, 1);
- this->compute_beam_data_from_manual_peaks();
+ /* Computes a default 100 MeV peak */
+ this->get_mebs()->add_peak (100, 1, 1);
+ this->compute_beam_data_from_manual_peaks ();
}
void
@@ -479,16 +642,19 @@ Rt_beam::compute_beam_modifiers (Volume *seg_vol)
{
if (d_ptr->beam_line_type == "active")
{
- this->rpl_vol->compute_beam_modifiers_active_scanning(seg_vol, d_ptr->smearing, d_ptr->mebs->get_proximal_margin(), d_ptr->mebs->get_distal_margin());
+ this->compute_beam_modifiers_active_scanning (seg_vol,
+ d_ptr->smearing, d_ptr->mebs->get_proximal_margin(),
+ d_ptr->mebs->get_distal_margin());
}
else
{
- this->rpl_vol->compute_beam_modifiers_passive_scattering(seg_vol, d_ptr->smearing, d_ptr->mebs->get_proximal_margin(), d_ptr->mebs->get_distal_margin());
+ this->compute_beam_modifiers_passive_scattering (seg_vol,
+ d_ptr->smearing, d_ptr->mebs->get_proximal_margin(),
+ d_ptr->mebs->get_distal_margin());
}
- d_ptr->mebs->set_prescription_depths(this->rpl_vol->get_min_wed(), this->rpl_vol->get_max_wed());
- this->rpl_vol->apply_beam_modifiers ();
- return;
+ d_ptr->mebs->set_prescription_depths (d_ptr->min_wed, d_ptr->max_wed);
+ this->rsp_accum_vol->apply_beam_modifiers ();
}
void
@@ -496,20 +662,368 @@ Rt_beam::compute_beam_modifiers (Volume *seg_vol, std::vector<double>& map_wed_m
{
if (d_ptr->beam_line_type == "active")
{
- this->rpl_vol->compute_beam_modifiers_active_scanning(seg_vol, d_ptr->smearing, d_ptr->mebs->get_proximal_margin(), d_ptr->mebs->get_distal_margin(), map_wed_min, map_wed_max);
+ this->compute_beam_modifiers_active_scanning (
+ seg_vol, d_ptr->smearing,
+ d_ptr->mebs->get_proximal_margin(),
+ d_ptr->mebs->get_distal_margin(), map_wed_min, map_wed_max);
}
else
{
- this->rpl_vol->compute_beam_modifiers_passive_scattering(seg_vol, d_ptr->smearing, d_ptr->mebs->get_proximal_margin(), d_ptr->mebs->get_distal_margin(), map_wed_min, map_wed_max);
+ this->compute_beam_modifiers_passive_scattering (seg_vol,
+ d_ptr->smearing, d_ptr->mebs->get_proximal_margin(),
+ d_ptr->mebs->get_distal_margin(), map_wed_min, map_wed_max);
+ }
+ d_ptr->mebs->set_prescription_depths (d_ptr->min_wed, d_ptr->max_wed);
+ this->rsp_accum_vol->apply_beam_modifiers ();
+}
+
+void
+Rt_beam::compute_beam_modifiers_active_scanning (
+ Volume *seg_vol, float smearing, float proximal_margin,
+ float distal_margin)
+{
+ std::vector<double> map_wed_min;
+ std::vector<double> map_wed_max;
+ this->compute_beam_modifiers_core (seg_vol, true, smearing, proximal_margin,
+ distal_margin, map_wed_min, map_wed_max);
+}
+
+void
+Rt_beam::compute_beam_modifiers_passive_scattering (
+ Volume *seg_vol, float smearing, float proximal_margin,
+ float distal_margin)
+{
+ std::vector<double> map_wed_min;
+ std::vector<double> map_wed_max;
+ this-> compute_beam_modifiers_core (seg_vol, false, smearing,
+ proximal_margin, distal_margin, map_wed_min, map_wed_max);
+}
+
+void
+Rt_beam::compute_beam_modifiers_active_scanning (
+ Volume *seg_vol, float smearing, float proximal_margin,
+ float distal_margin, std::vector<double>& map_wed_min,
+ std::vector<double>& map_wed_max)
+{
+ this->compute_beam_modifiers_core (seg_vol, true, smearing, proximal_margin,
+ distal_margin, map_wed_min, map_wed_max);
+}
+
+void
+Rt_beam::compute_beam_modifiers_passive_scattering (
+ Volume *seg_vol, float smearing, float proximal_margin,
+ float distal_margin, std::vector<double>& map_wed_min,
+ std::vector<double>& map_wed_max)
+{
+ this-> compute_beam_modifiers_core (seg_vol, false, smearing,
+ proximal_margin, distal_margin, map_wed_min, map_wed_max);
+}
+
+void
+Rt_beam::compute_beam_modifiers_core (
+ Volume *seg_vol,
+ bool active,
+ float smearing,
+ float proximal_margin,
+ float distal_margin,
+ std::vector<double>& map_wed_min,
+ std::vector<double>& map_wed_max)
+{
+ printf("Compute target wepl_min_max...\n");
+ this->compute_target_wepl_min_max (map_wed_min, map_wed_max);
+
+#if defined (commentout)
+ save_vector_as_image (
+ map_wed_min,
+ d_ptr->aperture->get_dim(),
+ "debug-min-a.nrrd");
+ save_vector_as_image (
+ map_wed_max,
+ d_ptr->aperture->get_dim(),
+ "debug-max-a.nrrd");
+#endif
+
+ printf ("Apply lateral smearing to the target...\n");
+ /* widen the min/max distance maps */
+ if (smearing > 0) {
+ this->apply_smearing_to_target (smearing, map_wed_min, map_wed_max);
+ }
+
+#if defined (commentout)
+ save_vector_as_image (
+ map_wed_min,
+ d_ptr->aperture->get_dim(),
+ "debug-min-b.nrrd");
+ save_vector_as_image (
+ map_wed_max,
+ d_ptr->aperture->get_dim(),
+ "debug-max-b.nrrd");
+#endif
+
+ printf ("Apply proximal and distal ...\n");
+ /* add the margins */
+ for (size_t i = 0; i < map_wed_min.size(); i++) {
+ map_wed_min[i] -= proximal_margin;
+ if (map_wed_min[i] < 0) {
+ map_wed_min[i] = 0;
+ }
+ if (map_wed_max[i] > 0) {
+ map_wed_max[i] += distal_margin;
+ }
+ }
+
+#if defined (commentout)
+ save_vector_as_image (
+ map_wed_min,
+ d_ptr->aperture->get_dim(),
+ "debug-min-c.nrrd");
+ save_vector_as_image (
+ map_wed_max,
+ d_ptr->aperture->get_dim(),
+ "debug-max-c.nrrd");
+#endif
+
+ /* Compute max wed, used by range compensator */
+ int idx = 0;
+ double max_wed = 0;
+ int i[2] = {0, 0};
+ printf("Compute max wed...\n");
+ for (i[1] = 0; i[1] < d_ptr->aperture->get_aperture_volume()->dim[1]; i[1]++) {
+ for (i[0] = 0; i[0] < d_ptr->aperture->get_aperture_volume()->dim[0]; i[0]++) {
+ idx = i[0] + i[1] * d_ptr->aperture->get_aperture_volume()->dim[0];
+ if (map_wed_max[idx] > max_wed) {
+ max_wed = map_wed_max[idx];
+ }
+ }
+ }
+
+ printf("Compute the aperture...\n");
+ /* compute the aperture */
+ /* This assumes that dim & spacing are correctly set in aperture */
+ d_ptr->aperture->allocate_aperture_images ();
+
+ Volume::Pointer aperture_vol = d_ptr->aperture->get_aperture_volume ();
+ unsigned char *aperture_img = (unsigned char*) aperture_vol->img;
+ for (int i = 0; i < aperture_vol->dim[0] * aperture_vol->dim[1]; i++) {
+ if (map_wed_min[i] > 0) {
+ aperture_img[i] = 1;
+ }
+ else {
+ aperture_img[i] = 0;
+ }
+ }
+
+ /* compute the range compensator if passive beam line with PMMA
+ range compensator */
+ Volume::Pointer range_comp_vol = d_ptr->aperture->get_range_compensator_volume ();
+ float *range_comp_img = (float*) range_comp_vol->img;
+
+ if (active == false)
+ {
+ printf("Compute range compensator...\n");
+ }
+
+ for (int i = 0; i < aperture_vol->dim[0] * aperture_vol->dim[1]; i++)
+ {
+ if (active == true)
+ {
+ range_comp_img[i] = 0;
+ }
+ else
+ {
+ range_comp_img[i] = (max_wed - map_wed_max[i]) / (PMMA_STPR * PMMA_DENSITY);
+ }
+ }
+
+ /* compute the max/min wed of the entire target + margins + range_comp*/
+ double total_min_wed = 0;
+ double total_max_wed = 0;
+ // Max should be the same as the max in the target as for this ray rgcomp is null
+ for (int i = 0; i < aperture_vol->dim[0] * aperture_vol->dim[1]; i++)
+ {
+ if (range_comp_img[i] * PMMA_STPR * PMMA_DENSITY + map_wed_max[i] > total_max_wed) { // if active beam line, range comp is null
+ total_max_wed = range_comp_img[i] * PMMA_STPR * PMMA_DENSITY + map_wed_max[i];
+ }
+ }
+ total_min_wed = total_max_wed;
+ for (int i = 0; i < aperture_vol->dim[0] * aperture_vol->dim[1]; i++)
+ {
+ if ((range_comp_img[i] * PMMA_STPR * PMMA_DENSITY + map_wed_max[i] > 0) && (range_comp_img[i] * PMMA_STPR * PMMA_DENSITY + map_wed_min[i] < total_min_wed)) {
+ total_min_wed = range_comp_img[i] * PMMA_STPR * PMMA_DENSITY + map_wed_min[i];
+ }
+ }
+
+ printf("Max wed in the target is %lg mm.\n", total_max_wed);
+ printf("Min wed in the target is %lg mm.\n", total_min_wed);
+
+ /* Save these values in private data store */
+ // GCS FIX: To be revisited
+ d_ptr->max_wed = total_max_wed;
+ d_ptr->min_wed = total_min_wed;
+}
+
+void
+Rt_beam::compute_target_wepl_min_max (
+ std::vector<double>& map_wed_min,
+ std::vector<double>& map_wed_max)
+{
+ Rpl_volume *wepl_rv = this->rsp_accum_vol;
+ Volume *wepl_vol = wepl_rv->get_vol ();
+ float *wepl_img = wepl_vol->get_raw<float> ();
+ Rpl_volume::Pointer target_rv = this->target_rv;
+ Volume *target_vol = target_rv->get_vol ();
+ float *target_img = target_vol->get_raw<float> ();
+ const plm_long *target_dim = target_vol->get_dim ();
+
+ map_wed_min.resize (target_dim[0]*target_dim[1], NLMAX(double));
+ map_wed_max.resize (target_dim[0]*target_dim[1], 0.);
+
+ int ij[2] = {0, 0};
+ int num_steps = this->target_rv->get_num_steps();
+ for (ij[1] = 0; ij[1] < target_dim[1]; ij[1]++) {
+ for (ij[0] = 0; ij[0] < target_dim[0]; ij[0]++) {
+ int map_idx = ij[0] + ij[1] * target_dim[0];
+ for (int s = 0; s < num_steps; s++) {
+ int rv_index = target_vol->index (ij[0],ij[1],s);
+ float tgt = target_img[rv_index];
+ float wepl = wepl_img[rv_index];
+ if (tgt < 0.2) {
+ continue;
+ }
+ if (map_wed_min[map_idx] > wepl) {
+ map_wed_min[map_idx] = wepl;
+ }
+ if (map_wed_max[map_idx] < wepl) {
+ map_wed_max[map_idx] = wepl;
+ }
+ }
+ }
+ }
+}
+
+void
+Rt_beam::apply_smearing_to_target (
+ float smearing,
+ std::vector <double>& map_min_distance,
+ std::vector <double>& map_max_distance)
+{
+ // GCS FIX. It appears that the reason for computing geometric
+ // distance in the previous version of the code was to make the
+ // smearing code act at the minimum target distance. This is unnecessary;
+ // it is easier/better to apply at isocenter plane.
+
+ // Convert smearing from isocenter to aperture plane
+ const Aperture::Pointer& ap = d_ptr->aperture;
+ float smearing_ap = smearing
+ * ap->get_distance() / this->get_source_distance();
+ printf ("Smearing = %f, Smearing_ap = %f\n", smearing, smearing_ap);
+
+ /* Create a structured element of the right size */
+ int strel_half_size[2];
+ int strel_size[2];
+ strel_half_size[0] = ROUND_INT (smearing_ap / ap->get_spacing()[0]);
+ strel_half_size[1] = ROUND_INT (smearing_ap / ap->get_spacing()[1]);
+
+ strel_size[0] = 1 + 2 * strel_half_size[0];
+ strel_size[1] = 1 + 2 * strel_half_size[1];
+
+ printf ("Strel size = (%d,%d), (%d,%d)\n",
+ strel_half_size[0], strel_half_size[1],
+ strel_size[0], strel_size[1]);
+
+ int *strel = new int[strel_size[0]*strel_size[1]];
+ /* (rf, cf) center of the smearing */
+ for (int r = 0; r < strel_size[1]; r++) {
+ float rf = (float) (r - strel_half_size[1]) * ap->get_spacing()[0];
+ for (int c = 0; c < strel_size[0]; c++) {
+ float cf = (float) (c - strel_half_size[0]) * ap->get_spacing()[1];
+
+ int idx = r*strel_size[0] + c;
+
+ strel[idx] = 0;
+ if ((rf*rf + cf*cf) <= smearing_ap*smearing_ap) {
+ strel[idx] = 1;
+ }
+ }
+ }
+
+ /* Debugging information */
+ for (int r = 0; r < strel_size[1]; r++) {
+ for (int c = 0; c < strel_size[0]; c++) {
+ int idx = r*strel_size[0] + c;
+ printf ("%d ", strel[idx]);
+ }
+ printf ("\n");
+ }
+
+ // GCS FIX. This is also in error. The smearing should be done
+ // in WEPL rather than in geometric distance.
+ /* Apply smear to target maps */
+ double distance_min;
+ double distance_max;
+ std::vector<double> min_distance_tmp (map_min_distance.size(), 0);
+ std::vector<double> max_distance_tmp (map_max_distance.size(), 0);
+
+ for (int ar = 0; ar < d_ptr->aperture->get_dim()[1]; ar++) {
+ for (int ac = 0; ac < d_ptr->aperture->get_dim()[0]; ac++) {
+ int aidx = ar * d_ptr->aperture->get_dim()[0] + ac;
+
+ /* Reset the limit values */
+ distance_min = DBL_MAX;
+ distance_max = 0;
+
+ for (int sr = 0; sr < strel_size[1]; sr++) {
+ int pr = ar + sr - strel_half_size[1];
+ if (pr < 0 || pr >= d_ptr->aperture->get_dim()[1]) {
+ continue;
+ }
+ for (int sc = 0; sc < strel_size[0]; sc++) {
+ int pc = ac + sc - strel_half_size[0];
+ if (pc < 0 || pc >= d_ptr->aperture->get_dim()[0]) {
+ continue;
+ }
+
+ int sidx = sr * strel_size[0] + sc;
+ if (strel[sidx] == 0) {
+ continue;
+ }
+
+ int pidx = pr * d_ptr->aperture->get_dim()[0] + pc;
+ if (map_min_distance[pidx] > 0 && map_min_distance[pidx] < distance_min) {
+ distance_min = map_min_distance[pidx];
+ }
+ if (map_max_distance[pidx] > distance_max) {
+ distance_max = map_max_distance[pidx];
+ }
+ }
+ }
+ if (distance_min == DBL_MAX)
+ {
+ min_distance_tmp[aidx] = 0;
+ }
+ else
+ {
+ min_distance_tmp[aidx] = distance_min;
+ }
+ max_distance_tmp[aidx] = distance_max;
+ }
+ }
+
+ /* update the initial distance map */
+ for (size_t i = 0; i < map_min_distance.size(); i++) {
+ map_min_distance[i] = min_distance_tmp[i];
+ map_max_distance[i] = max_distance_tmp[i];
}
- d_ptr->mebs->set_prescription_depths(this->rpl_vol->get_min_wed(), this->rpl_vol->get_max_wed());
- this->rpl_vol->apply_beam_modifiers ();
- return;
+
+ /* Clean up */
+ delete[] strel;
}
void
-Rt_beam::update_aperture_and_range_compensator()
+Rt_beam::update_aperture_and_range_compensator ()
{
+ // GCS FIX. The below logic is no longer valid
+#if defined (commentout)
/* The aperture is copied from rpl_vol
the range compensator and/or the aperture are erased if defined in the input file */
if (d_ptr->aperture_in != "")
@@ -517,7 +1031,7 @@ Rt_beam::update_aperture_and_range_compensator()
Plm_image::Pointer ap_img = Plm_image::New (d_ptr->aperture_in, PLM_IMG_TYPE_ITK_UCHAR);
this->get_aperture()->set_aperture_image(d_ptr->aperture_in.c_str());
this->get_aperture()->set_aperture_volume(ap_img->get_volume_uchar());
- if (this->rpl_vol->get_minimum_distance_target() == 0) // means that there is no target defined
+ if (this->rsp_accum_vol->get_minimum_distance_target() == 0) // means that there is no target defined
{
printf("Smearing applied to the aperture. The smearing width is defined in the aperture frame.\n");
d_ptr->aperture->apply_smearing_to_aperture(d_ptr->smearing, d_ptr->aperture->get_distance());
@@ -525,7 +1039,7 @@ Rt_beam::update_aperture_and_range_compensator()
else
{
printf("Smearing applied to the aperture. The smearing width is defined at the target minimal distance.\n");
- d_ptr->aperture->apply_smearing_to_aperture(d_ptr->smearing, this->rpl_vol->get_minimum_distance_target());
+ d_ptr->aperture->apply_smearing_to_aperture(d_ptr->smearing, this->rsp_accum_vol->get_minimum_distance_target());
}
}
/* Set range compensator */
@@ -535,7 +1049,7 @@ Rt_beam::update_aperture_and_range_compensator()
this->get_aperture()->set_range_compensator_image(d_ptr->range_compensator_in.c_str());
this->get_aperture()->set_range_compensator_volume(rgc_img->get_volume_float());
- if (this->rpl_vol->get_minimum_distance_target() == 0) // means that there is no target defined
+ if (this->rsp_accum_vol->get_minimum_distance_target() == 0) // means that there is no target defined
{
printf("Smearing applied to the range compensator. The smearing width is defined in the aperture frame.\n");
d_ptr->aperture->apply_smearing_to_range_compensator(d_ptr->smearing, d_ptr->aperture->get_distance());
@@ -543,9 +1057,28 @@ Rt_beam::update_aperture_and_range_compensator()
else
{
printf("Smearing applied to the range compensator. The smearing width is defined at the target minimal distance.\n");
- d_ptr->aperture->apply_smearing_to_range_compensator(d_ptr->smearing, this->rpl_vol->get_minimum_distance_target());
+ d_ptr->aperture->apply_smearing_to_range_compensator(d_ptr->smearing, this->rsp_accum_vol->get_minimum_distance_target());
}
}
+#endif
+}
+
+Plm_image::Pointer&
+Rt_beam::get_ct_psp ()
+{
+ return d_ptr->ct_psp;
+}
+
+const Plm_image::Pointer&
+Rt_beam::get_ct_psp () const
+{
+ return d_ptr->ct_psp;
+}
+
+void
+Rt_beam::set_ct_psp (Plm_image::Pointer& ct_psp)
+{
+ d_ptr->ct_psp = ct_psp;
}
Plm_image::Pointer&
@@ -561,11 +1094,23 @@ Rt_beam::get_target () const
}
void
-Rt_beam::set_target(Plm_image::Pointer& target)
+Rt_beam::set_target (Plm_image::Pointer& target)
{
d_ptr->target = target;
}
+void
+Rt_beam::set_rt_dose_timing (Rt_dose_timing::Pointer& rt_dose_timing)
+{
+ d_ptr->rt_dose_timing = rt_dose_timing;
+}
+
+Rt_dose_timing::Pointer&
+Rt_beam::get_rt_dose_timing ()
+{
+ return d_ptr->rt_dose_timing;
+}
+
Plm_image::Pointer&
Rt_beam::get_dose ()
{
@@ -596,6 +1141,30 @@ Rt_beam::get_aperture () const
return d_ptr->aperture;
}
+Plm_image::Pointer&
+Rt_beam::get_aperture_image ()
+{
+ return d_ptr->aperture->get_aperture_image ();
+}
+
+const Plm_image::Pointer&
+Rt_beam::get_aperture_image () const
+{
+ return d_ptr->aperture->get_aperture_image ();
+}
+
+Plm_image::Pointer&
+Rt_beam::get_range_compensator_image ()
+{
+ return d_ptr->aperture->get_range_compensator_image ();
+}
+
+const Plm_image::Pointer&
+Rt_beam::get_range_compensator_image () const
+{
+ return d_ptr->aperture->get_range_compensator_image ();
+}
+
void
Rt_beam::set_aperture_vup (const float vup[])
{
@@ -615,7 +1184,7 @@ Rt_beam::set_aperture_origin (const float ap_origin[])
}
void
-Rt_beam::set_aperture_resolution (const int ap_resolution[])
+Rt_beam::set_aperture_resolution (const plm_long ap_resolution[])
{
this->get_aperture()->set_dim (ap_resolution);
}
@@ -629,13 +1198,13 @@ Rt_beam::set_aperture_spacing (const float ap_spacing[])
void
Rt_beam::set_step_length(float step)
{
- d_ptr->step_length = step;
+ d_ptr->step_length = step;
}
float
Rt_beam::get_step_length()
{
- return d_ptr->step_length;
+ return d_ptr->step_length;
}
void
@@ -735,6 +1304,30 @@ Rt_beam::get_sigma_out()
}
void
+Rt_beam::set_beam_dump_out(std::string str)
+{
+ d_ptr->beam_dump_out = str;
+}
+
+std::string
+Rt_beam::get_beam_dump_out()
+{
+ return d_ptr->beam_dump_out;
+}
+
+void
+Rt_beam::set_dij_out (const std::string& str)
+{
+ d_ptr->dij_out = str;
+}
+
+const std::string&
+Rt_beam::get_dij_out()
+{
+ return d_ptr->dij_out;
+}
+
+void
Rt_beam::set_wed_out(std::string str)
{
d_ptr->wed_out = str;
@@ -747,16 +1340,28 @@ Rt_beam::get_wed_out()
}
void
+Rt_beam::set_proj_target_out(std::string str)
+{
+ d_ptr->proj_target_out = str;
+}
+
+std::string
+Rt_beam::get_proj_target_out()
+{
+ return d_ptr->proj_target_out;
+}
+
+void
Rt_beam::set_beam_line_type(std::string str)
{
- if (str == "active")
- {
- d_ptr->beam_line_type = str;
- }
- else
- {
- d_ptr->beam_line_type = "passive";
- }
+ if (str == "active")
+ {
+ d_ptr->beam_line_type = str;
+ }
+ else
+ {
+ d_ptr->beam_line_type = "passive";
+ }
}
std::string
@@ -851,51 +1456,53 @@ Rt_beam::load_txt (const char* fn)
}
bool
-Rt_beam::get_intersection_with_aperture(double* idx_ap, int* idx, double* rest, double* ct_xyz)
+Rt_beam::get_intersection_with_aperture (
+ double* idx_ap, plm_long* idx, double* rest, double* ct_xyz)
{
- double ray[3] = {0,0,0};
- double length_on_normal_axis = 0;
+ double ray[3] = {0,0,0};
+ double length_on_normal_axis = 0;
- vec3_copy(ray, ct_xyz);
- vec3_sub2(ray, d_ptr->source);
+ vec3_copy(ray, ct_xyz);
+ vec3_sub2(ray, d_ptr->source);
- length_on_normal_axis = -vec3_dot(ray, rpl_ct_vol_HU->get_proj_volume()->get_nrm()); // MD Fix: why is the aperture not updated at this point? and why proj vol is?
- if (length_on_normal_axis < 0)
- {
- return false;
- }
+ length_on_normal_axis = -vec3_dot(ray, hu_samp_vol->get_proj_volume()->get_nrm()); // MD Fix: why is the aperture not updated at this point? and why proj vol is?
+ if (length_on_normal_axis < 0)
+ {
+ return false;
+ }
- vec3_scale2(ray, this->get_aperture()->get_distance()/length_on_normal_axis);
+ vec3_scale2(ray, this->get_aperture()->get_distance()/length_on_normal_axis);
- vec3_add2(ray, d_ptr->source);
- vec3_sub2(ray, rpl_ct_vol_HU->get_proj_volume()->get_ul_room());
+ vec3_add2(ray, d_ptr->source);
+ vec3_sub2(ray, hu_samp_vol->get_proj_volume()->get_ul_room());
- idx_ap[0] = vec3_dot(ray, rpl_ct_vol_HU->get_proj_volume()->get_incr_c()) / (this->get_aperture()->get_spacing(0) * this->get_aperture()->get_spacing(0));
- idx_ap[1] = vec3_dot(ray, rpl_ct_vol_HU->get_proj_volume()->get_incr_r()) / (this->get_aperture()->get_spacing(1) * this->get_aperture()->get_spacing(1));
- idx[0] = (int) floor(idx_ap[0]);
- idx[1] = (int) floor(idx_ap[1]);
- rest[0] = idx_ap[0] - (double) idx[0];
- rest[1] = idx_ap[1] - (double) idx[1];
- return true;
+ idx_ap[0] = vec3_dot(ray, hu_samp_vol->get_proj_volume()->get_incr_c()) / (this->get_aperture()->get_spacing(0) * this->get_aperture()->get_spacing(0));
+ idx_ap[1] = vec3_dot(ray, hu_samp_vol->get_proj_volume()->get_incr_r()) / (this->get_aperture()->get_spacing(1) * this->get_aperture()->get_spacing(1));
+ idx[0] = (int) floor(idx_ap[0]);
+ idx[1] = (int) floor(idx_ap[1]);
+ rest[0] = idx_ap[0] - (double) idx[0];
+ rest[1] = idx_ap[1] - (double) idx[1];
+ return true;
}
bool
-Rt_beam::is_ray_in_the_aperture(int* idx, unsigned char* ap_img)
-{
- if ((float) ap_img[idx[0] + idx[1] * this->get_aperture()->get_dim(0)] == 0) {return false;}
- if (idx[0] + 1 < this->get_aperture()->get_dim(0))
- {
- if ((float) ap_img[idx[0] + 1 + idx[1] * this->get_aperture()->get_dim(0)] == 0) {return false;}
- }
- if (idx[1] + 1 < this->get_aperture()->get_dim(1))
- {
- if ((float) ap_img[idx[0] + (idx[1] + 1) * this->get_aperture()->get_dim(0)] == 0) {return false;}
- }
- if (idx[0] + 1 < this->get_aperture()->get_dim(0) && idx[1] + 1 < this->get_aperture()->get_dim(1))
- {
- if ((float) ap_img[idx[0] + 1 + (idx[1] + 1) * this->get_aperture()->get_dim(0)] == 0) {return false;}
- }
- return true;
+Rt_beam::is_ray_in_the_aperture (
+ const plm_long* idx, const unsigned char* ap_img)
+{
+ if ((float) ap_img[idx[0] + idx[1] * this->get_aperture()->get_dim(0)] == 0) {return false;}
+ if (idx[0] + 1 < this->get_aperture()->get_dim(0))
+ {
+ if ((float) ap_img[idx[0] + 1 + idx[1] * this->get_aperture()->get_dim(0)] == 0) {return false;}
+ }
+ if (idx[1] + 1 < this->get_aperture()->get_dim(1))
+ {
+ if ((float) ap_img[idx[0] + (idx[1] + 1) * this->get_aperture()->get_dim(0)] == 0) {return false;}
+ }
+ if (idx[0] + 1 < this->get_aperture()->get_dim(0) && idx[1] + 1 < this->get_aperture()->get_dim(1))
+ {
+ if ((float) ap_img[idx[0] + 1 + (idx[1] + 1) * this->get_aperture()->get_dim(0)] == 0) {return false;}
+ }
+ return true;
}
float
@@ -968,3 +1575,64 @@ void Rt_beam::set_prescription (float prescription_min, float prescription_max)
{
d_ptr->mebs->set_prescription (prescription_min, prescription_max);
}
+
+void
+Rt_beam::save_beam_output ()
+{
+ /* Save beam modifiers */
+ if (this->get_aperture_out() != "") {
+ Rpl_volume *rpl_vol = this->rsp_accum_vol;
+ Plm_image::Pointer& ap = rpl_vol->get_aperture()->get_aperture_image();
+ ap->save_image (this->get_aperture_out().c_str());
+ }
+
+ if (this->get_range_compensator_out() != ""
+ && this->get_beam_line_type() == "passive")
+ {
+ Rpl_volume *rpl_vol = this->rsp_accum_vol;
+ Plm_image::Pointer& rc = rpl_vol->get_aperture()->get_range_compensator_image();
+ rc->save_image (this->get_range_compensator_out().c_str());
+ }
+
+ /* Save projected density volume */
+ if (d_ptr->proj_img_out != "") {
+ Rpl_volume* proj_img = this->hu_samp_vol;
+ if (proj_img) {
+ proj_img->save (d_ptr->proj_img_out);
+ }
+ }
+
+ /* Save projected dose volume */
+ if (this->get_proj_dose_out() != "") {
+ Rpl_volume* dose_rv = this->dose_rv;
+ if (dose_rv) {
+ dose_rv->save (this->get_proj_dose_out());
+ }
+ }
+
+ /* Save wed volume */
+ if (this->get_wed_out() != "") {
+ Rpl_volume* rpl_vol = this->rsp_accum_vol;
+ if (rpl_vol) {
+ rpl_vol->save (this->get_wed_out());
+ }
+ }
+
+ /* Save projected target volume */
+ if (this->get_proj_target_out() != "") {
+ Rpl_volume::Pointer rpl_vol = this->target_rv;
+ if (rpl_vol) {
+ rpl_vol->save (this->get_proj_target_out());
+ }
+ }
+
+ /* Save the beamlet map */
+ if (this->get_mebs()->get_particle_number_out() != "") {
+ this->get_mebs()->export_as_txt (this->get_aperture());
+ }
+
+ /* Dump beam information */
+ if (this->get_beam_dump_out() != "") {
+ this->dump (this->get_beam_dump_out());
+ }
+}
diff --git a/src/plastimatch/dose/rt_beam.h b/src/plastimatch/dose/rt_beam.h
old mode 100644
new mode 100755
index d4ec0a5..f6d1a43
--- a/src/plastimatch/dose/rt_beam.h
+++ b/src/plastimatch/dose/rt_beam.h
@@ -12,6 +12,7 @@
#include "aperture.h"
#include "particle_type.h"
#include "rpl_volume.h"
+#include "rt_dose_timing.h"
#include "rt_mebs.h"
#include "smart_pointer.h"
@@ -60,9 +61,9 @@ public:
double get_source_distance () const;
/*! \brief Get "flavor" parameter of dose calculation algorithm */
- char get_flavor () const;
+ const std::string& get_flavor () const;
/*! \brief Set "flavor" parameter of dose calculation algorithm */
- void set_flavor (char flavor);
+ void set_flavor (const std::string& flavor);
/*! \brief Get "homo_approx" parameter of dose calculation algorithm */
char get_homo_approx () const;
@@ -92,44 +93,97 @@ public:
void set_debug (const std::string& dir);
/*! \name Outputs */
- void dump (const char* dir); /* Print debugging information */
+ void dump (const char* dir);
+ void dump (const std::string& dir);
+
+ /* Spot scanning */
+ void add_spot (
+ float xpos, float ypos, float energy, float sigma, float weight);
/* Compute beam modifiers, SOBP etc. according to the teatment strategy */
- void compute_prerequisites_beam_tools(Plm_image::Pointer& target);
+ bool prepare_for_calc (
+ Plm_image::Pointer& ct_hu,
+ Plm_image::Pointer& ct_psp,
+ Plm_image::Pointer& target);
/* Different strategies preparation */
+ void compute_beam_data_from_beamlet_map();
void compute_beam_data_from_spot_map();
void compute_beam_data_from_manual_peaks();
void compute_beam_data_from_manual_peaks(Plm_image::Pointer& target);
- void compute_beam_data_from_manual_peaks_passive_slicerRt(Plm_image::Pointer& target);
void compute_beam_data_from_prescription(Plm_image::Pointer& target);
void compute_beam_data_from_target(Plm_image::Pointer& target);
void compute_default_beam();
/* This computes the aperture and range compensator */
void compute_beam_modifiers (Volume *seg_vol);
- void compute_beam_modifiers (Volume *seg_vol, std::vector<double>& map_wed_min, std::vector<double>& map_wed_max); // returns also the wed max and min maps
-
- /* copy the aperture and range compensator from the rpl_vol if not defined in the input file */
+ void compute_beam_modifiers (Volume *seg_vol,
+ std::vector<double>& map_wed_min,
+ std::vector<double>& map_wed_max);
+ void compute_beam_modifiers_active_scanning (
+ Volume *seg_vol, float smearing, float proximal_margin,
+ float distal_margin);
+ void compute_beam_modifiers_passive_scattering (
+ Volume *seg_vol, float smearing, float proximal_margin,
+ float distal_margin);
+ void compute_beam_modifiers_active_scanning (
+ Volume *seg_vol, float smearing, float proximal_margin,
+ float distal_margin, std::vector<double>& map_wed_min,
+ std::vector<double>& map_wed_max);
+ void compute_beam_modifiers_passive_scattering (
+ Volume *seg_vol, float smearing, float proximal_margin,
+ float distal_margin, std::vector<double>& map_wed_min,
+ std::vector<double>& map_wed_max);
+ void compute_beam_modifiers_core (
+ Volume *seg_vol,
+ bool active,
+ float smearing,
+ float proximal_margin,
+ float distal_margin,
+ std::vector<double>& map_wed_min,
+ std::vector<double>& map_wed_max);
+ void apply_smearing_to_target (
+ float smearing,
+ std::vector <double>& map_min_distance,
+ std::vector <double>& map_max_distance);
+ void compute_target_wepl_min_max (
+ std::vector<double>& map_wed_min,
+ std::vector<double>& map_wed_max);
+
+ /* copy the aperture and range compensator from the rpl_vol if not
+ defined in the input file */
void update_aperture_and_range_compensator();
+ /* Set/ Get ct_psp */
+ Plm_image::Pointer& get_ct_psp ();
+ const Plm_image::Pointer& get_ct_psp () const;
+ void set_ct_psp(Plm_image::Pointer& ct_psp);
+
/* Set/ Get target */
Plm_image::Pointer& get_target ();
const Plm_image::Pointer& get_target () const;
void set_target(Plm_image::Pointer& target);
+ /* Set/ Get timer */
+ Rt_dose_timing::Pointer& get_rt_dose_timing ();
+ void set_rt_dose_timing (Rt_dose_timing::Pointer& rt_dose_timing);
+
/* Set/ Get dose_volume*/
Plm_image::Pointer& get_dose ();
const Plm_image::Pointer& get_dose () const;
void set_dose(Plm_image::Pointer& dose);
- /* Get aperture */
+ /* Get aperture and range compensator */
Aperture::Pointer& get_aperture ();
const Aperture::Pointer& get_aperture () const;
+ Plm_image::Pointer& get_aperture_image ();
+ const Plm_image::Pointer& get_aperture_image () const;
+ Plm_image::Pointer& get_range_compensator_image ();
+ const Plm_image::Pointer& get_range_compensator_image () const;
void set_aperture_vup (const float[]);
void set_aperture_distance (float);
void set_aperture_origin (const float[]);
- void set_aperture_resolution (const int[]);
+ void set_aperture_resolution (const plm_long[]);
void set_aperture_spacing (const float[]);
void set_step_length(float step);
@@ -162,14 +216,25 @@ public:
void set_sigma_out(std::string str);
std::string get_sigma_out();
+ void set_beam_dump_out(std::string str);
+ std::string get_beam_dump_out();
+
+ void set_dij_out (const std::string& str);
+ const std::string& get_dij_out();
+
void set_wed_out(std::string str);
std::string get_wed_out();
+ void set_proj_target_out(std::string str);
+ std::string get_proj_target_out();
+
void set_beam_line_type(std::string str);
std::string get_beam_line_type();
- bool get_intersection_with_aperture(double* idx_ap, int* idx, double* rest, double* ct_xyz);
- bool is_ray_in_the_aperture(int* idx, unsigned char* ap_img);
+ bool get_intersection_with_aperture (
+ double* idx_ap, plm_long* idx, double* rest, double* ct_xyz);
+ bool is_ray_in_the_aperture (
+ const plm_long* idx, const unsigned char* ap_img);
/* computes the minimal geometric distance of the target for this beam
-- used for smearing */
@@ -183,21 +248,30 @@ public:
void set_distal_margin (float distal_margin);
float get_distal_margin() const;
void set_prescription (float prescription_min, float prescription_max);
+
+ /* Save beam-specific output files to disk */
+ void save_beam_output ();
public:
- /* Volumes useful for dose calculation */
- /* raw volume */
- Rpl_volume* rpl_vol; // contains the radiologic path length along a ray
- Rpl_volume* rpl_ct_vol_HU; // contains the HU units along the ray
- Rpl_volume* sigma_vol; // contains the sigma (lateral spread of the pencil beam - used to calculate the off-axis term) along the ray
+ /*** Volumes useful for dose calculation */
+ /* contains the target */
+ Rpl_volume::Pointer target_rv;
+ /* contains the radiologic path length along a ray, according to
+ stopping power */
+ Rpl_volume* rsp_accum_vol;
+ /* contains HU, sampled at each point on the ray */
+ Rpl_volume* hu_samp_vol;
+ // contains the sigma (lateral spread of the pencil beam,
+ // used to calculate the off-axis term) along the ray
+ Rpl_volume* sigma_vol;
/* larger volumes for Hong and divergent geometry algorithms */
Rpl_volume* rpl_vol_lg;
- Rpl_volume* rpl_ct_vol_HU_lg;
+ Rpl_volume* rpl_vol_samp_lg;
Rpl_volume* sigma_vol_lg;
- Rpl_volume* rpl_dose_vol; // contains the dose vol for the divergent geometry algorithm
-
+ Rpl_volume* dose_rv;
+
private:
bool load_xio (const char* fn);
bool load_txt (const char* fn);
diff --git a/src/plastimatch/util/gabor.h b/src/plastimatch/dose/rt_beam_model.cxx
similarity index 50%
copy from src/plastimatch/util/gabor.h
copy to src/plastimatch/dose/rt_beam_model.cxx
index c4ef841..6beb514 100755
--- a/src/plastimatch/util/gabor.h
+++ b/src/plastimatch/dose/rt_beam_model.cxx
@@ -1,24 +1,21 @@
/* -----------------------------------------------------------------------
See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
----------------------------------------------------------------------- */
-#ifndef _gabor_h_
-#define _gabor_h_
+#include "plmdose_config.h"
-#include "plmutil_config.h"
-#include "plm_image.h"
-
-class Gabor_private;
-
-class Gabor
-{
-public:
- Gabor_private *d_ptr;
-public:
- Gabor ();
- ~Gabor ();
+#include "rt_beam_model.h"
+class Rt_beam_model_private {
public:
- Plm_image::Pointer get_filter ();
+ int i;
};
-#endif
+Rt_beam_model::Rt_beam_model ()
+{
+ d_ptr = new Rt_beam_model_private;
+}
+
+Rt_beam_model::~Rt_beam_model ()
+{
+ delete d_ptr;
+}
diff --git a/src/plastimatch/dose/rt_beam_model.h b/src/plastimatch/dose/rt_beam_model.h
new file mode 100755
index 0000000..0003a15
--- /dev/null
+++ b/src/plastimatch/dose/rt_beam_model.h
@@ -0,0 +1,21 @@
+/* -----------------------------------------------------------------------
+ See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
+ ----------------------------------------------------------------------- */
+#ifndef _rt_beam_model_h_
+#define _rt_beam_model_h_
+
+#include "plmdose_config.h"
+#include "smart_pointer.h"
+
+class Rt_beam_model_private;
+
+class PLMDOSE_API Rt_beam_model {
+public:
+ SMART_POINTER_SUPPORT (Rt_beam_model);
+ Rt_beam_model_private *d_ptr;
+public:
+ Rt_beam_model ();
+ ~Rt_beam_model ();
+};
+
+#endif
diff --git a/src/plastimatch/dose/rt_depth_dose.cxx b/src/plastimatch/dose/rt_depth_dose.cxx
index 8149bb2..89674f0 100644
--- a/src/plastimatch/dose/rt_depth_dose.cxx
+++ b/src/plastimatch/dose/rt_depth_dose.cxx
@@ -30,7 +30,7 @@ Rt_depth_dose::Rt_depth_dose (
{
this->d_lut = NULL;
this->e_lut = NULL;
- this->f_lut = NULL;
+ this->f_lut = NULL;
this->E0 = E0;
this->spread = spread;
@@ -46,9 +46,9 @@ Rt_depth_dose::~Rt_depth_dose ()
if (this->e_lut) {
free (this->e_lut);
}
- if (this->f_lut) {
- free (this->f_lut);
- }
+ if (this->f_lut) {
+ free (this->f_lut);
+ }
}
bool
@@ -92,11 +92,11 @@ Rt_depth_dose::load_xio (const char* fn)
this->d_lut = (float*)malloc (this->num_samples*sizeof(float));
this->e_lut = (float*)malloc (this->num_samples*sizeof(float));
- this->f_lut = (float*)malloc (this->num_samples*sizeof(float));
+ this->f_lut = (float*)malloc (this->num_samples*sizeof(float));
memset (this->d_lut, 0, this->num_samples*sizeof(float));
memset (this->e_lut, 0, this->num_samples*sizeof(float));
- memset (this->f_lut, 0, this->num_samples*sizeof(float));
+ memset (this->f_lut, 0, this->num_samples*sizeof(float));
/* load in the depths (10 samples per line) */
for (i=0, j=0; i<(this->num_samples/10)+1; i++) {
@@ -120,7 +120,7 @@ Rt_depth_dose::load_xio (const char* fn)
}
}
- /* load in the energies (10 samples per line) */
+ /* load in the energies (10 samples per line) */
for (i=0, j=0; i<(this->num_samples/10)+1; i++) {
fgets (linebuf, 128, fp);
ptoken = strtok (linebuf, ",\n\0");
@@ -143,28 +143,28 @@ Rt_depth_dose::load_txt (const char* fn)
while (fgets (linebuf, 128, fp)) {
float range, dose;
- float dose_int =0;
+ float dose_int =0;
if (2 != sscanf (linebuf, "%f %f", &range, &dose)) {
break;
}
- dose_int += dose;
+ dose_int += dose;
this->num_samples++;
this->d_lut = (float*) realloc (
- this->d_lut,
- this->num_samples * sizeof(float));
+ this->d_lut,
+ this->num_samples * sizeof(float));
this->e_lut = (float*) realloc (
- this->e_lut,
- this->num_samples * sizeof(float));
- this->f_lut = (float*) realloc (
- this->f_lut,
- this->num_samples * sizeof(float));
+ this->e_lut,
+ this->num_samples * sizeof(float));
+ this->f_lut = (float*) realloc (
+ this->f_lut,
+ this->num_samples * sizeof(float));
this->d_lut[this->num_samples-1] = range;
this->e_lut[this->num_samples-1] = dose;
- this->f_lut[this->num_samples-1] = dose_int;
+ this->f_lut[this->num_samples-1] = dose_int;
this->dend = range; /* Assume entries are sorted */
}
fclose (fp);
@@ -177,17 +177,17 @@ Rt_depth_dose::generate ()
int i;
double d;
- float max_prep = -1;
- float depth = -1;
- if (this->E0 > 190) {depth = 240;} // To accelerate the process and avoid the region where the dose decreases in the first mm (mathematic model) when E>190...
- float bragg = 0;
- while (bragg > max_prep)
- {
- max_prep = bragg;
- depth++;
- bragg = bragg_curve(this->E0, this->spread, depth);
- }
- this->dend = depth + 20; // 2 cm margins after the Bragg peak
+ float max_prep = -1;
+ float depth = -1;
+ if (this->E0 > 190) {depth = 240;} // To accelerate the process and avoid the region where the dose decreases in the first mm (mathematic model) when E>190...
+ float bragg = 0;
+ while (bragg > max_prep)
+ {
+ max_prep = bragg;
+ depth++;
+ bragg = bragg_curve(this->E0, this->spread, depth);
+ }
+ this->dend = depth + 20; // 2 cm margins after the Bragg peak
#if SPECFUN_FOUND
if (!this->E0) {
@@ -205,46 +205,46 @@ Rt_depth_dose::generate ()
this->num_samples = (int) ceilf (this->dend / this->dres)+1;
this->d_lut = (float*) malloc (this->num_samples*sizeof(float));
this->e_lut = (float*) malloc (this->num_samples*sizeof(float));
- this->f_lut = (float*) malloc (this->num_samples*sizeof(float));
+ this->f_lut = (float*) malloc (this->num_samples*sizeof(float));
memset (this->d_lut, 0, this->num_samples*sizeof(float));
memset (this->e_lut, 0, this->num_samples*sizeof(float));
- memset (this->f_lut, 0, this->num_samples*sizeof(float));
+ memset (this->f_lut, 0, this->num_samples*sizeof(float));
for (d=0, i=0; i<this->num_samples; d+=this->dres, i++) {
d_lut[i] = d;
- e_lut[i] = bragg_curve (this->E0, this->spread, d);
+ e_lut[i] = bragg_curve (this->E0, this->spread, d);
}
- float max = 0;
- if (this->num_samples > 0)
- {
- max = e_lut[0];
- for (int k = 1; k < this->num_samples; k++)
- {
- if (e_lut[k] > max)
- {
- max = e_lut[k];
- this->index_of_dose_max = k;
- }
- }
+ float max = 0;
+ if (this->num_samples > 0)
+ {
+ max = e_lut[0];
+ for (int k = 1; k < this->num_samples; k++)
+ {
+ if (e_lut[k] > max)
+ {
+ max = e_lut[k];
+ this->index_of_dose_max = k;
+ }
+ }
- /* normalization and creation of the accumulated dose curve */
- if (max > 0)
- {
- e_lut[0] /= max;
- f_lut[0] = e_lut[0] * this->dres;
- for (int k = 1; k < this->num_samples; k++)
- {
- e_lut[k] /= max;
- f_lut[k] = f_lut[k-1] + e_lut[k]*this->dres;
- }
- }
- else
- {
- printf("Error: Depth dose curve must have at least one value > 0.\n");
- return false;
- }
- }
+ /* normalization and creation of the accumulated dose curve */
+ if (max > 0)
+ {
+ e_lut[0] /= max;
+ f_lut[0] = e_lut[0] * this->dres;
+ for (int k = 1; k < this->num_samples; k++)
+ {
+ e_lut[k] /= max;
+ f_lut[k] = f_lut[k-1] + e_lut[k]*this->dres;
+ }
+ }
+ else
+ {
+ printf("Error: Depth dose curve must have at least one value > 0.\n");
+ return false;
+ }
+ }
return true;
#else
@@ -267,41 +267,40 @@ Rt_depth_dose::dump (const char* fn) const
int
Rt_depth_dose::get_index_of_dose_max()
{
- return index_of_dose_max;
+ return index_of_dose_max;
}
float
Rt_depth_dose::lookup_energy_integration (float depth, float dz) const
{
- int i = 0;
- int j = 0;
+ int i = 0;
+ int j = 0;
float energy = 0.0f;
- float dres = this->dres;
- float dmin = depth - dz/2.0;
- float dmax = depth + dz/2.0;
+ float dmin = depth - dz/2.0;
+ float dmax = depth + dz/2.0;
/* Sanity check */
- if (depth + dz/2.0 < 0) {
- return 0.0f;
- }
+ if (depth + dz/2.0 < 0) {
+ return 0.0f;
+ }
/* Find index into profile arrays */
for (i = 0; i < this->num_samples-1; i++) {
if (this->d_lut[i]> dmin) {
- i--;
+ i--;
break;
}
}
- for (j = i; j < this->num_samples; j++) {
- if (this->d_lut[j] > dmax) {
- j--;
- break;
- }
- }
+ for (j = i; j < this->num_samples; j++) {
+ if (this->d_lut[j] > dmax) {
+ j--;
+ break;
+ }
+ }
- /* Use index to lookup and interpolate energy */
+ /* Use index to lookup and interpolate energy */
if (j >= 0 && j < this->num_samples-1) {
// linear interpolation
energy = this->f_lut[j]
@@ -309,28 +308,27 @@ Rt_depth_dose::lookup_energy_integration (float depth, float dz) const
* ((this->f_lut[j+1] - this->f_lut[j])
/ (this->d_lut[j+1] - this->d_lut[j]));
}
- else
- {
- energy = this->f_lut[num_samples-1];
- }
+ else
+ {
+ energy = this->f_lut[num_samples-1];
+ }
- if (i >= 0 && i < this->num_samples-1) {
- // linear interpolation
+ if (i >= 0 && i < this->num_samples-1) {
+ // linear interpolation
energy -= this->f_lut[i]
+ (dmin - this->d_lut[i])
* ((this->f_lut[i+1] - this->f_lut[i])
/ (this->d_lut[i+1] - this->d_lut[i]));
}
- else if (i == num_samples-1)
- {
- energy -= this->f_lut[num_samples-1];
- }
- return energy;
+ else if (i == num_samples-1)
+ {
+ energy -= this->f_lut[num_samples-1];
+ }
+ return energy;
}
float
-Rt_depth_dose::lookup_energy (
- float depth)
+Rt_depth_dose::lookup_energy (float depth) const
{
int i = 0;
float energy = 0.0f;
@@ -365,4 +363,4 @@ Rt_depth_dose::lookup_energy (
energy = 0.0f;
}
return energy;
-}
\ No newline at end of file
+}
diff --git a/src/plastimatch/dose/rt_depth_dose.h b/src/plastimatch/dose/rt_depth_dose.h
old mode 100644
new mode 100755
index 78f7c50..83fc9fd
--- a/src/plastimatch/dose/rt_depth_dose.h
+++ b/src/plastimatch/dose/rt_depth_dose.h
@@ -19,28 +19,28 @@ public:
/* debug: print bragg curve to file */
void dump (const char* fn) const;
- /* Get dose maximum information */
- int get_index_of_dose_max();
+ /* Get dose maximum information */
+ int get_index_of_dose_max();
- float lookup_energy_integration(float depth, float dz) const;
- float lookup_energy (float depth);
+ float lookup_energy_integration(float depth, float dz) const;
+ float lookup_energy (float depth) const;
private:
bool load_xio (const char* fn);
bool load_txt (const char* fn);
public:
- float* d_lut; /* depth array (mm) */
- float* e_lut; /* energy array (MeV) */
- float* f_lut; /* integrated energy array (MeV) */
+ float* d_lut; /* depth array (mm) */
+ float* e_lut; /* energy array (MeV) */
+ float* f_lut; /* integrated energy array (MeV) */
float E0; /* initial ion energy (MeV) */
- double spread; /* beam energy sigma (MeV) */
- double dres; /* spatial resolution of bragg curve (mm)*/
- double dend; /* maximum w.e.d. (mm) */
- int num_samples; /* # of discrete bragg curve samples */
+ double spread; /* beam energy sigma (MeV) */
+ double dres; /* spatial resolution of bragg curve (mm)*/
+ double dend; /* maximum w.e.d. (mm) */
+ int num_samples; /* # of discrete bragg curve samples */
- int index_of_dose_max;
+ int index_of_dose_max;
};
#endif
diff --git a/src/plastimatch/dose/rt_dij.cxx b/src/plastimatch/dose/rt_dij.cxx
new file mode 100755
index 0000000..3be2dfe
--- /dev/null
+++ b/src/plastimatch/dose/rt_dij.cxx
@@ -0,0 +1,57 @@
+/* -----------------------------------------------------------------------
+ See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
+ ----------------------------------------------------------------------- */
+#include "plmdose_config.h"
+#include <list>
+
+#include "file_util.h"
+#include "string_util.h"
+#include "rpl_volume.h"
+#include "rt_dij.h"
+#include "volume_macros.h"
+
+void
+Rt_dij::set_from_dose_rv (
+ const plm_long ij[2],
+ size_t energy_index,
+ const Rpl_volume *dose_rv,
+ const Volume::Pointer& dose_vol)
+{
+ this->rows.push_back (Rt_dij_row (
+ float (ij[0]), float (ij[1]), float (energy_index)));
+ Rt_dij_row& rt_dij_row = this->rows.back ();
+
+ const Volume *dose = dose_vol.get();
+ plm_long ijk[3];
+ double xyz[3];
+ LOOP_Z (ijk, xyz, dose) {
+ LOOP_Y (ijk, xyz, dose) {
+ LOOP_X (ijk, xyz, dose) {
+ plm_long idx = dose->index (ijk);
+ float val = dose_rv->get_value (xyz);
+ if (val > 0.f) {
+ rt_dij_row.dose.push_back (Rt_dij_dose (idx, val));
+ }
+ }
+ }
+ }
+}
+
+void
+Rt_dij::dump (const std::string& dir) const
+{
+ int i = 0;
+ std::list<Rt_dij_row>::const_iterator r = rows.begin();
+ while (r != rows.end()) {
+ std::string fn = string_format ("%s/dij_%04d.txt", dir.c_str(), i++);
+ FILE *fp = plm_fopen (fn, "w");
+ fprintf (fp, "%f %f %f\n", r->xpos, r->ypos, r->energy);
+ std::list<Rt_dij_dose>::const_iterator c = r->dose.begin();
+ while (c != r->dose.end()) {
+ fprintf (fp, "%d %f\n", c->index, c->dose);
+ c++;
+ }
+ fclose (fp);
+ ++r;
+ }
+}
diff --git a/src/plastimatch/dose/rt_dij.h b/src/plastimatch/dose/rt_dij.h
new file mode 100755
index 0000000..97184fb
--- /dev/null
+++ b/src/plastimatch/dose/rt_dij.h
@@ -0,0 +1,48 @@
+/* -----------------------------------------------------------------------
+ See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
+ ----------------------------------------------------------------------- */
+#ifndef _rt_dij_h_
+#define _rt_dij_h_
+
+#include "plmdose_config.h"
+#include "smart_pointer.h"
+#include "volume.h"
+
+class Rpl_volume;
+class Rt_dij_private;
+
+class PLMDOSE_API Rt_dij_dose {
+public:
+ Rt_dij_dose (size_t index, float dose) : index(index), dose(dose)
+ {}
+public:
+ size_t index;
+ float dose;
+};
+
+class PLMDOSE_API Rt_dij_row {
+public:
+ Rt_dij_row (
+ float xpos, float ypos, float energy)
+ : xpos(xpos), ypos(ypos), energy(energy)
+ {}
+public:
+ float xpos;
+ float ypos;
+ float energy;
+ std::list<Rt_dij_dose> dose;
+};
+
+class PLMDOSE_API Rt_dij {
+public:
+ std::list<Rt_dij_row> rows;
+public:
+ void set_from_dose_rv (
+ const plm_long ij[2],
+ size_t energy_index,
+ const Rpl_volume *dose_rv,
+ const Volume::Pointer& dose_vol);
+ void dump (const std::string& dir) const;
+};
+
+#endif
diff --git a/src/plastimatch/dose/rt_dose.cxx b/src/plastimatch/dose/rt_dose.cxx
old mode 100644
new mode 100755
index 2272fd2..3225893
--- a/src/plastimatch/dose/rt_dose.cxx
+++ b/src/plastimatch/dose/rt_dose.cxx
@@ -17,91 +17,25 @@
#include "ray_data.h"
#include "ray_trace.h"
#include "rpl_volume.h"
+#include "rpl_volume_lut.h"
#include "rt_beam.h"
#include "rt_depth_dose.h"
+#include "rt_dij.h"
#include "rt_dose.h"
#include "rt_lut.h"
-#include "rt_parms.h"
-#include "rt_plan.h"
#include "rt_mebs.h"
+#include "rt_plan.h"
+#include "rt_sigma.h"
+#include "string_util.h"
#include "threading.h"
#include "volume.h"
-#define VERBOSE 1
-#define PROGRESS 1
-//#define DEBUG_VOXEL 1
-//#define DOSE_GAUSS 1
-
-#if defined (commentout)
-static bool voxel_debug = false;
-#endif
-
-/* This function is used to rotate a point about a ray in an orbit
- * perpendicular to the ray. It is assumed that the arbitrary axis of
- * rotation (ray) originates at the Cartesian origin.
- */
-static void
-rotate_about_ray (
- double *xyz_new, /* rotated point */
- double *xyz, /* point to rotate */
- double t, /* angle of rotation */
- double *ray /* axis of rotation */
-)
-{
- double u[3];
- double v[3];
- double w[3];
- double tmp[3] = {0.0, 0.0, 1.0};
- double M[12];
-
-#if defined (commentout)
- double M[16];
-#endif
-
- /* Generate coordinate system */
- vec3_copy (w, ray);
- vec3_normalize1 (w);
- vec3_cross (v, w, tmp);
- vec3_normalize1 (v);
- vec3_cross (u, v, w);
-
- /* Build the composite matrix
- * -- Axis rotation: W coincident Z
- * -- Rotates about Z by theta radians
- * -- Undoes axis rotation (Z -> W)
- */
- M[4*0 + 0] = u[0]*u[0]*cos(t) + u[0]*v[0]*sin(t) - u[0]*v[0]*sin(t) + v[0]*v[0]*cos(t) + w[0]*w[0];
- M[4*0 + 1] = u[0]*u[1]*cos(t) + u[0]*v[1]*sin(t) - u[1]*v[0]*sin(t) + v[0]*v[1]*cos(t) + w[0]*w[1];
- M[4*0 + 2] = u[0]*u[2]*cos(t) + u[0]*v[2]*sin(t) - u[2]*v[0]*sin(t) + v[0]*v[2]*cos(t) + w[0]*w[2];
- M[4*0 + 3] = 0;
-
- M[4*1 + 0] = u[1]*u[0]*cos(t) + u[1]*v[0]*sin(t) - u[0]*v[1]*sin(t) + v[1]*v[0]*cos(t) + w[1]*w[0];
- M[4*1 + 1] = u[1]*u[1]*cos(t) + u[1]*v[1]*sin(t) - u[1]*v[1]*sin(t) + v[1]*v[1]*cos(t) + w[1]*w[1];
- M[4*1 + 2] = u[1]*u[2]*cos(t) + u[1]*v[2]*sin(t) - u[2]*v[1]*sin(t) + v[1]*v[2]*cos(t) + w[1]*w[2];
- M[4*1 + 3] = 0;
-
- M[4*2 + 0] = u[2]*u[0]*cos(t) + u[2]*v[0]*sin(t) - u[0]*v[2]*sin(t) + v[2]*v[0]*cos(t) + w[2]*w[0];
- M[4*2 + 1] = u[2]*u[1]*cos(t) + u[2]*v[1]*sin(t) - u[1]*v[2]*sin(t) + v[2]*v[1]*cos(t) + w[2]*w[1];
- M[4*2 + 2] = u[2]*u[2]*cos(t) + u[2]*v[2]*sin(t) - u[2]*v[2]*sin(t) + v[2]*v[2]*cos(t) + w[2]*w[2];
- M[4*2 + 3] = 0;
-
-#if defined (commentout)
- M[4*3 + 0] = 0;
- M[4*3 + 1] = 0;
- M[4*3 + 2] = 0;
- M[4*3 + 3] = 1;
-#endif
-
- /* Apply rotation transform */
- mat43_mult_vec3(xyz_new, M, xyz);
-}
-
/* Ray Tracer */
double
energy_direct (
float rgdepth, /* voxel to dose */
- Rt_beam* beam,
- int beam_idx
+ Rt_beam* beam,
+ int beam_idx
)
{
/* The voxel was not hit directly by the beam */
@@ -110,611 +44,500 @@ energy_direct (
}
/* return the dose at this radiographic depth */
- return (double) beam->get_mebs()->get_depth_dose()[beam_idx]->lookup_energy(rgdepth);
+ return (double) beam->get_mebs()->get_depth_dose()[beam_idx]->lookup_energy(rgdepth);
}
-void compute_dose_ray_desplanques (
- Volume* dose_volume,
- Volume::Pointer ct_vol,
+void
+compute_dose_a (
+ Volume::Pointer dose_vol,
Rt_beam* beam,
- Volume::Pointer final_dose_volume,
- int beam_index
+ const Volume::Pointer ct_vol
)
{
- int ijk_idx[3] = {0,0,0};
- int ijk_travel[3] = {0,0,0};
- double xyz_travel[3] = {0.0,0.0,0.0};
-
- double spacing[3] = { (double) (dose_volume->spacing[0]), (double) (dose_volume->spacing[1]), (double) (dose_volume->spacing[2])};
- int ap_ij[2] = {1,0};
- int dim[2] = {beam->sigma_vol->get_aperture()->get_dim(0),beam->sigma_vol->get_aperture()->get_dim(1)};
- double ray_bev[3] = {0,0,0};
- double xyz_ray_center[3] = {0.0, 0.0, 0.0};
- double xyz_ray_pixel_center[3] = {0.0, 0.0, 0.0};
- double entrance_bev[3] = {0.0f, 0.0f, 0.0f}; // coordinates of intersection with the volume in the bev frame
- double xyz_room[3] = {0.0f, 0.0f, 0.0f};
- double xyz_room_tmp[3] = {0.0f, 0.0f, 0.0f};
- int ijk_ct[3] = {0,0,0};
- double entrance_length = 0;
- double distance = 0; // distance from the aperture to the POI
- double tmp[3] = {0.0f, 0.0f, 0.0f};
- double PB_density = 1/(beam->rpl_vol->get_aperture()->get_spacing(0) * beam->rpl_vol->get_aperture()->get_spacing(1));
- double ct_density = 0;
- double WER = 0;
- double STPR = 0;
- double sigma = 0;
- int sigma_x3 = 0;
- double rg_length = 0;
- double radius = 0;
- float range_comp = 0;
- float central_axis_dose = 0;
- float off_axis_factor = 0;
-
- int idx = 0; // index to travel in the dose volume
- int idx_bev = 0; // second index for reconstructing the final image
- int idx_room = 0;
- int i_min = 0;
- int i_max = 0;
- int j_min = 0;
- int j_max = 0;
- bool test = true;
- bool* in = &test;
-
- float* img = (float*) dose_volume->img;
- float* ct_img = (float*) ct_vol->img;
- float* rpl_image = (float*) beam->rpl_vol->get_vol()->img;
- float* rc_img = 0;
- unsigned char *ap_img = 0;
+ float* dose_img = (float*) dose_vol->img;
- if (beam->get_aperture()->have_range_compensator_image())
- {
- rc_img = (float*) beam->get_aperture()->get_range_compensator_volume ()->img;
- }
-
- if (beam->get_aperture()->have_aperture_image()) {
- Volume::Pointer ap_vol = beam->get_aperture()->get_aperture_volume();
- ap_img = (unsigned char*) ap_vol->img;
+ Aperture::Pointer& ap = beam->get_aperture ();
+ Volume *ap_vol = 0;
+ const unsigned char *ap_img = 0;
+ if (ap->have_aperture_image()) {
+ ap_vol = ap->get_aperture_vol ();
+ ap_img = ap_vol->get_raw<unsigned char> ();
}
- std::vector<float> num_part = beam->get_mebs()->get_num_particles();
-
- double dist = 0;
- int offset_step = 0;
-
- double vec_pdn_tmp[3] = {0,0,0};
- double vec_prt_tmp[3] = {0,0,0};
- double vec_nrm_tmp[3] = {0,0,0};
-
- vec3_copy(vec_pdn_tmp, beam->rpl_vol->get_proj_volume()->get_incr_c());
- vec3_normalize1(vec_pdn_tmp);
- vec3_copy(vec_prt_tmp, beam->rpl_vol->get_proj_volume()->get_incr_r());
- vec3_normalize1(vec_prt_tmp);
- vec3_copy(vec_nrm_tmp, beam->rpl_vol->get_proj_volume()->get_nrm());
- vec3_normalize1(vec_nrm_tmp);
-
- for (int i = 0; i < dim[0]*dim[1]; i++)
- {
- if (ap_img[i] == 0 || num_part[beam_index * dim[0] * dim[1] + i] == 0)
- {
- continue;
- }
-
- Ray_data* ray_data = &beam->sigma_vol->get_Ray_data()[i]; //MD Fix: Why ray_daya->ray for rpl_vol is wrong at this point?
-
- ap_ij[1] = i / dim[0];
- ap_ij[0] = i- ap_ij[1]*dim[0];
- ray_bev[0] = vec3_dot (ray_data->ray, vec_prt_tmp);
- ray_bev[1] = vec3_dot (ray_data->ray, vec_pdn_tmp);
- ray_bev[2] = -vec3_dot (ray_data->ray, vec_nrm_tmp); // ray_beam_eye_view is already normalized
+ /* Dose D(POI) = Dose(z_POI) but z_POI = rg_comp + depth in CT,
+ if there is a range compensator */
+ if (ap->have_range_compensator_image()) {
+ add_rcomp_length_to_rpl_volume(beam);
+ }
- /* printf("prt: %lg %lg %lg\n",vec_prt_tmp[0], vec_prt_tmp[1], vec_prt_tmp[2]);
- printf("pdn: %lg %lg %lg\n",vec_pdn_tmp[0], vec_pdn_tmp[1], vec_pdn_tmp[2]);
- printf("nrm: %lg %lg %lg\n",vec_nrm_tmp[0], vec_nrm_tmp[1], vec_nrm_tmp[2]);
- printf("ray: %lg %lg %lg\n",ray_data->ray[0], ray_data->ray[1], ray_data->ray[2]);
- printf("bev: %lg %lg %lg\n", ray_bev[0], ray_bev[1], ray_bev[2]); */
+ /* scan through patient CT Volume */
+ plm_long ct_ijk[3];
+ double ct_xyz[4];
+ plm_long idx = 0;
+ double idx_ap[2] = {0,0};
+ plm_long idx_ap_int[2] = {0,0};
+ double rest[2] = {0,0};
+ double particle_number = 0;
+ float WER = 0;
+ float rgdepth = 0;
- /* Calculation of the coordinates of the intersection of the ray with the clipping plane */
- entrance_length = vec3_dist(beam->rpl_vol->get_proj_volume()->get_src(), ray_data->cp);
+ for (ct_ijk[2] = 0; ct_ijk[2] < ct_vol->dim[2]; ct_ijk[2]++) {
+ for (ct_ijk[1] = 0; ct_ijk[1] < ct_vol->dim[1]; ct_ijk[1]++) {
+ for (ct_ijk[0] = 0; ct_ijk[0] < ct_vol->dim[0]; ct_ijk[0]++) {
+ double dose = 0.0;
- vec3_copy(entrance_bev, ray_bev);
- vec3_scale2(entrance_bev, entrance_length);
+ /* Transform vol index into space coords */
+ ct_xyz[0] = (double) (ct_vol->origin[0] + ct_ijk[0] * ct_vol->spacing[0]);
+ ct_xyz[1] = (double) (ct_vol->origin[1] + ct_ijk[1] * ct_vol->spacing[1]);
+ ct_xyz[2] = (double) (ct_vol->origin[2] + ct_ijk[2] * ct_vol->spacing[2]);
+ ct_xyz[3] = (double) 1.0;
- if (beam->get_aperture()->have_range_compensator_image())
- {
- range_comp = rc_img[i] * PMMA_DENSITY * PMMA_STPR; // Lucite material: d * rho * WER
- }
- else
- {
- range_comp = 0;
- }
- if (ray_bev[2] > DRR_BOUNDARY_TOLERANCE)
- {
- for(int k = 0; k < (int) dose_volume->dim[2] ;k++)
- {
- find_xyz_center(xyz_ray_center, ray_bev, dose_volume->origin[2],k, dose_volume->spacing[2]);
- distance = vec3_dist(xyz_ray_center, entrance_bev);
- ct_density = compute_density_from_HU(beam->rpl_ct_vol_HU->get_rgdepth(ap_ij, distance));
- STPR = compute_PrSTPR_from_HU(beam->rpl_ct_vol_HU->get_rgdepth(ap_ij, distance));
- rg_length = range_comp + beam->rpl_vol->get_rgdepth(ap_ij, distance);
- central_axis_dose = beam->get_mebs()->get_depth_dose()[beam_index]->lookup_energy_integration((float)rg_length, ct_density * dose_volume->spacing[2]) * STPR;
- sigma = beam->sigma_vol->get_rgdepth(ap_ij, distance);
- sigma_x3 = (int) ceil(3 * sigma);
-
- /* We defined the grid to be updated, the pixels that receive dose from the ray */
- /* We don't check to know if we are still in the matrix because the matrix was build to contain all pixels with a 3 sigma_max margin */
- find_ijk_pixel(ijk_idx, xyz_ray_center, dose_volume);
- i_min = ijk_idx[0] - sigma_x3;
- i_max = ijk_idx[0] + sigma_x3;
- j_min = ijk_idx[1] - sigma_x3;
- j_max = ijk_idx[1] + sigma_x3;
- for (int i2 = i_min; i2 <= i_max; i2++)
+ if (beam->get_intersection_with_aperture(idx_ap, idx_ap_int, rest, ct_xyz) == false)
{
- for (int j2 = j_min; j2 <= j_max; j2++)
- {
- if (i2 < 0 || j2 < 0 || i2 >= dose_volume->dim[0] || j2 >= dose_volume->dim[1])
- {
- continue;
- }
- idx = i2 + (dose_volume->dim[0] * (j2 + dose_volume->dim[1] * k));
- ijk_travel[0] = i2;
- ijk_travel[1] = j2;
- ijk_travel[2] = k;
-
- /* calculation of the corresponding position in the room and its HU number*/
- vec3_copy(xyz_room_tmp, vec_prt_tmp);
- vec3_scale2(xyz_room_tmp, dose_volume->origin[0] + (float) i2 * dose_volume->spacing[0]);
- vec3_copy(xyz_room, (xyz_room_tmp));
-
- vec3_copy(xyz_room_tmp, vec_pdn_tmp);
- vec3_scale2(xyz_room_tmp, dose_volume->origin[1] + (float) j2 * dose_volume->spacing[1]);
- vec3_add2(xyz_room, (xyz_room_tmp));
-
- vec3_copy(xyz_room_tmp, vec_nrm_tmp);
- vec3_scale2(xyz_room_tmp, (double) (-dose_volume->origin[2] - (float) k * dose_volume->spacing[2]));
- vec3_add2(xyz_room, (xyz_room_tmp));
- vec3_add2(xyz_room, beam->rpl_vol->get_proj_volume()->get_src());
-
- find_ijk_pixel(ijk_ct, xyz_room, ct_vol);
- idx_room = ijk_ct[0] + (ct_vol->dim[0] * (ijk_ct[1] + ct_vol->dim[1] * ijk_ct[2]));
- if (ijk_ct[0] < 0 || ijk_ct[1] < 0 || ijk_ct[2] < 0 || ijk_ct[0] >= ct_vol->dim[0] || ijk_ct[1] >= ct_vol->dim[1] || ijk_ct[2] >= ct_vol->dim[2])
- {
- WER = PROTON_WER_AIR;
- }
- else
- {
- WER = compute_PrWER_from_HU(ct_img[idx_room]);
- }
- find_xyz_from_ijk(xyz_travel,dose_volume,ijk_travel);
- radius = vec3_dist(xyz_travel,xyz_ray_center);
- if (sigma == 0)
- {
- off_axis_factor = 1;
- }
- else if (radius > sqrt(0.25 * spacing[0] * spacing [0] + 0.25 * spacing[1] * spacing[1]) + 3 * sigma )
- {
- off_axis_factor = 0;
- }
- else
- {
- off_axis_factor = double_gaussian_interpolation(xyz_ray_center, xyz_travel,sigma, spacing);
- }
- /* SOBP is weighted by the weight of the pristine peak */
- img[idx] += num_part[beam_index * dim[0] * dim[1] + i] * central_axis_dose
- * WER // dose = dose_w * WER
- * off_axis_factor ;
- }
+ continue;
}
- }
- }
- }
- float* final_dose_img = (float*) final_dose_volume->img;
- int ijk[3] = {0,0,0};
- float ijk_bev[3] = {0,0,0};
- int ijk_bev_trunk[3];
- float xyz_bev[3] = {0.0,0.0,0.0};
- plm_long mijk_f[3];
- plm_long mijk_r[3];
- plm_long idx_lower_left = 0;
- float li_frac1[3];
- float li_frac2[3];
- const plm_long *dim_ct = ct_vol->dim;
- plm_long dose_bev_dim[3] = { dose_volume->dim[0], dose_volume->dim[1], dose_volume->dim[2]};
-
- for (ijk[0] = 0; ijk[0] < dim_ct[0]; ijk[0]++)
- {
- for (ijk[1] = 0; ijk[1] < dim_ct[1]; ijk[1]++)
- {
- for (ijk[2] = 0; ijk[2] < dim_ct[2]; ijk[2]++)
- {
- idx = ijk[0] + dim_ct[0] *(ijk[1] + ijk[2] * dim_ct[1]);
- if ( ct_img[idx] >= -1000) // in air we have no dose, we let the voxel number at 0!
- {
- final_dose_volume->get_xyz_from_ijk(xyz_room, ijk);
+ /* Check that the ray cross the aperture */
+ if (idx_ap[0] < 0 || idx_ap[0] > (double) beam->hu_samp_vol->get_proj_volume()->get_image_dim(0)-1
+ || idx_ap[1] < 0 || idx_ap[1] > (double) beam->hu_samp_vol->get_proj_volume()->get_image_dim(1)-1)
+ {
+ continue;
+ }
- /* xyz contains the coordinates of the pixel in the room coordinates */
- /* we now calculate the coordinates of this pixel in the dose_volume coordinates */
+ /* Check that the ray cross the active part of the aperture */
+ if (ap_img && beam->is_ray_in_the_aperture(idx_ap_int, ap_img) == false)
+ {
+ continue;
+ }
- vec3_sub3(tmp, beam->rpl_vol->get_proj_volume()->get_src(), xyz_room);
- xyz_bev[0] = (float) -vec3_dot(tmp, vec_prt_tmp);
- xyz_bev[1] = (float) -vec3_dot(tmp, vec_pdn_tmp);
- xyz_bev[2] = (float) vec3_dot(tmp, vec_nrm_tmp);
- dose_volume->get_ijk_from_xyz(ijk_bev, xyz_bev, in);
+ dose = 0;
+ rgdepth = beam->rsp_accum_vol->get_value (ct_xyz);
+ WER = compute_PrWER_from_HU (beam->hu_samp_vol->get_value(ct_xyz));
- if (*in == true)
+ const Rt_mebs::Pointer& mebs = beam->get_mebs();
+ for (size_t dd_idx = 0; dd_idx < mebs->get_depth_dose().size(); dd_idx++)
+ {
+ particle_number = mebs->get_particle_number_xyz (idx_ap_int, rest, dd_idx, beam->get_aperture()->get_dim());
+ if (particle_number != 0 && rgdepth >=0 && rgdepth < mebs->get_depth_dose()[dd_idx]->dend)
{
- dose_volume->get_ijk_from_xyz(ijk_bev_trunk, xyz_bev, in);
- idx_bev = ijk_bev_trunk[0] + ijk_bev[1]*dose_volume->dim[0] + ijk_bev[2] * dose_volume->dim[0] * dose_volume->dim[1];
- li_clamp_3d(ijk_bev, mijk_f, mijk_r, li_frac1, li_frac2, dose_volume);
- idx_lower_left = mijk_f[0] + dose_bev_dim[0] *(mijk_f[1] + mijk_f[2] * dose_bev_dim[1]);
- final_dose_img[idx] += li_value(li_frac1[0], li_frac2[0], li_frac1[1], li_frac2[1], li_frac1[2], li_frac2[2], idx_lower_left, img, dose_volume);
+ dose += particle_number * WER * energy_direct (rgdepth, beam, dd_idx);
}
}
- }
- }
+
+ /* Insert the dose into the dose volume */
+ idx = volume_index (dose_vol->dim, ct_ijk);
+ dose_img[idx] = dose;
+ }
+ }
}
- return;
}
-void
-compute_dose_ray_sharp (
- const Volume::Pointer ct_vol,
- Rt_beam* beam,
- Rpl_volume* rpl_dose_volume,
- int beam_index,
- const int* margins
+void
+compute_dose_b (
+ Rt_beam* beam,
+ size_t energy_index,
+ const Volume::Pointer ct_vol
)
{
- int ap_ij_lg[2] = {0,0};
- int ap_ij_sm[2] = {0,0};
- int dim_lg[3] = {0,0,0};
- int dim_sm[3] = {0,0,0};
- const plm_long *dim_ct = ct_vol->dim;
- int idx2d_sm = 0;
- int idx2d_lg = 0;
- int idx3d_sm = 0;
- int idx3d_lg = 0;
- int idx3d_travel = 0;
- int idx_ct = 0;
- int ijk_ct[3] = {0,0,0};
- int i_min = 0;
- int i_max = 0;
- int j_min = 0;
- int j_max = 0;
-
- float ct_density = 0;
- float WER = 0;
- float DENSITY = 0;
- float STPR = 0;
- double sigma = 0;
- double sigma_x3 = 0;
- double rg_length = 0;
- float central_axis_dose = 0;
- float off_axis_factor = 0;
- double minimal_lateral = 0;
- double lateral_step[2] = {0,0};
- double central_ray_xyz[3] = {0.0, 0.0, 0.0};
- double travel_ray_xyz[3] = {0.0, 0.0, 0.0};
- double xyz_room[4] = {0.0, 0.0, 0.0, 1.0};
- double PB_density = 1 / ( beam->rpl_vol->get_aperture()->get_spacing(0) * beam->rpl_vol->get_aperture()->get_spacing(1));
-
- dim_lg[0] = rpl_dose_volume->get_vol()->dim[0];
- dim_lg[1] = rpl_dose_volume->get_vol()->dim[1];
- dim_lg[2] = rpl_dose_volume->get_vol()->dim[2];
- dim_sm[0] = beam->rpl_vol->get_vol()->dim[0];
- dim_sm[1] = beam->rpl_vol->get_vol()->dim[1];
- dim_sm[2] = beam->rpl_vol->get_vol()->dim[2];
-
- float* rpl_img = (float*) beam->rpl_vol->get_vol()->img;
- float* sigma_img = (float*) beam->sigma_vol->get_vol()->img;
- float* rpl_dose_img = (float*) rpl_dose_volume->get_vol()->img;
- float* ct_rpl_img = (float*) beam->rpl_ct_vol_HU->get_vol()->img;
- float* ct_img = (float*) ct_vol->img;
- float* rc_img = 0;
- unsigned char *ap_img = 0;
- float range_comp = 0;
-
- Ray_data* ray_data;
- Ray_data* ray_data_tmp;
-
- if (beam->get_aperture()->have_aperture_image()) {
- Volume::Pointer ap_vol = beam->get_aperture()->get_aperture_volume();
- ap_img = (unsigned char*) ap_vol->img;
- }
-
- if (beam->get_aperture()->have_range_compensator_image())
- {
- rc_img = (float*) beam->get_aperture()->get_range_compensator_volume ()->img;
+ Rpl_volume *wepl_rv = beam->rsp_accum_vol;
+ Volume *wepl_vol = wepl_rv->get_vol();
+ float *wepl_img = wepl_vol->get_raw<float> ();
+
+ Rpl_volume *dose_rv = beam->dose_rv;
+ Volume *dose_rv_vol = dose_rv->get_vol();
+ float *dose_rv_img = dose_rv_vol->get_raw<float> ();
+
+ Rt_mebs::Pointer mebs = beam->get_mebs();
+ const Rt_depth_dose *depth_dose = mebs->get_depth_dose()[energy_index];
+ std::vector<float>& num_part = mebs->get_num_particles();
+
+ /* scan through rpl volume */
+ Aperture::Pointer& ap = beam->get_aperture ();
+ Volume *ap_vol = 0;
+ const unsigned char *ap_img = 0;
+ if (ap->have_aperture_image()) {
+ ap_vol = ap->get_aperture_vol ();
+ ap_img = ap_vol->get_raw<unsigned char> ();
}
- double dist = 0;
- double radius = 0;
-
- /* Creation of the rpl_volume containing the coordinates xyz (beam eye view) and the CT density vol*/
- std::vector<double> xyz_init (4,0);
- std::vector< std::vector<double> > xyz_coor_vol (dim_lg[0]*dim_lg[1]*dim_lg[2], xyz_init);
- calculate_rpl_coordinates_xyz (&xyz_coor_vol, rpl_dose_volume);
-
- for (int m = 0; m < dim_lg[0] * dim_lg[1] * dim_lg[2]; m++)
- {
- rpl_dose_img[m] = 0;
+ const plm_long *dim = wepl_rv->get_image_dim();
+ int num_steps = wepl_rv->get_num_steps();
+ plm_long ij[2] = {0,0};
+ for (ij[1] = 0; ij[1] < dim[1]; ij[1]++) {
+ for (ij[0] = 0; ij[0] < dim[0]; ij[0]++) {
+ if (ap_img && ap_img[ap_vol->index(ij[0],ij[1],0)] == 0) {
+ continue;
+ }
+ size_t np_index = energy_index * dim[0] * dim[1]
+ + ij[1] * dim[0] + ij[0];
+ float np = num_part[np_index];
+ if (np == 0.f) {
+ continue;
+ }
+ for (int s = 0; s < num_steps; s++) {
+ int dose_index = ap_vol->index(ij[0],ij[1],s);
+ float wepl = wepl_img[dose_index];
+ dose_rv_img[dose_index] += np * depth_dose->lookup_energy(wepl);
+ }
+ }
}
+}
- /* calculation of the lateral steps in which the dose is searched constant with depth */
- std::vector <double> lateral_minimal_step (dim_lg[2],0);
- std::vector <double> lateral_step_x (dim_lg[2],0);
- std::vector <double> lateral_step_y (dim_lg[2],0);
-
- minimal_lateral = beam->get_aperture()->get_spacing(0);
- if (minimal_lateral < beam->get_aperture()->get_spacing(1))
- {
- minimal_lateral = beam->get_aperture()->get_spacing(1);
- }
+void
+compute_dose_ray_trace_dij_a (
+ Rt_beam* beam,
+ size_t energy_index,
+ const Volume::Pointer ct_vol,
+ Volume::Pointer& dose_vol
+)
+{
+ float* dose_img = (float*) dose_vol->img;
- for (int k = 0; k < dim_sm[2]; k++)
+ /* Dose D(POI) = Dose(z_POI) but z_POI = rg_comp + depth in CT,
+ if there is a range compensator */
+ if (beam->get_aperture()->have_range_compensator_image())
{
- lateral_minimal_step[k] = (beam->rpl_vol->get_front_clipping_plane() + beam->rpl_vol->get_aperture()->get_distance() + (double) k) * minimal_lateral / beam->rpl_vol->get_aperture()->get_distance();
- lateral_step_x[k] = (beam->rpl_vol->get_front_clipping_plane() + beam->rpl_vol->get_aperture()->get_distance() + (double) k) * beam->get_aperture()->get_spacing(0) / beam->rpl_vol->get_aperture()->get_distance();
- lateral_step_y[k] = (beam->rpl_vol->get_front_clipping_plane() + beam->rpl_vol->get_aperture()->get_distance() + (double) k) *beam->get_aperture()->get_spacing(1) / beam->rpl_vol->get_aperture()->get_distance();
+ add_rcomp_length_to_rpl_volume(beam);
}
- std::vector<float> num_part = beam->get_mebs()->get_num_particles();
+ /* scan through patient CT Volume */
+ plm_long ct_ijk[3];
+ double ct_xyz[4];
+ plm_long idx = 0;
+ double idx_ap[2] = {0,0};
+ plm_long idx_ap_int[2] = {0,0};
+ double rest[2] = {0,0};
+ unsigned char* ap_img = (unsigned char*) beam->get_aperture()->get_aperture_volume()->img;
+ double particle_number = 0;
+ float WER = 0;
+ float rgdepth = 0;
- /* calculation of the dose in the rpl_volume */
- for (ap_ij_lg[0] = margins[0]; ap_ij_lg[0] < rpl_dose_volume->get_vol()->dim[0]-margins[0]; ap_ij_lg[0]++){
- for (ap_ij_lg[1] = margins[1]; ap_ij_lg[1] < rpl_dose_volume->get_vol()->dim[1]-margins[1]; ap_ij_lg[1]++){
+ for (ct_ijk[2] = 0; ct_ijk[2] < ct_vol->dim[2]; ct_ijk[2]++) {
+ for (ct_ijk[1] = 0; ct_ijk[1] < ct_vol->dim[1]; ct_ijk[1]++) {
+ for (ct_ijk[0] = 0; ct_ijk[0] < ct_vol->dim[0]; ct_ijk[0]++) {
+ double dose = 0.0;
- ap_ij_sm[0] = ap_ij_lg[0] - margins[0];
- ap_ij_sm[1] = ap_ij_lg[1] - margins[1];
- idx2d_lg = ap_ij_lg[1] * dim_lg[0] + ap_ij_lg[0];
- idx2d_sm = ap_ij_sm[1] * dim_sm[0] + ap_ij_sm[0];
+ /* Transform vol index into space coords */
+ ct_xyz[0] = (double) (ct_vol->origin[0] + ct_ijk[0] * ct_vol->spacing[0]);
+ ct_xyz[1] = (double) (ct_vol->origin[1] + ct_ijk[1] * ct_vol->spacing[1]);
+ ct_xyz[2] = (double) (ct_vol->origin[2] + ct_ijk[2] * ct_vol->spacing[2]);
+ ct_xyz[3] = (double) 1.0;
- if (beam->get_aperture()->have_aperture_image())
- {
- if((float) ap_img[idx2d_sm] == 0 || num_part[beam_index * beam->get_aperture()->get_dim(0) * beam->get_aperture()->get_dim(1) + idx2d_sm] == 0)
+ if (beam->get_intersection_with_aperture (idx_ap, idx_ap_int, rest, ct_xyz) == false)
{
continue;
}
- }
- if (beam->get_aperture()->have_range_compensator_image())
- {
- range_comp = rc_img[idx2d_sm] * PMMA_DENSITY * PMMA_STPR; // Lucite Material: d * rho * WER, MD Fix
- }
- else
- {
- range_comp = 0;
- }
-
- ray_data = &rpl_dose_volume->get_Ray_data()[idx2d_lg];
- for (int k = 0; k < dim_sm[2]; k++)
- {
- idx3d_lg = idx2d_lg + k * dim_lg[0]*dim_lg[1];
- idx3d_sm = idx2d_sm + k * dim_sm[0]*dim_sm[1];
-
- central_ray_xyz[0] = xyz_coor_vol[idx3d_lg][0];
- central_ray_xyz[1] = xyz_coor_vol[idx3d_lg][1];
- central_ray_xyz[2] = xyz_coor_vol[idx3d_lg][2];
-
- lateral_step[0] = lateral_step_x[k];
- lateral_step[1] = lateral_step_x[k];
- ct_density = compute_density_from_HU(ct_rpl_img[idx3d_sm]);
- STPR = compute_PrSTPR_from_HU(ct_rpl_img[idx3d_sm]);
-
- rg_length = range_comp + rpl_img[idx3d_sm];
- central_axis_dose = num_part[beam_index * beam->get_aperture()->get_dim(0)* beam->get_aperture()->get_dim(1) + idx2d_sm] * beam->get_mebs()->get_depth_dose()[beam_index]->lookup_energy_integration(rg_length, ct_density * beam->rpl_vol->get_vol()->spacing[2]) * STPR;
+ /* Check that the ray cross the aperture */
+ if (idx_ap[0] < 0 || idx_ap[0] > (double) beam->hu_samp_vol->get_proj_volume()->get_image_dim(0)-1
+ || idx_ap[1] < 0 || idx_ap[1] > (double) beam->hu_samp_vol->get_proj_volume()->get_image_dim(1)-1)
+ {
+ continue;
+ }
- if (central_axis_dose <= 0) // no dose on the axis, no dose scattered
+ /* Check that the ray cross the active part of the aperture */
+ if (beam->get_aperture()->have_aperture_image() && beam->is_ray_in_the_aperture (idx_ap_int, ap_img) == false)
{
continue;
}
- sigma = (double) sigma_img[idx3d_sm];
- sigma_x3 = sigma * 3;
+ dose = 0;
+ rgdepth = beam->rsp_accum_vol->get_value (ct_xyz);
+ WER = compute_PrWER_from_HU (beam->hu_samp_vol->get_value(ct_xyz));
- /* finding the rpl_volume pixels that are contained in the the 3 sigma range */
- i_min = ap_ij_lg[0] - (int) ceil(sigma_x3 / lateral_minimal_step[k]);
- if (i_min < 0 ) {i_min = 0;}
- i_max = ap_ij_lg[0] + (int) ceil(sigma_x3 / lateral_minimal_step[k]);
- if (i_max > dim_lg[0]-1 ) {i_max = dim_lg[0]-1;}
- j_min = ap_ij_lg[1] - (int) ceil(sigma_x3 / lateral_minimal_step[k]);
- if (j_min < 0 ) {j_min = 0;}
- j_max = ap_ij_lg[1] + (int) ceil(sigma_x3 / lateral_minimal_step[k]);
- if (j_max > dim_lg[1]-1 ) {j_max = dim_lg[1]-1;}
+ const Rt_mebs::Pointer& mebs = beam->get_mebs();
+ for (size_t dd_idx = 0; dd_idx < mebs->get_depth_dose().size(); dd_idx++)
+ {
+ particle_number = mebs->get_particle_number_xyz (idx_ap_int, rest, dd_idx, beam->get_aperture()->get_dim());
+ if (particle_number != 0 && rgdepth >=0 && rgdepth < mebs->get_depth_dose()[dd_idx]->dend)
+ {
+ dose += particle_number * WER * energy_direct (rgdepth, beam, dd_idx);
+ }
+ }
- for (int i1 = i_min; i1 <= i_max; i1++) {
- for (int j1 = j_min; j1 <= j_max; j1++) {
- idx3d_travel = k * dim_lg[0]*dim_lg[1] + j1 * dim_lg[0] + i1;
+ /* Insert the dose into the dose volume */
+ idx = volume_index (dose_vol->dim, ct_ijk);
+ dose_img[idx] = dose;
+ }
+ }
+ }
+}
- ray_data_tmp = &rpl_dose_volume->get_Ray_data()[j1 * dim_lg[0] + i1];
+void
+compute_dose_ray_trace_dij_b (
+ Rt_beam* beam,
+ const Volume::Pointer ct_vol,
+ Volume::Pointer& dose_vol
+)
+{
+ Rpl_volume *wepl_rv = beam->rsp_accum_vol;
+ Volume *wepl_vol = wepl_rv->get_vol();
+ float *wepl_img = wepl_vol->get_raw<float> ();
+
+ Rpl_volume *dose_rv = beam->dose_rv;
+ Volume *dose_rv_vol = dose_rv->get_vol();
+ float *dose_rv_img = dose_rv_vol->get_raw<float> ();
+
+ Rt_mebs::Pointer mebs = beam->get_mebs();
+ const std::vector<Rt_depth_dose*> depth_dose = mebs->get_depth_dose();
+ std::vector<float>& num_part = mebs->get_num_particles();
+
+ /* Create the beamlet dij matrix */
+ Rt_dij rt_dij;
+
+ /* Create geometry map from volume to rpl_volume */
+ Rpl_volume_lut rpl_volume_lut (dose_rv, dose_vol.get());
+ rpl_volume_lut.build_lut ();
+
+ /* scan through rpl volume */
+ Aperture::Pointer& ap = beam->get_aperture ();
+ Volume *ap_vol = 0;
+ const unsigned char *ap_img = 0;
+ if (ap->have_aperture_image()) {
+ ap_vol = ap->get_aperture_vol ();
+ ap_img = ap_vol->get_raw<unsigned char> ();
+ }
+ const plm_long *dim = wepl_rv->get_image_dim();
+ int num_steps = wepl_rv->get_num_steps();
+ plm_long ij[2] = {0,0};
+ for (ij[1] = 0; ij[1] < dim[1]; ij[1]++) {
+ for (ij[0] = 0; ij[0] < dim[0]; ij[0]++) {
+ if (ap_img && ap_img[ap_vol->index(ij[0],ij[1],0)] == 0) {
+ continue;
+ }
+ for (size_t energy_index = 0;
+ energy_index < depth_dose.size();
+ energy_index++)
+ {
+ // Get beamlet weight
+ size_t np_index = energy_index * dim[0] * dim[1]
+ + ij[1] * dim[0] + ij[0];
+ float np = num_part[np_index];
+ if (np == 0.f) {
+ continue;
+ }
- travel_ray_xyz[0] = xyz_coor_vol[idx3d_travel][0];
- travel_ray_xyz[1] = xyz_coor_vol[idx3d_travel][1];
- travel_ray_xyz[2] = xyz_coor_vol[idx3d_travel][2];
- radius = vec3_dist(travel_ray_xyz, central_ray_xyz);
+ // Fill in dose
+ const Rt_depth_dose *dd = depth_dose[energy_index];
+ for (int s = 0; s < num_steps; s++) {
+ int dose_index = ap_vol->index(ij[0],ij[1],s);
+ float wepl = wepl_img[dose_index];
+ dose_rv_img[dose_index] = np * dd->lookup_energy(wepl);
+ }
- if (sigma == 0)
- {
- off_axis_factor = 1;
- }
- else
- {
- off_axis_factor = double_gaussian_interpolation(central_ray_xyz, travel_ray_xyz, sigma, lateral_step);
- }
+ // Create beamlet dij
+ rt_dij.set_from_dose_rv (
+ ij, energy_index, dose_rv, ct_vol);
- vec3_copy(xyz_room, ray_data_tmp->ray);
- vec3_scale2(xyz_room, rpl_dose_volume->get_aperture()->get_distance() + rpl_dose_volume->get_front_clipping_plane() + (double) k);
- vec3_add2(xyz_room, rpl_dose_volume->get_proj_volume()->get_src());
- find_ijk_pixel(ijk_ct, xyz_room, ct_vol);
- if (ijk_ct[0] < 0 || ijk_ct[0] >= dim_ct[0] || ijk_ct[1] < 0 || ijk_ct[1] >= dim_ct[1] || ijk_ct[2] < 0 || ijk_ct[2] >= dim_ct[2] )
- {
- WER = PROTON_WER_AIR;
- DENSITY = AIR_DENSITY;
- }
- else
- {
- WER = compute_PrWER_from_HU(ct_img[ijk_ct[2] * dim_ct[0]*dim_ct[1] + ijk_ct[1] * dim_ct[0] + ijk_ct[0] ] );
- DENSITY = compute_density_from_HU(ct_img[ijk_ct[2] * dim_ct[0]*dim_ct[1] + ijk_ct[1] * dim_ct[0] + ijk_ct[0] ] );
- }
- if (DENSITY > 0.8)
- {
- rpl_dose_img[idx3d_travel] += central_axis_dose
- * WER / DENSITY
- * off_axis_factor ;
- }
- } //for j1
- } //for i1
- } // for k
- } // ap_ij[1]
- } // ap_ij[0]
+ // Zero out again
+ for (int s = 0; s < num_steps; s++) {
+ int dose_index = ap_vol->index(ij[0],ij[1],s);
+ dose_rv_img[dose_index] = 0.f;
+ }
+ }
+ }
+ }
+
+ // Write beamlet dij
+ if (beam->get_dij_out() != "") {
+ rt_dij.dump (beam->get_dij_out());
+ }
}
-void compute_dose_ray_shackleford (
- Volume::Pointer dose_vol,
- Rt_plan* plan,
+void
+compute_dose_d (
Rt_beam* beam,
- int beam_index,
- std::vector<double>* area,
- std::vector<double>* xy_grid,
- int radius_sample,
- int theta_sample)
+ size_t energy_index,
+ const Volume::Pointer ct_vol
+)
{
- int ijk[3] = {0,0,0};
- double xyz[4] = {0,0,0,1};
- double xyz_travel[4] = {0,0,0,1};
- double tmp_xy[4] = {0,0,0,1};
- double tmp_cst = 0;
- int idx = 0;
- const plm_long *dose_dim = dose_vol->dim;
- double vec_ud[4] = {0,0,0,1};
- double vec_rl[4] = {0,0,0,1};
- float* ct_img = (float*) plan->get_patient_volume()->img;
- float* dose_img = (float*) dose_vol->img;
- double sigma_travel = 0;
- double sigma_3 = 0;
- double rg_length = 0;
- float ct_density = 0;
- float STPR = 0;
- float HU = 0;
- double central_sector_dose = 0;
- double radius = 0;
- double theta = 0;
- double dr = 0;
-
- double idx_ap[2] = {0,0};
- int idx_ap_int[2] = {0,0};
- double rest[2] = {0,0};
- float particle_number = 0;
+ beam->get_rt_dose_timing()->timer_dose_calc.resume ();
+ Rpl_volume *wepl_rv = beam->rsp_accum_vol;
+ Volume *wepl_vol = wepl_rv->get_vol();
+ float *wepl_img = wepl_vol->get_raw<float> ();
+
+ Rpl_volume *dose_rv = beam->dose_rv;
+ Volume *dose_rv_vol = dose_rv->get_vol();
+ float *dose_rv_img = dose_rv_vol->get_raw<float> ();
+
+ Rt_mebs::Pointer mebs = beam->get_mebs();
+ const Rt_depth_dose *depth_dose = mebs->get_depth_dose()[energy_index];
+ std::vector<float>& num_part = mebs->get_num_particles();
+ beam->get_rt_dose_timing()->timer_dose_calc.stop ();
+
+ // Compute sigma for this energy
+ beam->get_rt_dose_timing()->timer_sigma.resume ();
+ int margins[2] = {0,0};
+ float sigma_max = 0;
+ compute_sigmas (beam, depth_dose->E0, &sigma_max, "small", margins);
+ beam->get_rt_dose_timing()->timer_sigma.stop ();
+
+ beam->get_rt_dose_timing()->timer_dose_calc.resume ();
+ Rpl_volume *sigma_rv = beam->sigma_vol;
+ Volume *sigma_vol = sigma_rv->get_vol();
+ float *sigma_img = sigma_vol->get_raw<float> ();
+ const plm_long *sigma_dim = sigma_vol->get_dim();
+
+ // Get the variable magnification at each step
+ std::vector <double> lateral_spacing_0 (sigma_dim[2],0);
+ std::vector <double> lateral_spacing_1 (sigma_dim[2],0);
+ double sid = sigma_rv->get_aperture()->get_distance();
+ const double *ap_spacing = sigma_rv->get_aperture()->get_spacing();
+ float clipping_dist = sigma_rv->get_front_clipping_plane();
+ float step_length = sigma_rv->get_step_length ();
+ for (int k = 0; k < sigma_dim[2]; k++) {
+ float mag = (sid + clipping_dist + k * step_length) / sid;
+ lateral_spacing_0[k] = ap_spacing[0] * mag;
+ lateral_spacing_1[k] = ap_spacing[1] * mag;
+ }
- unsigned char *ap_img = 0;
- if (beam->get_aperture()->have_aperture_image()) {
- Volume::Pointer ap_vol = beam->get_aperture()->get_aperture_volume();
- ap_img = (unsigned char*) ap_vol->img;
+ // Compute lateral search distance (2.5 max sigma) for each depth
+ // (Only needed if pulling dose, not needed if pushing)
+ // GCS FIX: This need only be computed once per beam, not once per energy
+ std::vector <int> lateral_step_0 (sigma_dim[2],0);
+ std::vector <int> lateral_step_1 (sigma_dim[2],0);
+ for (int k = 0; k < sigma_dim[2]; k++) {
+ float sigma_max = 0.f;
+ for (int i = 0; i < sigma_dim[0]*sigma_dim[1]; i++) {
+ plm_long idx = k*sigma_dim[0]*sigma_dim[1] + i;
+ if (sigma_img[idx] > sigma_max) {
+ sigma_max = sigma_img[idx];
+ }
+ }
+ lateral_step_0[k] = ceil (2.5 * sigma_max / lateral_spacing_0[k]);
+ lateral_step_1[k] = ceil (2.5 * sigma_max / lateral_spacing_1[k]);
}
- /* Dose D(POI) = Dose(z_POI) but z_POI = rg_comp + depth in CT, if there is a range compensator */
- if (beam->rpl_vol->get_aperture()->have_range_compensator_image())
- {
- add_rcomp_length_to_rpl_volume(beam);
+ // Create central axis dose volume
+ Rpl_volume *cax_dose_rv = new Rpl_volume;
+ if (!cax_dose_rv) return;
+ cax_dose_rv->clone_geometry (wepl_rv);
+ cax_dose_rv->set_ray_trace_start (RAY_TRACE_START_AT_CLIPPING_PLANE);
+ cax_dose_rv->set_aperture (beam->get_aperture());
+ cax_dose_rv->set_ct (wepl_rv->get_ct());
+ cax_dose_rv->set_ct_limit (wepl_rv->get_ct_limit());
+ cax_dose_rv->compute_ray_data();
+ cax_dose_rv->set_front_clipping_plane (wepl_rv->get_front_clipping_plane());
+ cax_dose_rv->set_back_clipping_plane (wepl_rv->get_back_clipping_plane());
+ cax_dose_rv->compute_rpl_void ();
+ Volume *cax_dose_vol = cax_dose_rv->get_vol ();
+ float *cax_dose_img = cax_dose_vol->get_raw<float> ();
+
+ // Compute central axis dose
+ Aperture::Pointer& ap = beam->get_aperture ();
+ Volume *ap_vol = 0;
+ const unsigned char *ap_img = 0;
+ if (ap->have_aperture_image()) {
+ ap_vol = ap->get_aperture_vol ();
+ ap_img = ap_vol->get_raw<unsigned char> ();
+ }
+ const plm_long *dim = wepl_rv->get_image_dim();
+ plm_long num_steps = wepl_rv->get_num_steps();
+ plm_long ij[2] = {0,0};
+ for (ij[1] = 0; ij[1] < dim[1]; ij[1]++) {
+ for (ij[0] = 0; ij[0] < dim[0]; ij[0]++) {
+ if (ap_img && ap_img[ap_vol->index(ij[0],ij[1],0)] == 0) {
+ continue;
+ }
+ size_t np_index = energy_index * dim[0] * dim[1]
+ + ij[1] * dim[0] + ij[0];
+ float np = num_part[np_index];
+ if (np == 0.f) {
+ continue;
+ }
+ for (int s = 0; s < num_steps; s++) {
+ int dose_index = ap_vol->index(ij[0],ij[1],s);
+ float wepl = wepl_img[dose_index];
+ cax_dose_img[dose_index] += np * depth_dose->lookup_energy(wepl);
+ }
+ }
}
- vec3_copy(vec_ud, beam->rpl_vol->get_proj_volume()->get_incr_c());
- vec3_normalize1(vec_ud);
- vec3_copy(vec_rl, beam->rpl_vol->get_proj_volume()->get_incr_r());
- vec3_normalize1(vec_rl);
-
- for (ijk[0] = 0; ijk[0] < dose_dim[0]; ijk[0]++){
- printf("%d ", ijk[0]);
- for (ijk[1] = 0; ijk[1] < dose_dim[1]; ijk[1]++){
- for (ijk[2] = 0; ijk[2] < dose_dim[2]; ijk[2]++){
- idx = ijk[0] + dose_dim[0] * (ijk[1] + dose_dim[1] * ijk[2]);
-
- /* calculation of the pixel coordinates in the room coordinates */
- xyz[0] = (double) dose_vol->origin[0] + ijk[0] * dose_vol->spacing[0];
- xyz[1] = (double) dose_vol->origin[1] + ijk[1] * dose_vol->spacing[1];
- xyz[2] = (double) dose_vol->origin[2] + ijk[2] * dose_vol->spacing[2]; // xyz[3] always = 1.0
- sigma_3 = 3 * beam->sigma_vol_lg->get_rgdepth(xyz);
-
- for (int i = 0; i < radius_sample; i++)
- {
- for (int j =0; j < theta_sample; j++)
- {
- vec3_copy(xyz_travel, xyz);
-
- /* calculation of the center of the sector */
- vec3_copy(tmp_xy, vec_ud);
- tmp_cst = (double) (*xy_grid)[2*(i*theta_sample+j)] * sigma_3; // xy_grid is normalized to a circle of radius sigma x 3 = 1
- vec3_scale2(tmp_xy, tmp_cst);
- vec3_add2(xyz_travel,tmp_xy);
-
- vec3_copy(tmp_xy, vec_rl);
- tmp_cst = (double) (*xy_grid)[2*(i*theta_sample+j)+1] * sigma_3;
- vec3_scale2(tmp_xy, tmp_cst);
- vec3_add2(xyz_travel,tmp_xy);
-
- rg_length = beam->rpl_vol->get_rgdepth(xyz_travel);
- HU = beam->rpl_ct_vol_HU_lg->get_rgdepth(xyz_travel);
- if (beam->get_intersection_with_aperture(idx_ap, idx_ap_int, rest, xyz_travel) == false)
- {
- continue;
- }
- /* Check that the ray cross the aperture */
- if (idx_ap[0] < 0 || idx_ap[0] > (double) beam->rpl_ct_vol_HU->get_proj_volume()->get_image_dim(0)-1
- || idx_ap[1] < 0 || idx_ap[1] > (double) beam->rpl_ct_vol_HU->get_proj_volume()->get_image_dim(1)-1)
- {
- continue;
- }
- /* Check that the ray cross the active part of the aperture */
- if (beam->get_aperture()->have_aperture_image() && beam->is_ray_in_the_aperture(idx_ap_int, ap_img) == false)
- {
- continue;
- }
- /* Check that the spot map is positive for this ray */
- particle_number = beam->get_mebs()->get_particle_number_xyz(idx_ap_int, rest, beam_index, beam->get_aperture()->get_dim());
- if (particle_number <= 0)
- {
- continue;
- }
- ct_density = compute_density_from_HU(HU);
- STPR = compute_PrSTPR_from_HU(HU);
-
- if (rg_length <= 0)
+ /* Save sigma volume */
+ if (beam->get_sigma_out() != "") {
+ std::string fn;
+ fn = string_format ("%s/cax-%02d",
+ beam->get_sigma_out().c_str(), energy_index);
+ cax_dose_rv->save (fn);
+ fn = string_format ("%s/sig-%02d",
+ beam->get_sigma_out().c_str(), energy_index);
+ sigma_rv->save (fn);
+ }
+
+ // Smear dose by specified sigma
+ for (int s = 0; s < num_steps; s++) {
+ double pixel_spacing[2] = {
+ lateral_spacing_0[s],
+ lateral_spacing_1[s]
+ };
+ for (ij[1] = 0; ij[1] < dim[1]; ij[1]++) {
+ for (ij[0] = 0; ij[0] < dim[0]; ij[0]++) {
+ plm_long idx = s*sigma_dim[0]*sigma_dim[1] + ij[1]*dim[0] + ij[0];
+ float cax_dose = cax_dose_img[idx];
+ if (cax_dose == 0.f) {
+ continue;
+ }
+ double sigma = (double) sigma_img[idx];
+ double sigma_x3 = sigma * 2.5;
+
+ // finding the rpl_volume pixels that are contained in the
+ // the 3 sigma range
+ plm_long ij_min[2], ij_max[2];
+ ij_min[0] = ij[0] - ceil (sigma_x3 / lateral_spacing_0[s]);
+ if (ij_min[0] < 0) ij_min[0] = 0;
+ ij_min[1] = ij[1] - ceil (sigma_x3 / lateral_spacing_1[s]);
+ if (ij_min[1] < 0) ij_min[1] = 0;
+ ij_max[0] = ij[0] + ceil (sigma_x3 / lateral_spacing_0[s]);
+ if (ij_max[0] > dim[0]-1) ij_max[0] = dim[0]-1;
+ ij_max[1] = ij[1] + ceil (sigma_x3 / lateral_spacing_1[s]);
+ if (ij_max[1] > dim[1]-1) ij_max[1] = dim[1]-1;
+
+ float tot_off_axis = 0.f;
+ plm_long ij1[2];
+ for (ij1[1] = ij_min[1]; ij1[1] <= ij_max[1]; ij1[1]++) {
+ for (ij1[0] = ij_min[0]; ij1[0] <= ij_max[0]; ij1[0]++) {
+ plm_long idxs = s*sigma_dim[0]*sigma_dim[1]
+ + ij1[1]*dim[0] + ij1[0];
+ double gaussian_center[2] = { 0., 0. };
+ double pixel_center[2] = {
+ (double) ij1[0]-ij[0],
+ (double) ij1[1]-ij[1]
+ };
+ double off_axis_factor;
+ if (sigma == 0)
{
- continue;
+ off_axis_factor = 1;
}
else
{
-
- /* the dose from that sector is summed */
- sigma_travel = beam->sigma_vol->get_rgdepth(xyz_travel);
- radius = vec3_dist(xyz, xyz_travel);
-
- if (sigma_travel < radius / 3)
- {
- continue;
- }
- else
- {
- central_sector_dose = particle_number * beam->get_mebs()->get_depth_dose()[beam_index]->lookup_energy_integration((float) rg_length, ct_density * beam->rpl_vol->get_vol()->spacing[2])* STPR * (1/(sigma_travel*sqrt(2*M_PI)));
- dr = sigma_3 / (2* radius_sample);
- dose_img[idx] +=
- central_sector_dose
- * compute_PrWER_from_HU(HU)
- * get_off_axis(radius, dr, sigma_3/3)
- * beam->get_mebs()->get_weight()[beam_index];
- }
+ off_axis_factor = double_gaussian_interpolation (
+ gaussian_center, pixel_center,
+ sigma, pixel_spacing);
}
+
+ dose_rv_img[idxs] += cax_dose * off_axis_factor;
+#if defined (commentout)
+ // GCS FIX: The below correction would give the
+ // option for dose to tissue
+ / ct_density / STPR;
+#endif
+ tot_off_axis += off_axis_factor;
}
}
}
}
}
+
+ // Free temporary memory
+ delete cax_dose_rv;
+ beam->get_rt_dose_timing()->timer_dose_calc.stop ();
}
-void add_rcomp_length_to_rpl_volume (Rt_beam* beam)
+void
+add_rcomp_length_to_rpl_volume (Rt_beam* beam)
{
- const plm_long *dim = beam->rpl_vol->get_vol()->dim;
- float* rpl_img = (float*) beam->rpl_vol->get_vol()->img;
- float* rc_img = (float*) beam->rpl_vol->get_aperture()->get_range_compensator_volume()->img;
+ const plm_long *dim = beam->rsp_accum_vol->get_vol()->dim;
+ float* rpl_img = (float*) beam->rsp_accum_vol->get_vol()->img;
+ float* rc_img = (float*) beam->rsp_accum_vol->get_aperture()->get_range_compensator_volume()->img;
int idx = 0;
for(int i = 0; i < dim[0] * dim[1]; i++)
diff --git a/src/plastimatch/dose/rt_dose.h b/src/plastimatch/dose/rt_dose.h
old mode 100644
new mode 100755
index ceac39a..9fdb6a6
--- a/src/plastimatch/dose/rt_dose.h
+++ b/src/plastimatch/dose/rt_dose.h
@@ -17,6 +17,32 @@ energy_direct (
int beam_idx
);
+void compute_dose_a (
+ Volume::Pointer dose_vol,
+ Rt_beam* beam,
+ const Volume::Pointer ct_vol
+);
+void compute_dose_b (
+ Rt_beam* beam,
+ size_t energy_index,
+ const Volume::Pointer ct_vol
+);
+void compute_dose_ray_trace_dij_a (
+ Rt_beam* beam,
+ size_t energy_index,
+ const Volume::Pointer ct_vol,
+ Volume::Pointer& dose_vol
+);
+void compute_dose_ray_trace_dij_b (
+ Rt_beam* beam,
+ const Volume::Pointer ct_vol,
+ Volume::Pointer& dose_vol
+);
+void compute_dose_d (
+ Rt_beam* beam,
+ size_t energy_index,
+ const Volume::Pointer ct_vol
+);
void compute_dose_ray_desplanques (
Volume* dose_volume,
Volume::Pointer ct_vol,
@@ -28,7 +54,7 @@ void compute_dose_ray_sharp (
const Volume::Pointer ct_vol,
Rt_beam* beam,
Rpl_volume* rpl_dose_volume,
- int beam_index,
+ int beam_index,
const int* margins
);
void compute_dose_ray_shackleford (
diff --git a/src/plastimatch/dose/rt_dose_timing.h b/src/plastimatch/dose/rt_dose_timing.h
new file mode 100644
index 0000000..d6f3333
--- /dev/null
+++ b/src/plastimatch/dose/rt_dose_timing.h
@@ -0,0 +1,39 @@
+/* -----------------------------------------------------------------------
+ See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
+ ----------------------------------------------------------------------- */
+#ifndef _rt_dose_timing_h_
+#define _rt_dose_timing_h_
+
+#include "plmdose_config.h"
+#include "logfile.h"
+#include "plm_timer.h"
+#include "smart_pointer.h"
+
+class Rt_dose_timing
+{
+public:
+ SMART_POINTER_SUPPORT (Rt_dose_timing);
+public:
+ Plm_timer timer_sigma;
+ Plm_timer timer_dose_calc;
+ Plm_timer timer_reformat;
+ Plm_timer timer_io;
+ Plm_timer timer_misc;
+public:
+ void reset () {
+ timer_sigma.reset ();
+ timer_dose_calc.reset ();
+ timer_reformat.reset ();
+ timer_io.reset ();
+ timer_misc.reset ();
+ }
+ void report () {
+ lprintf ("Sigma: %f seconds\n", timer_sigma.report());
+ lprintf ("Calc: %f seconds\n", timer_dose_calc.report());
+ lprintf ("IO: %f seconds\n", timer_io.report());
+ lprintf ("Reformat: %f seconds\n", timer_reformat.report());
+ lprintf ("Misc: %f seconds\n", timer_misc.report());
+ };
+};
+
+#endif
diff --git a/src/plastimatch/dose/rt_lut.cxx b/src/plastimatch/dose/rt_lut.cxx
index c9676a7..4ad6183 100644
--- a/src/plastimatch/dose/rt_lut.cxx
+++ b/src/plastimatch/dose/rt_lut.cxx
@@ -76,36 +76,36 @@ double get_proton_stop (double energy)
double get_theta0_Highland(double range)
{
- /* lucite sigma0 (in rads) computing- From the figure A2 of the Hong's paper (be careful, in this paper the fit shows sigma0^2)*/
- if (range > 150)
- {
- return 0.05464 + 5.8348E-6 * range -5.21006E-9 * range * range;
- }
- else
- {
- return 0.05394 + 1.80222E-5 * range -5.5430E-8 * range * range;
- }
+ /* lucite sigma0 (in rads) computing- From the figure A2 of the Hong's paper (be careful, in this paper the fit shows sigma0^2)*/
+ if (range > 150)
+ {
+ return 0.05464 + 5.8348E-6 * range -5.21006E-9 * range * range;
+ }
+ else
+ {
+ return 0.05394 + 1.80222E-5 * range -5.5430E-8 * range * range;
+ }
}
double get_theta0_MC(float energy)
{
- return 4.742E-6 * energy * energy -1.918E-3 * energy + 1.158;
+ return 4.742E-6 * energy * energy -1.918E-3 * energy + 1.158;
}
double get_theta_rel_Highland(double rc_over_range)
{
- return rc_over_range * ( 1.6047 -2.7295 * rc_over_range + 2.1578 * rc_over_range * rc_over_range);
+ return rc_over_range * ( 1.6047 -2.7295 * rc_over_range + 2.1578 * rc_over_range * rc_over_range);
}
double get_theta_rel_MC(double rc_over_range)
{
- return 3.833E-2 * pow(rc_over_range, 0.657) + 2.118E-2 * pow(rc_over_range, 6.528);
+ return 3.833E-2 * pow(rc_over_range, 0.657) + 2.118E-2 * pow(rc_over_range, 6.528);
}
double get_scat_or_Highland(double rc_over_range)
{
- /* calculation of rc_eff - see Hong's paper graph A3 - linear interpolation of the curve */
- if (rc_over_range >= 0 && rc_over_range < 0.5)
+ /* calculation of rc_eff - see Hong's paper graph A3 - linear interpolation of the curve */
+ if (rc_over_range >= 0 && rc_over_range < 0.5)
{
return 1 - (0.49 + 0.060 / 0.5 * rc_over_range);
}
@@ -135,12 +135,14 @@ double get_scat_or_Highland(double rc_over_range)
}
}
-double get_scat_or_MC(double rc_over_range)
+double
+get_scat_or_MC (double rc_over_range)
{
- return 0.023 * rc_over_range + 0.332;
+ return 0.023 * rc_over_range + 0.332;
}
-double compute_X0_from_HU(double CT_HU)
+double
+compute_X0_from_HU (double CT_HU)
{
if (CT_HU <= -1000)
{
diff --git a/src/plastimatch/dose/rt_mebs.cxx b/src/plastimatch/dose/rt_mebs.cxx
old mode 100644
new mode 100755
index 24ee137..3dcb0c8
--- a/src/plastimatch/dose/rt_mebs.cxx
+++ b/src/plastimatch/dose/rt_mebs.cxx
@@ -41,9 +41,10 @@ public:
float proximal_margin;
float distal_margin;
- double spread; /* spread for optimized SOBP, may be changed to a vector for each energy */
+ /* spread for optimized SOBP, may be changed to a vector for each energy */
+ double spread;
- /* p & alpha are parameters that bind depth and energy
+ /* p & alpha are parameters that bind depth and energy
according to ICRU */
Particle_type particle_type;
double alpha;
@@ -75,6 +76,9 @@ public:
std::string particle_number_in;
std::string particle_number_out;
+ /* debug */
+ bool debug;
+
public:
Rt_mebs_private ()
{
@@ -88,9 +92,9 @@ public:
this->energy_res = 1.f;
this->energy_number = 1;
- this->target_min_depth = 0.f; /* lower depth of target */
- this->target_max_depth = 0.f; /* higher depth of target */
- this->depth_res = 0.01f; /* depth resolution */
+ this->target_min_depth = 0.f; /* lower depth of target */
+ this->target_max_depth = 0.f; /* higher depth of target */
+ this->depth_res = 0.01f; /* depth resolution */
this->depth_end = 20.f;
this->prescription_depth_min = 0.f;
@@ -113,6 +117,8 @@ public:
this->particle_number_in ="";
this->particle_number_out ="";
+
+ this->debug = false;
}
Rt_mebs_private (Particle_type part)
{
@@ -126,9 +132,9 @@ public:
this->energy_res = 1.f;
this->energy_number = 1;
- this->target_min_depth = 0.f; /* lower depth of target */
- this->target_max_depth = 0.f; /* higher depth of target */
- this->depth_res = 0.01f; /* depth resolution */
+ this->target_min_depth = 0.f;
+ this->target_max_depth = 0.f;
+ this->depth_res = 0.01f;
this->depth_end = 20.f;
this->prescription_depth_min = 0.f;
@@ -162,9 +168,9 @@ public:
this->energy_res = rsp->energy_res;
this->energy_number = rsp->energy_number;
- this->target_min_depth = rsp->target_min_depth; /* lower depth of target */
- this->target_max_depth = rsp->target_max_depth; /* higher depth of target */
- this->depth_res = rsp->depth_res; /* depth resolution */
+ this->target_min_depth = rsp->target_min_depth;
+ this->target_max_depth = rsp->target_max_depth;
+ this->depth_res = rsp->depth_res;
this->depth_end = rsp->depth_end;
this->prescription_depth_min = rsp->prescription_depth_min;
@@ -189,19 +195,19 @@ public:
this->particle_number_out = rsp->particle_number_out;
/* copy the associated depth dose and update the dept dose curve */
- for (int i = 0; i < rsp->depth_dose.size(); i++)
+ for (size_t i = 0; i < rsp->depth_dose.size(); i++)
{
this->depth_dose.push_back(rsp->depth_dose[i]);
}
- for (int i = 0; i < rsp->depth_dose_weight.size(); i++)
+ for (size_t i = 0; i < rsp->depth_dose_weight.size(); i++)
{
this->depth_dose_weight.push_back(rsp->depth_dose_weight[i]);
}
- for (int i = 0; i < rsp->energies.size(); i++)
+ for (size_t i = 0; i < rsp->energies.size(); i++)
{
this->energies.push_back(rsp->energies[i]);
}
- for (int i = 0; i < rsp->num_particles.size(); i++)
+ for (size_t i = 0; i < rsp->num_particles.size(); i++)
{
this->num_particles.push_back(rsp->num_particles[i]);
}
@@ -220,7 +226,10 @@ public:
this->e_lut[i] = rsp->e_lut[i];
this->f_lut[i] = rsp->f_lut[i];
}
+
+ this->debug = false;
}
+public:
~Rt_mebs_private ()
{
if (d_lut) delete[] d_lut;
@@ -308,7 +317,6 @@ public:
num_particles.pop_back();
}
}
-
};
Rt_mebs::Rt_mebs ()
@@ -356,8 +364,7 @@ Rt_mebs::add_depth_dose (Rt_depth_dose* depth_dose)
d_ptr->energies.push_back(depth_dose->E0);
/* update the mebs depth dose length if this one is longer */
- if (depth_dose->num_samples > d_ptr->num_samples)
- {
+ if (depth_dose->num_samples > d_ptr->num_samples) {
d_ptr->num_samples = depth_dose->num_samples;
}
}
@@ -389,8 +396,7 @@ Rt_mebs::add_peak (double E0, double spread, double weight)
d_ptr->energies.push_back(E0);
/* update the mebs depth dose length if this one is longer */
- if (depth_dose->num_samples > d_ptr->num_samples)
- {
+ if (depth_dose->num_samples > d_ptr->num_samples) {
d_ptr->num_samples = depth_dose->num_samples;
}
}
@@ -469,7 +475,7 @@ Rt_mebs::lookup_energy (
* ((d_ptr->e_lut[i+1] - d_ptr->e_lut[i])
/ (d_ptr->d_lut[i+1] - d_ptr->d_lut[i]));
} else {
- // we wen't past the end of the lookup table
+ // we went past the end of the lookup table
energy = 0.0f;
}
return energy;
@@ -494,7 +500,7 @@ Rt_mebs::generate ()
d_ptr->f_lut[i] = 0;
}
- for (int it = 0; it < d_ptr->depth_dose.size(); it++)
+ for (size_t it = 0; it < d_ptr->depth_dose.size(); it++)
{
const Rt_depth_dose *ppp = d_ptr->depth_dose[it];
/* Check that this peak has the same resolution */
@@ -529,7 +535,7 @@ Rt_mebs::dump (const char* dir)
/* Dump SOBP */
std::string sobp_fn = string_format ("%s/bragg_curve.txt", dir);
- FILE* fp = fopen (sobp_fn.c_str(), "w");
+ FILE* fp = plm_fopen (sobp_fn.c_str(), "w");
for (int i=0; i < d_ptr->num_samples; i++) {
fprintf (fp, "%3.2f %3.2f\n", d_ptr->d_lut[i], d_ptr->e_lut[i]);
}
@@ -553,12 +559,12 @@ Rt_mebs::printparameters()
printf ("\nParticle type : %s, alpha: %lg, p: %lg\n", particle_type_string (d_ptr->particle_type), d_ptr->alpha, d_ptr->p);
printf("Number of depth_dose : %d\n",d_ptr->energy_number = d_ptr->depth_dose.size());
printf("Energy set (in MeV):\n");
- for (int i = 0; i < d_ptr->energies.size(); i++)
+ for (size_t i = 0; i < d_ptr->energies.size(); i++)
{
printf("%lg ", d_ptr->energies[i]);
}
printf("\nweights set:\n");
- for (int i = 0; i < d_ptr->depth_dose_weight.size(); i++)
+ for (size_t i = 0; i < d_ptr->depth_dose_weight.size(); i++)
{
printf("%lg ", d_ptr->depth_dose_weight[i]);
}
@@ -659,8 +665,8 @@ Rt_mebs::set_target_depths(float new_depth_min, float new_depth_max)
void
Rt_mebs::set_target_depths(float new_z_min, float new_z_max, float new_step)
{
- d_ptr->depth_res = new_step;
- this->set_target_depths(new_z_min, new_z_max);
+ d_ptr->depth_res = new_step;
+ this->set_target_depths(new_z_min, new_z_max);
}
void
@@ -1040,10 +1046,10 @@ Rt_mebs::get_num_particles()
}
void
-Rt_mebs::set_prescription(float prescription_min, float prescription_max)
+Rt_mebs::set_prescription (float prescription_min, float prescription_max)
{
d_ptr->have_prescription = true;
- this->set_prescription_depths(prescription_min, prescription_max);
+ this->set_prescription_depths (prescription_min, prescription_max);
}
void
@@ -1218,7 +1224,7 @@ Rt_mebs::optimize_sobp ()
std::vector<float> energy_tmp;
this->optimizer (&weight_tmp, &energy_tmp);
- for (int i = 0; i < energy_tmp.size(); i++)
+ for (size_t i = 0; i < energy_tmp.size(); i++)
{
add_peak(energy_tmp[i], d_ptr->spread, weight_tmp[i]);
}
@@ -1235,7 +1241,10 @@ Rt_mebs::optimizer (std::vector<float>* weight_tmp, std::vector<float>* energy_t
}
void
-Rt_mebs::initialize_energy_weight_and_depth_dose_vectors(std::vector<float>* weight_tmp, std::vector<float>* energy_tmp, std::vector<Rt_depth_dose*>* depth_dose_tmp)
+Rt_mebs::initialize_energy_weight_and_depth_dose_vectors (
+ std::vector<float>* weight_tmp,
+ std::vector<float>* energy_tmp,
+ std::vector<Rt_depth_dose*>* depth_dose_tmp)
{
/* initialize the energies in the table */
printf("\n %d Mono-energetic BP used:\n", d_ptr->energy_number);
@@ -1249,7 +1258,7 @@ Rt_mebs::initialize_energy_weight_and_depth_dose_vectors(std::vector<float>* wei
d_ptr->energy_number--;
(*energy_tmp).pop_back();
weight_tmp->pop_back();
- printf("sobp: peak with energy < 0, Energy resolution error. Last peak deleted.\n");
+ printf ("sobp: peak with energy < 0, Energy resolution error. Last peak deleted.\n");
}
}
printf("\n");
@@ -1268,14 +1277,12 @@ Rt_mebs::initialize_energy_weight_and_depth_dose_vectors(std::vector<float>* wei
}
void
-Rt_mebs::generate_part_num_from_weight(int* ap_dim)
+Rt_mebs::generate_part_num_from_weight (const plm_long* ap_dim)
{
//int idx = 0;
- for (int i = 0; i < d_ptr->energy_number; i++)
- {
- for (int j = 0; j < ap_dim[0] * ap_dim[1]; j++)
- {
- d_ptr->num_particles.push_back(d_ptr->depth_dose_weight[i]);
+ for (int i = 0; i < d_ptr->energy_number; i++) {
+ for (int j = 0; j < ap_dim[0] * ap_dim[1]; j++) {
+ d_ptr->num_particles.push_back (d_ptr->depth_dose_weight[i]);
}
}
}
@@ -1290,27 +1297,53 @@ Rt_mebs::scale_num_part(double A, int* ap_dim)
}
double
-Rt_mebs::get_particle_number_xyz(int* idx, double* rest, int idx_beam, const int* ap_dim)
+Rt_mebs::get_particle_number_xyz (
+ plm_long* idx, double* rest, int dd_idx, const plm_long* ap_dim)
{
- /* The boundaries possible errors like idx = dim are already excluded by the test on the aperture
- Practically, idx = dim -1 is not possible */
+ /* The boundaries possible errors like idx = dim are already excluded by
+ the test on the aperture. Practically, idx = dim -1 is not possible */
double A = 0;
double B = 0;
- int spot = 0;
- spot = ap_dim[0] * ap_dim[1] * idx_beam + ap_dim[0] * idx[1] + idx[0];
- A = d_ptr->num_particles[spot] + rest[0] * ( d_ptr->num_particles[spot+1] - d_ptr->num_particles[spot]);
- spot = ap_dim[0] * ap_dim[1] * idx_beam + ap_dim[0] * (idx[1] +1 ) + idx[0];
- B = d_ptr->num_particles[spot] + rest[0] * ( d_ptr->num_particles[spot+1] - d_ptr->num_particles[spot]);
+ int beamlet = 0;
+ beamlet = ap_dim[0] * ap_dim[1] * dd_idx + ap_dim[0] * idx[1] + idx[0];
+ A = d_ptr->num_particles[beamlet] + rest[0] * ( d_ptr->num_particles[beamlet+1] - d_ptr->num_particles[beamlet]);
+#if defined (commentout)
+ if (d_ptr->debug) {
+ printf (" Mebs::GPNXYZ %f %f",
+ d_ptr->num_particles[beamlet],
+ d_ptr->num_particles[beamlet+1]
+ );
+ }
+#endif
+ beamlet = ap_dim[0] * ap_dim[1] * dd_idx + ap_dim[0] * (idx[1]+1) + idx[0];
+ B = d_ptr->num_particles[beamlet] + rest[0] * ( d_ptr->num_particles[beamlet+1] - d_ptr->num_particles[beamlet]);
+#if defined (commentout)
+ if (d_ptr->debug) {
+ printf (" %f %f\n",
+ d_ptr->num_particles[beamlet],
+ d_ptr->num_particles[beamlet+1]
+ );
+ }
+#endif
return A + rest[1] * (B-A);
}
void
-Rt_mebs::extract_particle_number_map_from_txt(Aperture::Pointer& ap)
+Rt_mebs::set_from_spot_map (const Rt_spot_map::Pointer& rsm)
+{
+ this->clear_depth_dose ();
+
+ const std::list<Rt_spot>& spot_list = rsm->get_spot_list();
+
+}
+
+void
+Rt_mebs::load_beamlet_map (Aperture::Pointer& ap)
{
/* Confirm file can be read */
if (!file_exists (d_ptr->particle_number_in)) {
printf ("Error reading config file: %s\n", d_ptr->particle_number_in.c_str());
- printf("Particle number map set to 0 for each dose spot \n");
+ printf("Particle number map set to 0 for each dose beamlet \n");
return;
}
@@ -1331,7 +1364,7 @@ Rt_mebs::extract_particle_number_map_from_txt(Aperture::Pointer& ap)
char sep[] = " ";
char* token;
- int spot_number = 0;
+ int beamlet_number = 0;
int line_number = 0;
int energy_number = 0;
int idx = 0;
@@ -1345,11 +1378,11 @@ Rt_mebs::extract_particle_number_map_from_txt(Aperture::Pointer& ap)
if (buf == "") continue;
if (buf[0] == '#') continue;
- /* Check the dim for the last spot map */
+ /* Check the dim for the last beamlet map */
if (buf.find ("[Energy]") != std::string::npos && energy_number != 0 && line_number != ap->get_dim(1))
{
- printf("***WARNING*** the number of spot line doesn't correspond to the aperture size\n");
- printf("spot line number expected: %d, spot line detected: %d.\n", ap->get_dim(1), line_number);
+ printf("***WARNING*** the number of beamlet line doesn't correspond to the aperture size\n");
+ printf("beamlet line number expected: %d, beamlet line detected: %d.\n", ap->get_dim(1), line_number);
}
if (buf.find ("[Energy]") != std::string::npos)
@@ -1358,7 +1391,7 @@ Rt_mebs::extract_particle_number_map_from_txt(Aperture::Pointer& ap)
val = buf.c_str();
val = strtok(&val[0], "[Energy]");
energy = strtod(val.c_str(),0);
- spot_number = 0;
+ beamlet_number = 0;
line_number = 0;
if (energy > 0)
@@ -1378,74 +1411,77 @@ Rt_mebs::extract_particle_number_map_from_txt(Aperture::Pointer& ap)
continue;
}
- /* If we arrive here, it means that we read a spot map */
+ /* If we arrive here, it means that we read a beamlet map */
val ="";
val = buf.c_str();
val = string_trim (val);
token = strtok(&val[0], sep);
- spot_number = 0;
+ beamlet_number = 0;
while (token != NULL)
{
part_number = strtod(token,0);
- if (spot_number < ap->get_dim(0))
+ if (beamlet_number < ap->get_dim(0))
{
- idx = (energy_number-1) * ap->get_dim(0) * ap->get_dim(1) + line_number * ap->get_dim(0) + spot_number;
+ idx = (energy_number-1) * ap->get_dim(0) * ap->get_dim(1) + line_number * ap->get_dim(0) + beamlet_number;
d_ptr->num_particles[idx] = part_number;
- spot_number++;
+ beamlet_number++;
}
token = strtok(NULL, sep);
}
- if (spot_number != ap->get_dim(0))
+ if (beamlet_number != ap->get_dim(0))
{
- printf("***WARNING*** the number of spots doesn't correspond to the aperture size\n");
- printf("line %d: spot number expected: %d, spot number detected: %d.\n", line_number, ap->get_dim(0), spot_number);
+ printf("***WARNING*** the number of beamlets doesn't correspond to the aperture size\n");
+ printf("line %d: beamlet number expected: %d, beamlet number detected: %d.\n", line_number, ap->get_dim(0), beamlet_number);
}
line_number++;
}
- /* Check the dim for the last spot map */
+ /* Check the dim for the last beamlet map */
if (energy_number != 0 && line_number != ap->get_dim(1))
{
- printf("***WARNING*** the number of spot line doesn't correspond to the aperture size\n");
- printf("spot line number expected: %d, spot line detected: %d.\n", ap->get_dim(1), line_number);
+ printf("***WARNING*** the number of beamlet line doesn't correspond to the aperture size\n");
+ printf("beamlet line number expected: %d, beamlet line detected: %d.\n", ap->get_dim(1), line_number);
}
}
void
-Rt_mebs::compute_particle_number_matrix_from_target_active (Rpl_volume* rpl_vol, Plm_image::Pointer& target, float smearing)
+Rt_mebs::compute_particle_number_matrix_from_target_active (
+ Rpl_volume* rpl_vol,
+ std::vector <double>& wepl_min,
+ std::vector <double>& wepl_max)
{
- int dim[2] = {rpl_vol->get_aperture()->get_dim()[0], rpl_vol->get_aperture()->get_dim()[1]};
+ int dim[2] = {
+ rpl_vol->get_aperture()->get_dim()[0],
+ rpl_vol->get_aperture()->get_dim()[1]
+ };
/* vector containing the min and the max of depth of the target */
- std::vector <double> dmin;
- std::vector <double> dmax;
float min = 0;
float max = 0;
- rpl_vol->compute_beam_modifiers_active_scanning(target->get_vol(), smearing, d_ptr->proximal_margin, d_ptr->distal_margin, dmin, dmax);
/* Sanity check */
- if (dmin.size() != rpl_vol->get_aperture()->get_dim(0) * rpl_vol->get_aperture()->get_dim(1)
- || dmax.size() != rpl_vol->get_aperture()->get_dim(0) * rpl_vol->get_aperture()->get_dim(1))
+ if (wepl_min.size() != rpl_vol->get_aperture()->get_dim(0) * rpl_vol->get_aperture()->get_dim(1)
+ || wepl_max.size() != rpl_vol->get_aperture()->get_dim(0) * rpl_vol->get_aperture()->get_dim(1))
{
printf("ERROR: the aperture size doesn't correspond to the min and max depth maps of the target.\n");
- printf("Aperture size: %d, min depth map size: %d, max depth map size: %d.\n", rpl_vol->get_aperture()->get_dim(0) * rpl_vol->get_aperture()->get_dim(1), dmin.size(), dmax.size());
+ printf("Aperture size: %d, min depth map size: %d, max depth map size: %d.\n", rpl_vol->get_aperture()->get_dim(0) * rpl_vol->get_aperture()->get_dim(1), (int) wepl_min.size(), (int) wepl_max.size());
}
- for (int i = 0; i < dmax.size(); i++)
+ for (size_t i = 0; i < wepl_max.size(); i++)
{
- if (dmax[i] > max)
+ if (wepl_max[i] > max)
{
- max = dmax[i];
+ max = wepl_max[i];
}
}
min = max;
- for (int i = 0; i < dmin.size(); i++)
+ for (size_t i = 0; i < wepl_min.size(); i++)
{
- if (dmin[i] < min && dmin[i] != 0)
+ if (wepl_min[i] < min && wepl_min[i] != 0)
{
- min = dmin[i];
+ min = wepl_min[i];
}
}
this->set_prescription_depths(min, max);
@@ -1455,19 +1491,20 @@ Rt_mebs::compute_particle_number_matrix_from_target_active (Rpl_volume* rpl_vol,
std::vector<float> energy_tmp;
std::vector<float> weight_tmp;
std::vector<Rt_depth_dose*> depth_dose_tmp;
- this->initialize_energy_weight_and_depth_dose_vectors(&weight_tmp, &energy_tmp, &depth_dose_tmp);
+ this->initialize_energy_weight_and_depth_dose_vectors (&weight_tmp, &energy_tmp, &depth_dose_tmp);
/* initialization of the dose matrix slice for monoenergetic slice */
- for (int i = 0; i < dim[0] * dim[1] * d_ptr->energy_number;i++)
+ for (int i = 0; i < dim[0] * dim[1] * d_ptr->energy_number; i++)
{
d_ptr->num_particles.push_back(0);
}
printf("Optimization of the particle number map for any mono-energetic slice in progress...\n");
/* Let's optimize the SOBP for each beamlet */
- for (int i = 0; i < dmin.size(); i++)
+ for (size_t i = 0; i < wepl_min.size(); i++)
{
- this->get_optimized_peaks(dmin[i], dmax[i], &weight_tmp, &depth_dose_tmp);
+ this->get_optimized_peaks (wepl_min[i], wepl_max[i],
+ &weight_tmp, &depth_dose_tmp);
for (int j = 0; j < d_ptr->energy_number; j++)
{
d_ptr->num_particles[i + j * dim[0] * dim[1] ] = weight_tmp[j];
@@ -1475,87 +1512,23 @@ Rt_mebs::compute_particle_number_matrix_from_target_active (Rpl_volume* rpl_vol,
weight_tmp[j] = 0;
}
}
- for (int i = 0; i < energy_tmp.size(); i++)
+ for (size_t i = 0; i < energy_tmp.size(); i++)
{
add_peak(energy_tmp[i], d_ptr->spread, 1);
}
}
-void
-Rt_mebs::compute_particle_number_matrix_from_target_active_slicerRt (Rpl_volume* rpl_vol, Plm_image::Pointer& target, float smearing)
-{
- int dim[2] = {rpl_vol->get_aperture()->get_dim()[0], rpl_vol->get_aperture()->get_dim()[1]};
-
- /* vector containing the min and the max of depth of the target */
- std::vector <double> dmin;
- std::vector <double> dmax;
- float min = 0;
- float max = 0;
- rpl_vol->compute_beam_modifiers_core_slicerRt(target, true, smearing, d_ptr->proximal_margin, d_ptr->distal_margin, dmin, dmax);
-
- /* Sanity check */
- if (dmin.size() != rpl_vol->get_aperture()->get_dim(0) * rpl_vol->get_aperture()->get_dim(1)
- || dmax.size() != rpl_vol->get_aperture()->get_dim(0) * rpl_vol->get_aperture()->get_dim(1))
- {
- printf("ERROR: the aperture size doesn't correspond to the min and max depth maps of the target.\n");
- printf("Aperture size: %d, min depth map size: %d, max depth map size: %d.\n", rpl_vol->get_aperture()->get_dim(0) * rpl_vol->get_aperture()->get_dim(1), dmin.size(), dmax.size());
- }
-
- for (int i = 0; i < dmax.size(); i++)
- {
- if (dmax[i] > max)
- {
- max = dmax[i];
- }
- }
- min = max;
- for (int i = 0; i < dmin.size(); i++)
- {
- if (dmin[i] < min && dmin[i] != 0)
- {
- min = dmin[i];
- }
- }
- this->set_prescription_depths(min, max);
- printf("Min and max depths in the PTV (target + margins): %lg mm and %lg mm.\n", d_ptr->prescription_depth_min, d_ptr->prescription_depth_max);
- printf("Min and max energies for treating the PTV: %lg MeV and %lg MeV.\n", d_ptr->beam_min_energy, d_ptr->beam_max_energy);
-
- std::vector<float> energy_tmp;
- std::vector<float> weight_tmp;
- std::vector<Rt_depth_dose*> depth_dose_tmp;
- this->initialize_energy_weight_and_depth_dose_vectors(&weight_tmp, &energy_tmp, &depth_dose_tmp);
-
- /* initialization of the dose matrix slice for monoenergetic slice */
- for (int i = 0; i < dim[0] * dim[1] * d_ptr->energy_number;i++)
- {
- d_ptr->num_particles.push_back(0);
- }
-
- printf("Optimization of the particle number map for any mono-energetic slice in progress...\n");
- /* Let's optimize the SOBP for each beamlet */
- for (int i = 0; i < dmin.size(); i++)
- {
- this->get_optimized_peaks(dmin[i], dmax[i], &weight_tmp, &depth_dose_tmp);
- for (int j = 0; j < d_ptr->energy_number; j++)
- {
- d_ptr->num_particles[i + j * dim[0] * dim[1] ] = weight_tmp[j];
- /* Reset weight_tmp for next turn */
- weight_tmp[j] = 0;
- }
- }
- for (int i = 0; i < energy_tmp.size(); i++)
- {
- add_peak(energy_tmp[i], d_ptr->spread, 1);
- }
-}
-
-/* This function returns optimized weighted peaks for passive systems (SOBP weights)
- and active systems (beamlet particle numbers for each energy) */
+/* This function returns optimized weighted peaks for passive systems
+ (SOBP weights) and active systems (beamlet particle numbers
+ for each energy) */
void
-Rt_mebs::get_optimized_peaks(float dmin, float dmax, std::vector<float>* weight_tmp, std::vector<Rt_depth_dose*>* depth_dose_tmp)
+Rt_mebs::get_optimized_peaks (
+ float dmin,
+ float dmax,
+ std::vector<float>* weight_tmp,
+ std::vector<Rt_depth_dose*>* depth_dose_tmp)
{
- if (dmin == 0 || dmax == 0)
- {
+ if (dmin == 0 || dmax == 0) {
return;
}
int energy_min_index = (int) floor(pow((dmin/(10*d_ptr->alpha)),(1/d_ptr->p)) / d_ptr->energy_res);
@@ -1565,10 +1538,12 @@ Rt_mebs::get_optimized_peaks(float dmin, float dmax, std::vector<float>* weight_
float E_max_sobp = (float) energy_max_index * d_ptr->energy_res;
/* This is useful only for active scanning */
- /* check that the E_max is sufficiently high for covering the distal part of the prescription */
+ /* check that the E_max is sufficiently high for covering the distal
+ part of the prescription */
E_max_sobp += this->check_and_correct_max_energy(E_max_sobp, dmax);
- /* check that the E_min is sufficiently low for covering the distal part of the prescription */
+ /* check that the E_min is sufficiently low for covering the distal
+ part of the prescription */
E_min_sobp += this->check_and_correct_min_energy(E_min_sobp, dmin);
int i0 = (int) ((d_ptr->beam_max_energy - E_max_sobp) / d_ptr->energy_res);
@@ -1583,7 +1558,6 @@ Rt_mebs::get_optimized_peaks(float dmin, float dmax, std::vector<float>* weight_
}
int idx_max = 0;
-
for (int i = i0; i <= imax; i++)
{
idx_max = (*depth_dose_tmp)[i]->index_of_dose_max;
@@ -1610,7 +1584,8 @@ Rt_mebs::get_optimized_peaks(float dmin, float dmax, std::vector<float>* weight_
e_lut_tmp[j] += (*weight_tmp)[i] * (*depth_dose_tmp)[i]->e_lut[j];
}
}
-
+
+ /* Repeat for 40 iterations */
for (int k = 0; k < 40; k++)
{
for (int i = i0; i <= imax; i++)
@@ -1651,23 +1626,23 @@ Rt_mebs::get_optimized_peaks(float dmin, float dmax, std::vector<float>* weight_
return;
}
- for(int i = i0; i <= imax; i++)
+ for (int i = i0; i <= imax; i++)
{
(*weight_tmp)[i] /= (float) (mean_sobp / mean_count);
}
}
void
-Rt_mebs::export_spot_map_as_txt(Aperture::Pointer ap)
+Rt_mebs::export_as_txt(Aperture::Pointer ap)
{
make_parent_directories (d_ptr->particle_number_out.c_str());
- printf("Trying to write spot maps in %s\n", d_ptr->particle_number_out.c_str());
+ printf("Trying to write mebs in %s\n", d_ptr->particle_number_out.c_str());
std::ofstream fichier(d_ptr->particle_number_out.c_str());
if ( !fichier ){
- std::cerr << "Erreur de creation du fichier spot_map" << std::endl;
+ std::cerr << "Erreur de creation du fichier beamlet_map" << std::endl;
return;
}
@@ -1690,3 +1665,8 @@ Rt_mebs::export_spot_map_as_txt(Aperture::Pointer ap)
fichier.close();
}
+void
+Rt_mebs::set_debug (bool debug)
+{
+ d_ptr->debug = debug;
+}
diff --git a/src/plastimatch/dose/rt_mebs.h b/src/plastimatch/dose/rt_mebs.h
old mode 100644
new mode 100755
index ce3c183..cf9500f
--- a/src/plastimatch/dose/rt_mebs.h
+++ b/src/plastimatch/dose/rt_mebs.h
@@ -2,8 +2,9 @@
See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
----------------------------------------------------------------------- */
/* -----------------------------------------------------------------------
- rt_mebs (for mono-energetic_beam_set) is a class that creates beams of different energies,
- including SOBP (Spread Out Bragg Peak) or any multi-energy beam configuration.
+ rt_mebs (for mono-energetic beamlet set) is a class that creates beams
+ of different energies, including SOBP (Spread Out Bragg Peak)
+ or any multi-energy beam configuration.
----------------------------------------------------------------------- */
#ifndef _rt_mebs_h_
#define _rt_mebs_h_
@@ -18,6 +19,7 @@
#include "plm_config.h"
#include "rpl_volume.h"
#include "rt_lut.h"
+#include "rt_spot_map.h"
#include "smart_pointer.h"
class Rt_depth_dose;
@@ -131,22 +133,41 @@ public:
/* Optimize, then generate mebs depth curve from prescription
range and modulation */
void optimize_sobp ();
- /* Weight optimizer */
- void optimizer (std::vector<float>* weight_tmp, std::vector<float>* energy_tmp);
- void get_optimized_peaks(float dmin, float dmax, std::vector<float>* weight_tmp, std::vector<Rt_depth_dose*>* depth_dose);
- void initialize_energy_weight_and_depth_dose_vectors(std::vector<float>* weight_tmp, std::vector<float>* energy_tmp, std::vector<Rt_depth_dose*>* depth_dose_tmp);
+ /* Weight optimizer */
+ void optimizer (std::vector<float>* weight_tmp,
+ std::vector<float>* energy_tmp);
+ void get_optimized_peaks (float dmin, float dmax,
+ std::vector<float>* weight_tmp,
+ std::vector<Rt_depth_dose*>* depth_dose);
+ void initialize_energy_weight_and_depth_dose_vectors (
+ std::vector<float>* weight_tmp, std::vector<float>* energy_tmp,
+ std::vector<Rt_depth_dose*>* depth_dose_tmp);
+
+ void scale_num_part (double A, int* ap_dim);
+ double get_particle_number_xyz (plm_long* idx, double* rest,
+ int idx_beam, const plm_long* ap_dim);
+
+ // returns also the wed max and min maps
+ void compute_beam_modifiers_active_scanning (
+ Volume *seg_vol, float smearing,
+ float proximal_margin, float distal_margin,
+ std::vector<double>& map_wed_min, std::vector<double>& map_wed_max);
+
+ /* This computes the E_min and E_max map from a target for all pencil beam*/
+ void generate_part_num_from_weight (const plm_long* ap_dim);
+ void compute_particle_number_matrix_from_target_active (
+ Rpl_volume* rpl_vol,
+ std::vector <double>& wepl_min,
+ std::vector <double>& wepl_max);
- void scale_num_part(double A, int* ap_dim);
- double get_particle_number_xyz(int* idx, double* rest, int idx_beam, const int* ap_dim);
+ void set_from_spot_map (const Rt_spot_map::Pointer& rsm);
- /* This computes the E_min and E_max map from a target for all pencil beam*/
- void generate_part_num_from_weight(int* ap_dim);
- void extract_particle_number_map_from_txt(Aperture::Pointer& ap);
- void compute_particle_number_matrix_from_target_active(Rpl_volume* rpl_vol, Plm_image::Pointer& target, float smearing);
- void compute_particle_number_matrix_from_target_active_slicerRt (Rpl_volume* rpl_vol, Plm_image::Pointer& target, float smearing);
+ void load_beamlet_map (Aperture::Pointer& ap);
+ void export_as_txt (Aperture::Pointer ap);
- void export_spot_map_as_txt(Aperture::Pointer ap);
+ /* Debugging */
+ void set_debug (bool);
};
#endif
diff --git a/src/plastimatch/dose/rt_parms.cxx b/src/plastimatch/dose/rt_parms.cxx
old mode 100644
new mode 100755
index 79850b1..08e41a2
--- a/src/plastimatch/dose/rt_parms.cxx
+++ b/src/plastimatch/dose/rt_parms.cxx
@@ -135,9 +135,10 @@ public:
virtual Plm_return_code set_key_value (
const std::string& section,
const std::string& key,
+ const std::string& index,
const std::string& val)
{
- return this->rp->set_key_value (section, key, val);
+ return this->rp->set_key_value (section, key, index, val);
}
};
@@ -168,6 +169,7 @@ Plm_return_code
Rt_parms::set_key_value (
const std::string& section,
const std::string& key,
+ const std::string& index,
const std::string& val)
{
if (section == "COMMENT" || section == "GLOBAL") {
@@ -181,7 +183,7 @@ Rt_parms::set_key_value (
}
else if (key == "target") {
d_ptr->rt_plan->set_target (val);
- }
+ }
else if (key == "threading") {
Threading threading = THREADING_CPU_OPENMP;
if (val == "single") {
@@ -209,7 +211,10 @@ Rt_parms::set_key_value (
d_ptr->rt_plan->set_threading (threading);
}
else if (key == "dose_out") {
- d_ptr->rt_plan->set_output_dose (val);
+ d_ptr->rt_plan->set_output_dose_fn (val);
+ }
+ else if (key == "psp_out") {
+ d_ptr->rt_plan->set_output_psp_fn (val);
}
else if (key == "debug") {
d_ptr->rt_plan->set_debug (string_value_true (val));
@@ -219,13 +224,13 @@ Rt_parms::set_key_value (
if (sscanf (val.c_str(), "%f", &norm_dose) != 1) {
goto error_exit;
}
- if (norm_dose <= 0) {
- goto error_exit;
- }
+ if (norm_dose <= 0) {
+ goto error_exit;
+ }
d_ptr->rt_plan->set_normalization_dose (norm_dose);
- d_ptr->rt_plan->set_have_dose_norm(true);
+ d_ptr->rt_plan->set_have_dose_norm(true);
}
- else if (key == "ref_dose_point") {
+ else if (key == "ref_dose_point") {
float rdp[3];
int rc = sscanf (val.c_str(), "%f %f %f",
&rdp[0], &rdp[1], &rdp[2]);
@@ -233,9 +238,9 @@ Rt_parms::set_key_value (
goto error_exit;
}
d_ptr->rt_plan->set_ref_dose_point (rdp);
- d_ptr->rt_plan->set_have_ref_dose_point(true);
+ d_ptr->rt_plan->set_have_ref_dose_point(true);
}
- else if (key == "non_normalized_dose") {
+ else if (key == "non_normalized_dose") {
if (val.length() >= 1) {
d_ptr->rt_plan->set_non_norm_dose (val[0]);
} else {
@@ -254,12 +259,12 @@ Rt_parms::set_key_value (
if (key == "flavor") {
if (val.length() >= 1) {
- rt_beam->set_flavor (val[0]);
+ rt_beam->set_flavor (val);
} else {
goto error_exit;
}
}
- else if (key == "beam_line") {
+ else if (key == "beam_line") {
rt_beam->set_beam_line_type (val);
}
else if (key == "homo_approx") {
@@ -285,10 +290,13 @@ Rt_parms::set_key_value (
else if (key == "proj_img_out") {
rt_beam->set_proj_img_out (val);
}
+ else if (key == "proj_target_out") {
+ rt_beam->set_proj_target_out (val);
+ }
else if (key == "rc_out") {
rt_beam->set_range_compensator_out (val);
}
- else if (key == "particle_number_out") {
+ else if (key == "particle_number_out") {
rt_beam->get_mebs()->set_particle_number_out (val);
}
else if (key == "sigma_out") {
@@ -297,6 +305,12 @@ Rt_parms::set_key_value (
else if (key == "wed_out") {
rt_beam->set_wed_out (val);
}
+ else if (key == "beam_dump_out") {
+ rt_beam->set_beam_dump_out (val);
+ }
+ else if (key == "dij_out") {
+ rt_beam->set_dij_out (val);
+ }
else if (key == "beam_type") {
Particle_type part = particle_type_parse (val);
if (part == PARTICLE_TYPE_UNKNOWN) {
@@ -315,13 +329,13 @@ Rt_parms::set_key_value (
if (sscanf (val.c_str(), "%lf", &(d_ptr->max_depth)) != 1) {
goto error_exit;
}
- rt_beam->get_mebs()->set_depth_end(d_ptr->max_depth);
+ rt_beam->get_mebs()->set_depth_end(d_ptr->max_depth);
}
else if (key == "depth_dose_z_res") {
if (sscanf (val.c_str(), "%lf", &(d_ptr->depth_res)) != 1) {
goto error_exit;
}
- rt_beam->get_mebs()->set_depth_resolution(d_ptr->max_depth);
+ rt_beam->get_mebs()->set_depth_resolution(d_ptr->max_depth);
}
else if (key == "source") {
float src[3];
@@ -343,7 +357,7 @@ Rt_parms::set_key_value (
}
else if (key == "prescription_min_max") {
float prescription_min;
- float prescription_max;
+ float prescription_max;
int rc = sscanf (val.c_str(), "%f %f", &prescription_min, &prescription_max);
if (rc != 2) {
goto error_exit;
@@ -376,11 +390,12 @@ Rt_parms::set_key_value (
rt_beam->set_aperture_origin (ap_origin);
}
else if (key == "aperture_resolution") {
- int ap_dim[2];
- int rc = sscanf (val.c_str(), "%i %i", &ap_dim[0], &ap_dim[1]);
+ int a, b;
+ int rc = sscanf (val.c_str(), "%i %i", &a, &b);
if (rc != 2) {
goto error_exit;
}
+ plm_long ap_dim[2] = { a, b };
rt_beam->set_aperture_resolution (ap_dim);
}
else if (key == "aperture_spacing") {
@@ -392,7 +407,7 @@ Rt_parms::set_key_value (
}
rt_beam->set_aperture_spacing (ap_spacing);
}
- else if (key == "range_comp_mc_model") {
+ else if (key == "range_comp_mc_model") {
if (val.length() >= 1) {
rt_beam->set_rc_MC_model (val[0]);
} else {
@@ -412,9 +427,9 @@ Rt_parms::set_key_value (
else if (key == "range_compensator_file_in") {
rt_beam->set_range_compensator_in (val);
}
- else if (key == "particle_number_in") {
+ else if (key == "particle_number_in") {
rt_beam->get_mebs()->set_particle_number_in (val);
- rt_beam->get_mebs()->set_have_particle_number_map(true);
+ rt_beam->get_mebs()->set_have_particle_number_map(true);
}
else if (key == "aperture_smearing") {
float smearing;
@@ -437,7 +452,7 @@ Rt_parms::set_key_value (
}
rt_beam->get_mebs()->set_distal_margin (distal_margin);
}
- else if (key == "energy_resolution") {
+ else if (key == "energy_resolution") {
float eres;
if (sscanf (val.c_str(), "%f", &eres) != 1) {
goto error_exit;
@@ -451,6 +466,14 @@ Rt_parms::set_key_value (
}
rt_beam->get_mebs()->set_photon_energy (photon_energy);
}
+ else if (key == "spot") {
+ float xpos, ypos, energy, sigma, weight;
+ if (sscanf (val.c_str(), "%f,%f,%f,%f,%f",
+ &xpos, &ypos, &energy, &sigma, &weight) != 1) {
+ goto error_exit;
+ }
+ rt_beam->add_spot (xpos, ypos, energy, sigma, weight);
+ }
else {
goto error_exit;
}
@@ -487,13 +510,20 @@ Rt_parms::set_key_value (
print_and_exit ("Unknown section value: %s\n", section.c_str());
return PLM_ERROR;
- error_exit:
+error_exit:
print_and_exit ("Unknown (key,val) combination: (%s,%s)\n",
key.c_str(), val.c_str());
return PLM_ERROR;
}
Plm_return_code
+Rt_parms::set_command_file (const char *command_file)
+{
+ Rt_parms_parser rpp (this);
+ return rpp.parse_config_file (command_file);
+}
+
+Plm_return_code
Rt_parms::parse_args (int argc, char** argv)
{
int i;
@@ -512,6 +542,6 @@ Rt_parms::parse_args (int argc, char** argv)
if (!argv[i]) {
print_usage ();
}
- Rt_parms_parser rpp (this);
- return rpp.parse_config_file (argv[i]);
+
+ return this->set_command_file (argv[i]);
}
diff --git a/src/plastimatch/dose/rt_parms.h b/src/plastimatch/dose/rt_parms.h
index f5f6637..209f331 100644
--- a/src/plastimatch/dose/rt_parms.h
+++ b/src/plastimatch/dose/rt_parms.h
@@ -27,15 +27,18 @@ public:
public:
void set_rt_plan (Rt_plan *rt_plan);
+ Plm_return_code set_command_file (const char *command_file);
Plm_return_code parse_args (int argc, char** argv);
Plm_return_code set_key_value (
const std::string& section,
const std::string& key,
+ const std::string& index,
const std::string& val);
void append_beam ();
void append_peak ();
+
protected:
void parse_config (const char* config_fn);
};
diff --git a/src/plastimatch/dose/rt_plan.cxx b/src/plastimatch/dose/rt_plan.cxx
old mode 100644
new mode 100755
index dc4d613..415603d
--- a/src/plastimatch/dose/rt_plan.cxx
+++ b/src/plastimatch/dose/rt_plan.cxx
@@ -8,6 +8,7 @@
#include "aperture.h"
#include "dose_volume_functions.h"
+#include "float_pair_list.h"
#include "plm_image.h"
#include "plm_exception.h"
#include "plm_timer.h"
@@ -17,8 +18,10 @@
#include "ray_data.h"
#include "rpl_volume.h"
#include "rt_beam.h"
+#include "rt_beam_model.h"
#include "rt_depth_dose.h"
#include "rt_dose.h"
+#include "rt_dose_timing.h"
#include "rt_lut.h"
#include "rt_parms.h"
#include "rt_plan.h"
@@ -26,9 +29,10 @@
#include "rt_mebs.h"
#include "rt_study.h"
#include "volume.h"
+#include "volume_adjust.h"
+#include "volume_header.h"
#include "volume_macros.h"
-
-static void display_progress (float is, float of);
+#include "volume_resample.h"
class Rt_plan_private {
@@ -45,16 +49,21 @@ public:
std::string patient_fn;
std::string target_fn;
std::string output_dose_fn;
- std::string output_proj_img_fn;
+ std::string output_psp_fn;
- /* Patient (ct_image) , target, output dose volume */
- Plm_image::Pointer patient;
+ /* Patient (hu), patient (ed or sp) , target, output dose volume */
+ Plm_image::Pointer patient_hu;
+ Plm_image::Pointer patient_psp;
Plm_image::Pointer target;
Plm_image::Pointer dose;
Rt_parms::Pointer rt_parms;
Rt_study* rt_study;
+ Rt_dose_timing::Pointer rt_dose_timing;
+
+ Rt_beam_model::Pointer beam_model;
+
/* Storage of beams */
std::vector<Rt_beam*> beam_storage;
@@ -71,10 +80,12 @@ public:
this->non_norm_dose = 'n';
this->depth_dose_max = 1.f;
- patient = Plm_image::New();
- target = Plm_image::New();
+ patient_hu = Plm_image::New();
+ patient_psp = Plm_image::Pointer();
+ target = Plm_image::Pointer();
dose = Plm_image::New();
rt_parms = Rt_parms::New ();
+ rt_dose_timing = Rt_dose_timing::New ();
}
~Rt_plan_private ()
@@ -85,6 +96,7 @@ public:
Rt_plan::Rt_plan ()
{
this->d_ptr = new Rt_plan_private;
+ d_ptr->rt_parms->set_rt_plan (this);
}
Rt_plan::~Rt_plan ()
@@ -95,10 +107,15 @@ Rt_plan::~Rt_plan ()
Plm_return_code
Rt_plan::parse_args (int argc, char* argv[])
{
- d_ptr->rt_parms->set_rt_plan (this);
return d_ptr->rt_parms->parse_args (argc, argv);
}
+Plm_return_code
+Rt_plan::set_command_file (const char *command_file)
+{
+ return d_ptr->rt_parms->set_command_file (command_file);
+}
+
void
Rt_plan::set_patient (const std::string& patient_fn)
{
@@ -108,58 +125,67 @@ Rt_plan::set_patient (const std::string& patient_fn)
void
Rt_plan::set_patient (Plm_image::Pointer& ct_vol)
{
- d_ptr->patient = ct_vol;
+ d_ptr->patient_hu = ct_vol;
+ d_ptr->patient_hu->convert (PLM_IMG_TYPE_GPUIT_FLOAT);
+ d_ptr->patient_psp = Plm_image::Pointer ();
}
void
Rt_plan::set_patient (ShortImageType::Pointer& ct_vol)
{
- d_ptr->patient->set_itk (ct_vol);
-
- /* compute_segdepth_volume assumes float */
- d_ptr->patient->convert (PLM_IMG_TYPE_GPUIT_FLOAT);
+ /* compute_segdepth_volume assumes float, so convert here */
+ d_ptr->patient_hu->set_itk (ct_vol);
+ d_ptr->patient_hu->convert (PLM_IMG_TYPE_GPUIT_FLOAT);
+ d_ptr->patient_psp = Plm_image::Pointer ();
}
void
Rt_plan::set_patient (FloatImageType::Pointer& ct_vol)
{
- d_ptr->patient->set_itk (ct_vol);
+ d_ptr->patient_hu->set_itk (ct_vol);
+ d_ptr->patient_hu->convert (PLM_IMG_TYPE_GPUIT_FLOAT);
+ d_ptr->patient_psp = Plm_image::Pointer ();
}
void
Rt_plan::set_patient (Volume* ct_vol)
{
- d_ptr->patient->set_volume (ct_vol);
+ d_ptr->patient_hu->set_volume (ct_vol);
}
Volume::Pointer
Rt_plan::get_patient_volume ()
{
- return d_ptr->patient->get_volume_float ();
+ return d_ptr->patient_hu->get_volume_float ();
}
Plm_image *
Rt_plan::get_patient ()
{
- return d_ptr->patient.get();
+ return d_ptr->patient_hu.get();
}
void
Rt_plan::set_target (const std::string& target_fn)
{
d_ptr->target_fn = target_fn;
- d_ptr->target = Plm_image::New (new Plm_image (target_fn));
+}
- /* Need float, because compute_segdepth_volume assumes float */
+void
+Rt_plan::set_target (UCharImageType::Pointer& target_vol)
+{
+ d_ptr->target = Plm_image::New (target_vol);
+
+ /* compute_segdepth_volume assumes float */
d_ptr->target->convert (PLM_IMG_TYPE_GPUIT_FLOAT);
this->propagate_target_to_beams ();
}
void
-Rt_plan::set_target (UCharImageType::Pointer& target_vol)
+Rt_plan::set_target (FloatImageType::Pointer& target_vol)
{
- d_ptr->target->set_itk (target_vol);
+ d_ptr->target = Plm_image::New (target_vol);
/* compute_segdepth_volume assumes float */
d_ptr->target->convert (PLM_IMG_TYPE_GPUIT_FLOAT);
@@ -168,9 +194,15 @@ Rt_plan::set_target (UCharImageType::Pointer& target_vol)
}
void
-Rt_plan::set_target (FloatImageType::Pointer& target_vol)
+Rt_plan::load_target ()
{
- d_ptr->target->set_itk (target_vol);
+ if (d_ptr->target_fn == "") {
+ return;
+ }
+ d_ptr->target = Plm_image::New (new Plm_image (d_ptr->target_fn));
+
+ /* Need float, because compute_segdepth_volume assumes float */
+ d_ptr->target->convert (PLM_IMG_TYPE_GPUIT_FLOAT);
this->propagate_target_to_beams ();
}
@@ -204,6 +236,7 @@ Rt_plan::append_beam ()
new_beam = new Rt_beam;
}
d_ptr->beam_storage.push_back (new_beam);
+ new_beam->set_rt_dose_timing (d_ptr->rt_dose_timing);
new_beam->set_target (d_ptr->target);
return new_beam;
}
@@ -236,7 +269,7 @@ Rt_plan::set_threading (Threading threading)
}
void
-Rt_plan::set_normalization_dose(float normalization_dose)
+Rt_plan::set_normalization_dose (float normalization_dose)
{
d_ptr->normalization_dose = normalization_dose;
}
@@ -278,25 +311,25 @@ Rt_plan::set_ref_dose_point (const double* rdp)
void
Rt_plan::set_have_ref_dose_point(bool have_rdp)
{
- d_ptr->have_rdp = have_rdp;
+ d_ptr->have_rdp = have_rdp;
}
bool
Rt_plan::get_have_ref_dose_point()
{
- return d_ptr->have_rdp;
+ return d_ptr->have_rdp;
}
void
-Rt_plan::set_have_dose_norm(bool have_dose_norm)
+Rt_plan::set_have_dose_norm (bool have_dose_norm)
{
- d_ptr->have_dose_norm = have_dose_norm;
+ d_ptr->have_dose_norm = have_dose_norm;
}
bool
Rt_plan::get_have_dose_norm()
{
- return d_ptr->have_dose_norm;
+ return d_ptr->have_dose_norm;
}
char
@@ -308,7 +341,7 @@ Rt_plan::get_non_norm_dose () const
void
Rt_plan::set_non_norm_dose (char non_norm_dose)
{
- d_ptr->non_norm_dose = non_norm_dose;
+ d_ptr->non_norm_dose = non_norm_dose;
}
void
@@ -320,447 +353,221 @@ Rt_plan::propagate_target_to_beams ()
}
}
-bool
-Rt_plan::prepare_beam_for_calc (Rt_beam *beam)
+void
+Rt_plan::create_patient_psp ()
{
- if (!beam) return false;
- if (!this->get_patient()) return false;
+ Float_pair_list lookup;
+ lookup.push_back (std::pair<float,float> (NLMIN(float), 0));
+ lookup.push_back (std::pair<float,float> (-1000, 0.00106));
+ lookup.push_back (std::pair<float,float> (0, 1.0));
+ lookup.push_back (std::pair<float,float> (41.46, 1.048674));
+ lookup.push_back (std::pair<float,float> (NLMAX(float), 0.005011));
+
+ Volume::Pointer psp = volume_adjust (
+ d_ptr->patient_hu->get_volume(), lookup);
+ d_ptr->patient_psp = Plm_image::New (psp);
+}
- if (beam->get_aperture()->get_distance() > beam->get_source_distance ())
+void
+Rt_plan::normalize_beam_dose (Rt_beam *beam)
+{
+ Plm_image::Pointer dose = beam->get_dose ();
+ Volume::Pointer dose_vol = dose->get_volume ();
+ float* dose_img = (float*) dose_vol->img;
+
+ /* Dose normalization process*/
+ if (this->get_non_norm_dose() != 'y')
{
- throw Plm_exception ("Source distance must be greater than aperture distance");
+ if (this->get_have_ref_dose_point()) // case 1: ref dose point defined
+ {
+ float rdp_ijk[3] = {0,0,0};
+ float rdp[3] = {this->get_ref_dose_point(0), this->get_ref_dose_point(1), this->get_ref_dose_point(2)};
+ rdp_ijk[0] = (rdp[0] - dose_vol->origin[0]) / dose_vol->spacing[0];
+ rdp_ijk[1] = (rdp[1] - dose_vol->origin[1]) / dose_vol->spacing[1];
+ rdp_ijk[2] = (rdp[2] - dose_vol->origin[2]) / dose_vol->spacing[2];
+
+ if (rdp_ijk[0] >=0 && rdp_ijk[1] >=0 && rdp_ijk[2] >=0 && rdp_ijk[0] < dose_vol->dim[0] && rdp_ijk[1] < dose_vol->dim[1] && rdp_ijk[2] < dose_vol->dim[2])
+ {
+ printf("Dose normalized to the dose reference point.\n");
+ dose_normalization_to_dose_and_point(dose_vol, beam->get_beam_weight() * this->get_normalization_dose(), rdp_ijk, rdp, beam); // if no normalization dose, norm_dose = 1 by default
+ if (this->get_have_dose_norm())
+ {
+ printf("%lg x %lg Gy.\n", beam->get_beam_weight(), this->get_normalization_dose());
+ }
+ else
+ {
+ printf("%lg x 100%%.\n", beam->get_beam_weight());
+ }
+ printf("Primary PB num. x, y: %d, %d, primary PB res. x, y: %lg PB/mm, %lg PB/mm\n", beam->get_aperture()->get_dim(0), beam->get_aperture()->get_dim(1), 1.0 / (double) beam->get_aperture()->get_spacing(0), 1.0 / (double) beam->get_aperture()->get_spacing(1));
+ }
+ else
+ {
+ printf("***WARNING***\nThe reference dose point is not in the image volume.\n");
+ dose_normalization_to_dose(dose_vol, beam->get_beam_weight() * this->get_normalization_dose(), beam);
+ if (this->get_have_dose_norm())
+ {
+ printf("%lg x %lg Gy.\n", beam->get_beam_weight(), this->get_normalization_dose());
+ }
+ else
+ {
+ printf("%lg x 100%%.\n", beam->get_beam_weight());
+ }
+ printf("Primary PB num. x, y: %d, %d, primary PB res. x, y: %lg PB/mm, %lg PB/mm\n", beam->get_aperture()->get_dim(0), beam->get_aperture()->get_dim(1), 1.0 / (double) beam->get_aperture()->get_spacing(0), 1.0 / (double) beam->get_aperture()->get_spacing(1));
+ }
+ }
+ else // case 2: no red dose point defined
+ {
+ dose_normalization_to_dose(dose_vol, beam->get_beam_weight() * this->get_normalization_dose(), beam); // normalization_dose = 1 if no dose_prescription is set
+ if (this->get_have_dose_norm())
+ {
+ printf("%lg x %lg Gy.\n", beam->get_beam_weight(), this->get_normalization_dose());
+ }
+ else
+ {
+ printf("%lg x 100%%.\n", beam->get_beam_weight());
+ }
+ printf("Primary PB num. x, y: %d, %d, primary PB res. x, y: %lg PB/mm, %lg PB/mm\n", beam->get_aperture()->get_dim(0), beam->get_aperture()->get_dim(1), 1.0 / (double) beam->get_aperture()->get_spacing(0), 1.0 / (double) beam->get_aperture()->get_spacing(1));
+ }
}
-
- if (!beam->rpl_vol) {beam->rpl_vol = new Rpl_volume;}
- beam->rpl_vol->set_geometry (
- beam->get_source_position(),
- beam->get_isocenter_position(),
- beam->get_aperture()->vup,
- beam->get_aperture()->get_distance(),
- beam->get_aperture()->get_dim(),
- beam->get_aperture()->get_center(),
- beam->get_aperture()->get_spacing(),
- beam->get_step_length());
- if (!beam->rpl_vol) return false;
- /* building the ct_density_vol */
- beam->rpl_ct_vol_HU = new Rpl_volume;
- beam->rpl_ct_vol_HU->set_geometry (
- beam->get_source_position(),
- beam->get_isocenter_position(),
- beam->get_aperture()->vup,
- beam->get_aperture()->get_distance(),
- beam->get_aperture()->get_dim(),
- beam->get_aperture()->get_center(),
- beam->get_aperture()->get_spacing(),
- beam->get_step_length());
- if (!beam->rpl_ct_vol_HU) return false;
- if (beam->get_flavor() == 'f'|| beam->get_flavor() == 'g' || beam->get_flavor() == 'h')
+ else // raw dose, dose not normalized
{
- /* building the sigma_vol */
- beam->sigma_vol = new Rpl_volume;
- beam->sigma_vol->set_geometry (
- beam->get_source_position(),
- beam->get_isocenter_position(),
- beam->get_aperture()->vup,
- beam->get_aperture()->get_distance(),
- beam->get_aperture()->get_dim(),
- beam->get_aperture()->get_center(),
- beam->get_aperture()->get_spacing(),
- beam->get_step_length());
-
- if (!beam->sigma_vol) return false;
+ for (int i = 0; i < dose_vol->dim[0] * dose_vol->dim[1] * dose_vol->dim[2]; i++)
+ {
+ dose_img[i] *= beam->get_beam_weight();
+ }
}
+}
+
+void
+Rt_plan::compute_dose (Rt_beam *beam)
+{
+ printf ("-- compute_dose entry --\n");
+ d_ptr->rt_dose_timing->timer_misc.resume ();
+ Volume::Pointer ct_vol = this->get_patient_volume ();
+ Volume::Pointer dose_vol = ct_vol->clone_empty ();
- /* Copy aperture from scene into rpl volume */
- beam->rpl_ct_vol_HU->set_aperture (beam->get_aperture());
+ Volume* dose_volume_tmp = new Volume;
- beam->rpl_vol->set_aperture (beam->get_aperture());
+ float margin = 0;
+ int margins[2] = {0,0};
+ double range = 0;
+ int new_dim[2]={0,0};
+ double new_center[2]={0,0};
+ double biggest_sigma_ever = 0;
- if (beam->get_flavor() == 'f' || beam->get_flavor() == 'g' || beam->get_flavor() == 'h')
- {
- Aperture::Pointer ap_sigma = Aperture::New(beam->get_aperture());
- beam->sigma_vol->set_aperture (ap_sigma);
- beam->sigma_vol->set_aperture (beam->get_aperture());
+ /* Convert from HU to stopping power, if not already done */
+ if (!d_ptr->patient_psp) {
+ this->create_patient_psp ();
}
- /* Scan through aperture to fill in rpl_volume */
- beam->rpl_vol->set_ct_volume (d_ptr->patient);
-
- if(beam->rpl_vol->get_ct() && beam->rpl_vol->get_ct_limit())
- {
- /* We don't do everything again, we just copy the ct & ct_limits as all the volumes geometrically equal*/
- beam->rpl_ct_vol_HU->set_ct (beam->rpl_vol->get_ct());
- beam->rpl_ct_vol_HU->set_ct_limit(beam->rpl_vol->get_ct_limit());
-
- if (beam->get_flavor() == 'f' || beam->get_flavor() == 'g' || beam->get_flavor() == 'h')
- {
- beam->sigma_vol->set_ct(beam->rpl_vol->get_ct());
- beam->sigma_vol->set_ct_limit(beam->rpl_vol->get_ct_limit());
- }
+ /* Resample target to match CT resolution, if not already done */
+ if (d_ptr->target) {
+ Volume_header vh (d_ptr->patient_hu);
+ d_ptr->target->set_volume (
+ volume_resample (d_ptr->target->get_volume(), &vh));
+ this->propagate_target_to_beams ();
}
- else
+ d_ptr->rt_dose_timing->timer_misc.stop ();
+
+ /* Create rpl images, compute beam modifiers, SOBP etc. according
+ to the teatment strategy */
+ d_ptr->rt_dose_timing->timer_dose_calc.resume ();
+ if (!beam->prepare_for_calc (d_ptr->patient_hu,
+ d_ptr->patient_psp, d_ptr->target))
{
- printf("ray_data or clipping planes to be copied from rpl volume don't exist\n");
+ print_and_exit ("ERROR: Unable to initilize plan.\n");
}
+ d_ptr->rt_dose_timing->timer_dose_calc.stop ();
- /*Now we can compute the rpl_volume*/
- beam->rpl_vol->compute_rpl_PrSTRP_no_rgc ();
- /* and the others */
- if(beam->rpl_vol->get_Ray_data() && beam->rpl_vol->get_front_clipping_plane() && beam->rpl_vol->get_back_clipping_plane())
- {
- beam->rpl_ct_vol_HU->set_ray(beam->rpl_vol->get_Ray_data());
- beam->rpl_ct_vol_HU->set_front_clipping_plane(beam->rpl_vol->get_front_clipping_plane());
- beam->rpl_ct_vol_HU->set_back_clipping_plane(beam->rpl_vol->get_back_clipping_plane());
- beam->rpl_ct_vol_HU->compute_rpl_HU();
+#if defined (commentout)
+ printf ("Computing rpl_ct\n");
+ beam->hu_samp_vol->compute_rpl_HU ();
+#endif
+
+ if (beam->get_flavor() == "a") {
+ compute_dose_a (dose_vol, beam, ct_vol);
+ }
+ else if (beam->get_flavor() == "b") {
+
+ d_ptr->rt_dose_timing->timer_dose_calc.resume ();
- if (beam->get_flavor() == 'f' || beam->get_flavor() == 'g' || beam->get_flavor() == 'h')
+ // Add range compensator to rpl volume
+ if (beam->rsp_accum_vol->get_aperture()->have_range_compensator_image())
{
- /* We don't do everything again, we just copy the ray_data & clipping planes as all the volumes geometrically equal*/
+ add_rcomp_length_to_rpl_volume(beam);
+ }
- beam->sigma_vol->set_ray(beam->rpl_vol->get_Ray_data());
- beam->sigma_vol->set_front_clipping_plane(beam->rpl_vol->get_front_clipping_plane());
- beam->sigma_vol->set_back_clipping_plane(beam->rpl_vol->get_back_clipping_plane());
+ // Loop through energies
+ Rt_mebs::Pointer mebs = beam->get_mebs();
+ std::vector<Rt_depth_dose*> depth_dose = mebs->get_depth_dose();
+ for (size_t i = 0; i < depth_dose.size(); i++) {
+ compute_dose_b (beam, i, ct_vol);
}
+ d_ptr->rt_dose_timing->timer_dose_calc.stop ();
+ d_ptr->rt_dose_timing->timer_reformat.resume ();
+ dose_volume_reconstruction (beam->dose_rv, dose_vol);
+ d_ptr->rt_dose_timing->timer_reformat.stop ();
}
- else
+ else if (beam->get_flavor() == "ray_trace_dij_a")
{
- printf("ct or ct_limits to be copied from rpl_vol don't exist\n");
+ /* This is the same as alg 'a', except that it computes
+ and exports Dij matrices */
+ d_ptr->rt_dose_timing->timer_dose_calc.resume ();
+ // Loop through energies
+ Rt_mebs::Pointer mebs = beam->get_mebs();
+ std::vector<Rt_depth_dose*> depth_dose = mebs->get_depth_dose();
+ for (size_t i = 0; i < depth_dose.size(); i++) {
+ compute_dose_ray_trace_dij_a (beam, i, ct_vol, dose_vol);
+ }
+ d_ptr->rt_dose_timing->timer_dose_calc.resume ();
}
- return true;
-}
-
- void
- Rt_plan::compute_dose (Rt_beam *beam)
+ else if (beam->get_flavor() == "ray_trace_dij_b")
{
- printf ("-- compute_dose entry --\n");
- Volume::Pointer ct_vol = this->get_patient_volume ();
- Volume::Pointer dose_vol = ct_vol->clone_empty ();
- float* dose_img = (float*) dose_vol->img;
-
- Volume* dose_volume_tmp = new Volume;
- float* dose_img_tmp = (float*) dose_volume_tmp->img;
-
- UNUSED_VARIABLE (dose_img_tmp);
-
- float margin = 0;
- int margins[2] = {0,0};
- double range = 0;
- int new_dim[2]={0,0};
- double new_center[2]={0,0};
- double biggest_sigma_ever = 0;
- Plm_timer timer;
- double time_sigma_conv = 0.0;
- double time_dose_calc = 0.0;
- double time_dose_misc = 0.0;
- double time_dose_reformat = 0.0;
-
- printf ("Computing rpl_ct\n");
- beam->rpl_ct_vol_HU->compute_rpl_HU ();
-
- if (beam->get_flavor() == 'f' || beam->get_flavor() == 'g' || beam->get_flavor() == 'h')
- {
- float sigmaMax = 0;
- float *sigma_max =&sigmaMax; // used to find the max sigma in the volume and add extra margins during the dose creation volume
-
- printf ("Computing_void_rpl\n");
-
- beam->sigma_vol->compute_rpl_PrSTRP_no_rgc(); // we compute the rglength in the sigma_volume, without the range compensator as it will be added by a different process
- Rpl_volume* sigma_vol = beam->sigma_vol;
-
- float* sigma_img = (float*) sigma_vol->get_vol()->img;
- UNUSED_VARIABLE (sigma_img);
-
-
- /* building the sigma_dose_vol */
- if (beam->get_flavor() == 'g') {
- beam->rpl_dose_vol = new Rpl_volume;
- }
-
- if (beam->get_flavor() == 'h') {
- beam->rpl_vol_lg = new Rpl_volume;
- beam->rpl_ct_vol_HU_lg = new Rpl_volume;
- beam->sigma_vol_lg = new Rpl_volume;
- }
+ /* This is the same as alg 'b', except that it computes
+ and exports Dij matrices */
- printf ("More setup\n");
+ d_ptr->rt_dose_timing->timer_dose_calc.resume ();
- std::vector<Rt_depth_dose*> depth_dose = beam->get_mebs()->get_depth_dose();
-
- for (size_t i = 0; i < depth_dose.size(); i++) {
- const Rt_depth_dose *ppp = beam->get_mebs()->get_depth_dose()[i];
- printf("Building dose matrix for %lg MeV beamlets - \n", ppp->E0);
- timer.start ();
-
- compute_sigmas (this, beam, ppp->E0, sigma_max, "small", margins);
- time_sigma_conv += timer.report ();
-
- if (beam->get_flavor() == 'f') // Desplanques' algorithm
- {
- range = 10 * get_proton_range(ppp->E0); // range in mm
- dose_volume_create(dose_volume_tmp, sigma_max, beam->rpl_vol, range);
- compute_dose_ray_desplanques(dose_volume_tmp, ct_vol, beam, dose_vol, i);
- }
- else if (beam->get_flavor() == 'g') // Sharp's algorithm
- {
- timer.start ();
-
- if (*sigma_max > biggest_sigma_ever)
- {
- biggest_sigma_ever = *sigma_max;
- /* Calculating the pixel-margins of the aperture to take into account the scattering*/
- margin = (float) 3 * (*sigma_max)/(beam->get_aperture()->get_distance() + beam->rpl_vol->get_front_clipping_plane()) * beam->get_aperture()->get_distance()+1;
- margins[0] = ceil (margin/vec3_len(beam->rpl_vol->get_proj_volume()->get_incr_c()));
- margins[1] = ceil (margin/vec3_len(beam->rpl_vol->get_proj_volume()->get_incr_r()));
- new_dim[0] = beam->rpl_vol->get_aperture()->get_dim(0) + 2 * margins[0];
- new_dim[1] = beam->rpl_vol->get_aperture()->get_dim(1) + 2 * margins[1];
- new_center[0] = beam->rpl_vol->get_aperture()->get_center(0) + margins[0];
- new_center[1] = beam->rpl_vol->get_aperture()->get_center(1) + margins[1];
-
- beam->rpl_dose_vol->get_aperture()->set_center(new_center);
- beam->rpl_dose_vol->get_aperture()->set_dim(new_dim);
- beam->rpl_dose_vol->get_aperture()->set_distance(beam->rpl_vol->get_aperture()->get_distance());
- beam->rpl_dose_vol->get_aperture()->set_spacing(beam->rpl_vol->get_aperture()->get_spacing());
-
- beam->rpl_dose_vol->set_geometry (
- beam->get_source_position(),
- beam->get_isocenter_position(),
- beam->get_aperture()->vup,
- beam->get_aperture()->get_distance(),
- beam->rpl_dose_vol->get_aperture()->get_dim(),
- beam->rpl_dose_vol->get_aperture()->get_center(),
- beam->get_aperture()->get_spacing(),
- beam->get_step_length());
-
- beam->rpl_dose_vol->set_ct(beam->rpl_vol->get_ct());
- beam->rpl_dose_vol->set_ct_limit(beam->rpl_vol->get_ct_limit());
- beam->rpl_dose_vol->compute_ray_data();
- beam->rpl_dose_vol->set_front_clipping_plane(beam->rpl_vol->get_front_clipping_plane());
- beam->rpl_dose_vol->set_back_clipping_plane(beam->rpl_vol->get_back_clipping_plane());
- }
-
- /* update the dose_vol with the CT values before to calculate the dose */
- beam->rpl_dose_vol->compute_rpl_void();
- time_dose_misc += timer.report ();
-
- /* dose calculation in the rpl_dose_volume */
- timer.start ();
- compute_dose_ray_sharp (ct_vol, beam, beam->rpl_dose_vol, i, margins);
- time_dose_calc += timer.report ();
- timer.start ();
- dose_volume_reconstruction(beam->rpl_dose_vol, dose_vol);
- time_dose_reformat += timer.report ();
- }
-
- if (beam->get_flavor() == 'h') // Shackleford's algorithm
- {
- /* Calculating the pixel-margins of the aperture to take into account the scattering*/
- margin = (float) 3 * (*sigma_max)/(beam->get_aperture()->get_distance()+beam->rpl_vol->get_front_clipping_plane()) * beam->get_aperture()->get_distance()+1;
- margins[0] = ceil (margin/vec3_len(beam->rpl_vol->get_proj_volume()->get_incr_c()));
- margins[1] = ceil (margin/vec3_len(beam->rpl_vol->get_proj_volume()->get_incr_r()));
- new_dim[0] = beam->rpl_vol->get_aperture()->get_dim(0) + 2 * margins[0];
- new_dim[1] = beam->rpl_vol->get_aperture()->get_dim(1) + 2 * margins[1];
- new_center[0] = beam->rpl_vol->get_aperture()->get_center(0) + margins[0];
- new_center[1] = beam->rpl_vol->get_aperture()->get_center(1) + margins[1];
-
- int radius_sample = 4;
- int theta_sample = 8;
- std::vector<double> xy_grid (2*(radius_sample * theta_sample),0); // contains the xy coordinates of the sectors in the plane; the central pixel is not included in this vector.
- std::vector<double> area (radius_sample, 0); // contains the areas of the sectors
-
- beam->rpl_vol_lg->get_aperture()->set_center(new_center);
- beam->rpl_vol_lg->get_aperture()->set_dim(new_dim);
- beam->rpl_vol_lg->get_aperture()->set_distance(beam->rpl_vol->get_aperture()->get_distance());
- beam->rpl_vol_lg->get_aperture()->set_spacing(beam->rpl_vol->get_aperture()->get_spacing());
- beam->rpl_vol_lg->set_geometry (beam->get_source_position(), beam->get_isocenter_position(), beam->get_aperture()->vup, beam->get_aperture()->get_distance(), beam->rpl_vol_lg->get_aperture()->get_dim(), beam->rpl_vol_lg->get_aperture()->get_center(), beam->get_aperture()->get_spacing(), beam->get_step_length());
- beam->rpl_vol_lg->set_ct(beam->rpl_vol->get_ct());
- beam->rpl_vol_lg->set_ct_limit(beam->rpl_vol->get_ct_limit());
- beam->rpl_vol_lg->compute_ray_data();
- beam->rpl_vol_lg->compute_rpl_PrSTRP_no_rgc();
-
- beam->rpl_ct_vol_HU_lg->get_aperture()->set_center(new_center);
- beam->rpl_ct_vol_HU_lg->get_aperture()->set_dim(new_dim);
- beam->rpl_ct_vol_HU_lg->get_aperture()->set_distance(beam->rpl_vol->get_aperture()->get_distance());
- beam->rpl_ct_vol_HU_lg->get_aperture()->set_spacing(beam->rpl_vol->get_aperture()->get_spacing());
- beam->rpl_ct_vol_HU_lg->set_geometry (beam->get_source_position(), beam->get_isocenter_position(), beam->get_aperture()->vup, beam->get_aperture()->get_distance(), beam->rpl_vol_lg->get_aperture()->get_dim(), beam->rpl_vol_lg->get_aperture()->get_center(), beam->get_aperture()->get_spacing(), beam->get_step_length());
- beam->rpl_ct_vol_HU_lg->set_ct(beam->rpl_vol->get_ct());
- beam->rpl_ct_vol_HU_lg->set_ct_limit(beam->rpl_vol->get_ct_limit());
- beam->rpl_ct_vol_HU_lg->compute_ray_data();
- beam->rpl_ct_vol_HU_lg->set_front_clipping_plane(beam->rpl_vol_lg->get_front_clipping_plane());
- beam->rpl_ct_vol_HU_lg->set_back_clipping_plane(beam->rpl_vol_lg->get_back_clipping_plane());
- beam->rpl_ct_vol_HU_lg->compute_rpl_HU();
-
- beam->sigma_vol_lg->get_aperture()->set_center(new_center);
- beam->sigma_vol_lg->get_aperture()->set_dim(new_dim);
- beam->sigma_vol_lg->get_aperture()->set_distance(beam->rpl_vol->get_aperture()->get_distance());
- beam->sigma_vol_lg->get_aperture()->set_spacing(beam->rpl_vol->get_aperture()->get_spacing());
- beam->sigma_vol_lg->set_geometry (beam->get_source_position(), beam->get_isocenter_position(), beam->get_aperture()->vup, beam->get_aperture()->get_distance(), beam->rpl_vol_lg->get_aperture()->get_dim(), beam->rpl_vol_lg->get_aperture()->get_center(), beam->get_aperture()->get_spacing(), beam->get_step_length());
- beam->sigma_vol_lg->set_ct(beam->rpl_vol->get_ct());
- beam->sigma_vol_lg->set_ct_limit(beam->rpl_vol->get_ct_limit());
- beam->sigma_vol_lg->compute_ray_data();
- beam->sigma_vol_lg->set_front_clipping_plane(beam->rpl_vol_lg->get_front_clipping_plane());
- beam->sigma_vol_lg->set_back_clipping_plane(beam->rpl_vol_lg->get_back_clipping_plane());
- beam->sigma_vol_lg->compute_rpl_PrSTRP_no_rgc();
-
- compute_sigmas (this, beam, ppp->E0, sigma_max, "large", margins);
- build_hong_grid(&area, &xy_grid, radius_sample, theta_sample);
- compute_dose_ray_shackleford (
- dose_vol, this, beam,
- i, &area, &xy_grid,
- radius_sample, theta_sample);
- }
- printf("dose computed\n");
- }
- }
- if (beam->get_flavor() == 'a') // pull algorithm
- {
- /* Dose D(POI) = Dose(z_POI) but z_POI = rg_comp + depth in CT, if there is a range compensator */
- if (beam->rpl_vol->get_aperture()->have_range_compensator_image())
- {
- add_rcomp_length_to_rpl_volume(beam);
- }
-
- /* scan through patient CT Volume */
- plm_long ct_ijk[3];
- double ct_xyz[4];
- plm_long idx = 0;
- double idx_ap[2] = {0,0};
- int idx_ap_int[2] = {0,0};
- double rest[2] = {0,0};
- unsigned char* ap_img = (unsigned char*) beam->get_aperture()->get_aperture_volume()->img;
- double particle_number = 0;
- float WER = 0;
- float rgdepth = 0;
-
- for (ct_ijk[2] = 0; ct_ijk[2] < ct_vol->dim[2]; ct_ijk[2]++) {
- for (ct_ijk[1] = 0; ct_ijk[1] < ct_vol->dim[1]; ct_ijk[1]++) {
- for (ct_ijk[0] = 0; ct_ijk[0] < ct_vol->dim[0]; ct_ijk[0]++) {
- double dose = 0.0;
-
- /* Transform vol index into space coords */
- ct_xyz[0] = (double) (ct_vol->origin[0] + ct_ijk[0] * ct_vol->spacing[0]);
- ct_xyz[1] = (double) (ct_vol->origin[1] + ct_ijk[1] * ct_vol->spacing[1]);
- ct_xyz[2] = (double) (ct_vol->origin[2] + ct_ijk[2] * ct_vol->spacing[2]);
- ct_xyz[3] = (double) 1.0;
-
- if (beam->get_intersection_with_aperture(idx_ap, idx_ap_int, rest, ct_xyz) == false)
- {
- continue;
- }
-
- /* Check that the ray cross the aperture */
- if (idx_ap[0] < 0 || idx_ap[0] > (double) beam->rpl_ct_vol_HU->get_proj_volume()->get_image_dim(0)-1
- || idx_ap[1] < 0 || idx_ap[1] > (double) beam->rpl_ct_vol_HU->get_proj_volume()->get_image_dim(1)-1)
- {
- continue;
- }
-
- /* Check that the ray cross the active part of the aperture */
- if (beam->get_aperture()->have_aperture_image() && beam->is_ray_in_the_aperture(idx_ap_int, ap_img) == false)
- {
- continue;
- }
-
- switch (beam->get_flavor()) {
- case 'a':
- dose = 0;
- rgdepth = beam->rpl_vol->get_rgdepth (ct_xyz);
- WER = compute_PrWER_from_HU(beam->rpl_ct_vol_HU->get_rgdepth(ct_xyz));
-
- for (size_t beam_idx = 0; beam_idx < beam->get_mebs()->get_depth_dose().size(); beam_idx++)
- {
- particle_number = beam->get_mebs()->get_particle_number_xyz(idx_ap_int, rest, beam_idx, beam->get_aperture()->get_dim());
- if (particle_number != 0 && rgdepth >=0 && rgdepth < beam->get_mebs()->get_depth_dose()[beam_idx]->dend)
- {
- dose += particle_number * WER * energy_direct (rgdepth, beam, beam_idx);
- }
- }
- break;
- }
-
- /* Insert the dose into the dose volume */
- idx = volume_index (dose_vol->dim, ct_ijk);
- dose_img[idx] = dose;
- }
- }
- }
- display_progress ((float)idx, (float)ct_vol->npix);
+ // Add range compensator to rpl volume
+ if (beam->rsp_accum_vol->get_aperture()->have_range_compensator_image())
+ {
+ add_rcomp_length_to_rpl_volume(beam);
}
+
+ // Loop through energies
+ compute_dose_ray_trace_dij_b (beam, ct_vol, dose_vol);
+ d_ptr->rt_dose_timing->timer_dose_calc.stop ();
- /* Dose normalization process*/
- if (this->get_non_norm_dose() != 'y')
- {
- if (this->get_have_ref_dose_point()) // case 1: ref dose point defined
- {
- float rdp_ijk[3] = {0,0,0};
- float rdp[3] = {this->get_ref_dose_point(0), this->get_ref_dose_point(1), this->get_ref_dose_point(2)};
- rdp_ijk[0] = (rdp[0] - dose_vol->origin[0]) / dose_vol->spacing[0];
- rdp_ijk[1] = (rdp[1] - dose_vol->origin[1]) / dose_vol->spacing[1];
- rdp_ijk[2] = (rdp[2] - dose_vol->origin[2]) / dose_vol->spacing[2];
-
- if (rdp_ijk[0] >=0 && rdp_ijk[1] >=0 && rdp_ijk[2] >=0 && rdp_ijk[0] < dose_vol->dim[0] && rdp_ijk[1] < dose_vol->dim[1] && rdp_ijk[2] < dose_vol->dim[2])
- {
- printf("Dose normalized to the dose reference point.\n");
- dose_normalization_to_dose_and_point(dose_vol, beam->get_beam_weight() * this->get_normalization_dose(), rdp_ijk, rdp, beam); // if no normalization dose, norm_dose = 1 by default
- if (this->get_have_dose_norm())
- {
- printf("%lg x %lg Gy.\n", beam->get_beam_weight(), this->get_normalization_dose());
- }
- else
- {
- printf("%lg x 100%%.\n", beam->get_beam_weight());
- }
- printf("Primary PB num. x, y: %d, %d, primary PB res. x, y: %lg PB/mm, %lg PB/mm\n", beam->get_aperture()->get_dim(0), beam->get_aperture()->get_dim(1), 1.0 / (double) beam->get_aperture()->get_spacing(0), 1.0 / (double) beam->get_aperture()->get_spacing(1));
- }
- else
- {
- printf("***WARNING***\nThe reference dose point is not in the image volume.\n");
- dose_normalization_to_dose(dose_vol, beam->get_beam_weight() * this->get_normalization_dose(), beam);
- if (this->get_have_dose_norm())
- {
- printf("%lg x %lg Gy.\n", beam->get_beam_weight(), this->get_normalization_dose());
- }
- else
- {
- printf("%lg x 100%%.\n", beam->get_beam_weight());
- }
- printf("Primary PB num. x, y: %d, %d, primary PB res. x, y: %lg PB/mm, %lg PB/mm\n", beam->get_aperture()->get_dim(0), beam->get_aperture()->get_dim(1), 1.0 / (double) beam->get_aperture()->get_spacing(0), 1.0 / (double) beam->get_aperture()->get_spacing(1));
- }
- }
- else // case 2: no red dose point defined
- {
- dose_normalization_to_dose(dose_vol, beam->get_beam_weight() * this->get_normalization_dose(), beam); // normalization_dose = 1 if no dose_prescription is set
- if (this->get_have_dose_norm())
- {
- printf("%lg x %lg Gy.\n", beam->get_beam_weight(), this->get_normalization_dose());
- }
- else
- {
- printf("%lg x 100%%.\n", beam->get_beam_weight());
- }
- printf("Primary PB num. x, y: %d, %d, primary PB res. x, y: %lg PB/mm, %lg PB/mm\n", beam->get_aperture()->get_dim(0), beam->get_aperture()->get_dim(1), 1.0 / (double) beam->get_aperture()->get_spacing(0), 1.0 / (double) beam->get_aperture()->get_spacing(1));
- }
- }
- else // raw dose, dose not normalized
- {
- for (int i = 0; i < dose_vol->dim[0] * dose_vol->dim[1] * dose_vol->dim[2]; i++)
- {
- dose_img[i] *= beam->get_beam_weight();
- }
- }
-
- Plm_image::Pointer dose = Plm_image::New();
- dose->set_volume (dose_vol);
- beam->set_dose(dose);
+ d_ptr->rt_dose_timing->timer_reformat.resume ();
+ dose_volume_reconstruction (beam->dose_rv, dose_vol);
+ d_ptr->rt_dose_timing->timer_reformat.stop ();
+ }
+ else if (beam->get_flavor() == "d") {
- printf ("Sigma conversion: %f seconds\n", time_sigma_conv);
- printf ("Dose calculation: %f seconds\n", time_dose_calc);
- printf ("Dose reformat: %f seconds\n", time_dose_reformat);
- printf ("Dose overhead: %f seconds\n", time_dose_misc); fflush(stdout);
+ // Loop through energies
+ Rt_mebs::Pointer mebs = beam->get_mebs();
+ std::vector<Rt_depth_dose*> depth_dose = mebs->get_depth_dose();
+ for (size_t i = 0; i < depth_dose.size(); i++) {
+ compute_dose_d (beam, i, ct_vol);
+ }
+ d_ptr->rt_dose_timing->timer_reformat.resume ();
+ dose_volume_reconstruction (beam->dose_rv, dose_vol);
+ d_ptr->rt_dose_timing->timer_reformat.stop ();
}
+ d_ptr->rt_dose_timing->timer_misc.resume ();
+ Plm_image::Pointer dose = Plm_image::New();
+ dose->set_volume (dose_vol);
+ beam->set_dose (dose);
+ this->normalize_beam_dose (beam);
+ d_ptr->rt_dose_timing->timer_misc.stop ();
+}
+
Plm_return_code
Rt_plan::compute_plan ()
{
+ d_ptr->rt_dose_timing->reset ();
+
if (!d_ptr->rt_parms) {
print_and_exit ("Error: cannot compute_plan without an Rt_parms\n");
}
@@ -774,155 +581,68 @@ Rt_plan::compute_plan ()
"not specified in configuration file!\n");
}
- /* Load the patient CT image and save into the plan */
+ /* Load the patient CT image */
+ d_ptr->rt_dose_timing->timer_io.resume ();
Plm_image::Pointer ct = Plm_image::New (d_ptr->patient_fn,
PLM_IMG_TYPE_ITK_FLOAT);
if (!ct) {
print_and_exit ("Error: Unable to load patient volume.\n");
}
this->set_patient (ct);
- this->print_verif ();
+ /* Load the patient target structure */
+ this->load_target ();
+ d_ptr->rt_dose_timing->timer_io.stop ();
+
+ /* Display debugging information */
+ d_ptr->rt_dose_timing->timer_misc.resume ();
+ this->print_verif ();
+
Volume::Pointer ct_vol = this->get_patient_volume ();
Volume::Pointer dose_vol = ct_vol->clone_empty ();
plm_long dim[3] = {dose_vol->dim[0], dose_vol->dim[1], dose_vol->dim[2]};
float* total_dose_img = (float*) dose_vol->img;
-
+ d_ptr->rt_dose_timing->timer_misc.stop ();
+
for (size_t i = 0; i < d_ptr->beam_storage.size(); i++)
{
printf ("\nStart dose calculation Beam %d\n", (int) i + 1);
Rt_beam *beam = d_ptr->beam_storage[i];
- /* try to generate plan with the provided parameters */
- if (!this->prepare_beam_for_calc (beam)) {
- print_and_exit ("ERROR: Unable to initilize plan.\n");
- }
- /* Compute beam modifiers, SOBP etc. according to the teatment strategy */
- beam->compute_prerequisites_beam_tools(this->get_target());
-
- /* GCS FIX: The below code is commented out by Max.
- Need to figure out if it can be safely deleted. */
-#if defined (commentout)
- if (beam->get_beam_line_type() == "passive")
- {
- /* handle auto-generated beam modifiers */
- if (d_ptr->target_fn != "") {
- printf ("Target fn = %s\n", d_ptr->target_fn.c_str());
- this->set_target (d_ptr->target_fn);
- beam->compute_beam_modifiers(this->get_target()->get_vol());
- }
-
- /* generate depth dose curve, might be manual peaks or
- optimized based on prescription, or automatic based on target */
-
- if ((beam->get_mebs()->get_have_copied_peaks() == false && beam->get_mebs()->get_have_prescription() == false && d_ptr->target_fn == "")||(beam->get_mebs()->get_have_manual_peaks() == true)) {
-
- /* Manually specified, so do not optimize */
- if (!beam->get_mebs()->generate ()) {
- return PLM_ERROR;
- }
- }
- else if (d_ptr->target_fn != "" && !beam->get_mebs()->get_have_prescription()) {
- /* Optimize based on target volume */
- Rpl_volume *rpl_vol = beam->rpl_vol;
- beam->get_mebs()->set_prescription(rpl_vol->get_min_wed() - beam->get_mebs()->get_proximal_margin(), rpl_vol->get_max_wed() + beam->get_mebs()->get_distal_margin());
- beam->get_mebs()->optimize_sobp ();
- } else {
- /* Optimize based on manually specified range and modulation */
- beam->get_mebs()->optimize_sobp ();
- }
-
- /* compute the pencil beam spot matrix for passive beams */
- beam->get_mebs()->initialize_and_compute_particle_number_matrix_passive(beam->get_aperture());
- }
- else // active
- {
- // to be computed
-
- /* Compute the aperture and wed matrices */
- if (beam->get_mebs()->get_have_particle_number_map() == false)
- {
- /* we extract the max and min energies to cover the target/prescription */
- beam->compute_beam_modifiers(
- beam->get_mebs()->compute_particle_number_matrix_from_target_active(beam->rpl_vol, beam->get_target(), beam->get_aperture());
- }
- else // spot map exists as a txt file
- {
- beam->get_mebs()->initialize_and_read_particle_number_matrix_active(beam->get_aperture());
- }
- }
- }
-#endif
-
/* Generate dose */
this->set_debug (true);
this->compute_dose (beam);
- /* Save beam modifiers */
- if (beam->get_aperture_out() != "") {
- Rpl_volume *rpl_vol = beam->rpl_vol;
- Plm_image::Pointer& ap = rpl_vol->get_aperture()->get_aperture_image();
- ap->save_image (beam->get_aperture_out().c_str());
- }
-
- if (beam->get_range_compensator_out() != "" && beam->get_beam_line_type() == "passive") {
- Rpl_volume *rpl_vol = beam->rpl_vol;
- Plm_image::Pointer& rc = rpl_vol->get_aperture()->get_range_compensator_image();
- rc->save_image (beam->get_range_compensator_out().c_str());
- }
-
- /* Save projected density volume */
- if (d_ptr->output_proj_img_fn != "") {
- Rpl_volume* proj_img = beam->rpl_ct_vol_HU;
- if (proj_img) {
- proj_img->save (beam->get_proj_img_out());
- }
- }
-
- /* Save projected dose volume */
- if (beam->get_proj_dose_out() != "") {
- Rpl_volume* proj_dose = beam->rpl_dose_vol;
- if (proj_dose) {
- proj_dose->save (beam->get_proj_dose_out());
- }
- }
-
- /* Save sigma volume */
- if (beam->get_sigma_out() != "") {
- Rpl_volume* sigma_img = beam->sigma_vol;
- if (sigma_img) {
- sigma_img->save (beam->get_sigma_out());
- }
- }
-
- /* Save wed volume */
- if (beam->get_wed_out() != "") {
- Rpl_volume* rpl_vol = beam->rpl_vol;
- if (rpl_vol) {
- rpl_vol->save (beam->get_wed_out());
- }
- }
-
- /* Save the spot map */
- if (beam->get_mebs()->get_particle_number_out() != "") {
- beam->get_mebs()->export_spot_map_as_txt(beam->get_aperture());
- }
-
- float* beam_dose_img = (float*) d_ptr->beam_storage[i]->get_dose()->get_volume()->img;
+ /* Save beam data */
+ d_ptr->rt_dose_timing->timer_io.resume ();
+ beam->save_beam_output ();
+ d_ptr->rt_dose_timing->timer_io.stop ();
/* Dose cumulation to the plan dose volume */
+ d_ptr->rt_dose_timing->timer_misc.resume ();
+ float* beam_dose_img = (float*) d_ptr->beam_storage[i]->get_dose()->get_volume()->img;
for (int j = 0; j < dim[0] * dim[1] * dim[2]; j++)
{
total_dose_img[j] += beam_dose_img[j];
}
+ d_ptr->rt_dose_timing->timer_misc.stop ();
}
+ /* Save stopping power image */
+ d_ptr->rt_dose_timing->timer_io.resume ();
+ if (d_ptr->output_psp_fn != "") {
+ d_ptr->patient_psp->save_image (d_ptr->output_psp_fn);
+ }
+
/* Save dose output */
Plm_image::Pointer dose = Plm_image::New();
dose->set_volume (dose_vol);
this->set_dose(dose);
this->get_dose()->save_image (d_ptr->output_dose_fn.c_str());
+ d_ptr->rt_dose_timing->timer_io.stop ();
+ d_ptr->rt_dose_timing->report ();
+
printf ("done. \n\n");
return PLM_SUCCESS;
}
@@ -940,28 +660,21 @@ Rt_plan::get_dose_itk ()
}
void
-Rt_plan::set_output_dose (const std::string& output_dose_fn)
+Rt_plan::set_output_dose_fn (const std::string& output_dose_fn)
{
d_ptr->output_dose_fn = output_dose_fn;
}
void
-Rt_plan::set_dose(Plm_image::Pointer& dose)
+Rt_plan::set_output_psp_fn (const std::string& output_psp_fn)
{
- d_ptr->dose = dose;
+ d_ptr->output_psp_fn = output_psp_fn;
}
-static inline void
-display_progress (
- float is,
- float of
-)
+void
+Rt_plan::set_dose (Plm_image::Pointer& dose)
{
-#if defined (PROGRESS)
- printf (" [%3i%%]\b\b\b\b\b\b\b",
- (int)floorf((is/of)*100.0f));
- fflush (stdout);
-#endif
+ d_ptr->dose = dose;
}
void
@@ -976,7 +689,7 @@ Rt_plan::print_verif ()
printf("\n \n [SETTINGS]");
int num_beams = d_ptr->beam_storage.size();
- printf("\n flavor: "); for (int i = 0; i < num_beams; i++) {printf("%c ** ", d_ptr->beam_storage[i]->get_flavor());}
+ printf("\n flavor: "); for (int i = 0; i < num_beams; i++) {printf("%s ** ", d_ptr->beam_storage[i]->get_flavor().c_str());}
printf("\n homo_approx: "); for (int i = 0; i < num_beams; i++) {printf("%c ** ", d_ptr->beam_storage[i]->get_homo_approx());}
printf("\n ray_step: "); for (int i = 0; i < num_beams; i++) {printf("%lg ** ", d_ptr->beam_storage[i]->get_step_length());}
printf("\n aperture_out: "); for (int i = 0; i < num_beams; i++) {printf("%s ** ", d_ptr->beam_storage[i]->get_aperture_out().c_str());}
@@ -1024,4 +737,5 @@ Rt_plan::print_verif ()
printf("%lg ** ", d_ptr->beam_storage[i]->get_mebs()->get_weight()[j]);
}
}
+ printf ("\n");
}
diff --git a/src/plastimatch/dose/rt_plan.h b/src/plastimatch/dose/rt_plan.h
index 3889d98..1e5be5a 100644
--- a/src/plastimatch/dose/rt_plan.h
+++ b/src/plastimatch/dose/rt_plan.h
@@ -28,6 +28,7 @@ public:
public:
Plm_return_code parse_args (int argc, char* argv[]);
+ Plm_return_code set_command_file (const char *command_file);
/* Set the CT volume for dose calculation.
The Rt_plan takes ownership of this CT/Patient. */
@@ -46,6 +47,7 @@ public:
void set_target (UCharImageType::Pointer&);
void set_target (FloatImageType::Pointer&);
Plm_image::Pointer& get_target ();
+ void load_target ();
/* Set/Get Rt_study */
void set_rt_study(Rt_study* rt_study);
@@ -72,34 +74,36 @@ public:
/* Get the position of the beam isocenter in world coordinates. */
const float* get_ref_dose_point () const;
/* Get the x, y, or z coordinate of the beam source
- in world coordinates. */
+ in world coordinates. */
float get_ref_dose_point (int dim) const;
/* Set the position of the beam isocenter in world coordinates. */
void set_ref_dose_point (const float rdp[3]);
/* Set the position of the beam isocenter in world coordinates. */
void set_ref_dose_point (const double rdp[3]);
- /* Set / Get the declaration of the normalization conditions*/
- void set_have_ref_dose_point(bool have_rdp);
- bool get_have_ref_dose_point();
- void set_have_dose_norm(bool have_dose_norm);
- bool get_have_dose_norm();
+ /* Set / Get the declaration of the normalization conditions*/
+ void set_have_ref_dose_point(bool have_rdp);
+ bool get_have_ref_dose_point();
+ void set_have_dose_norm(bool have_dose_norm);
+ bool get_have_dose_norm();
- /*! \brief Get the "non normalized" dose option */
+ /*! \brief Get the "non normalized" dose option */
char get_non_norm_dose () const;
/*! \brief Set "non normalized" dose option */
void set_non_norm_dose (char non_norm_dose);
/* Compute dose */
+ void create_patient_psp ();
void propagate_target_to_beams ();
- bool prepare_beam_for_calc (Rt_beam *beam);
void compute_dose (Rt_beam *beam);
Plm_return_code compute_plan ();
+ void normalize_beam_dose (Rt_beam *beam);
- /* Get outputs */
+ /* Getting outputs and creating output files */
Plm_image::Pointer get_dose ();
FloatImageType::Pointer get_dose_itk ();
- void set_output_dose (const std::string& output_dose_fn);
+ void set_output_dose_fn (const std::string& output_dose_fn);
+ void set_output_psp_fn (const std::string& output_psp_fn);
void set_dose(Plm_image::Pointer& dose);
void print_verif ();
diff --git a/src/plastimatch/dose/rt_sigma.cxx b/src/plastimatch/dose/rt_sigma.cxx
old mode 100644
new mode 100755
index d0afbe4..1ad6d95
--- a/src/plastimatch/dose/rt_sigma.cxx
+++ b/src/plastimatch/dose/rt_sigma.cxx
@@ -1,6 +1,7 @@
/* -----------------------------------------------------------------------
See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
----------------------------------------------------------------------- */
+#include "plmdose_config.h"
#include "ray_data.h"
#include "rpl_volume.h"
@@ -8,17 +9,19 @@
#include "rt_lut.h"
#include "rt_sigma.h"
-void compute_sigmas (
- Rt_plan* plan,
+void
+compute_sigmas (
const Rt_beam* beam,
float energy,
float* sigma_max,
- std::string size,
- int* margins)
+ std::string size,
+ int* margins)
{
- /* We compute the sigmas for source, range compensator and patient as described in the Hong's paper */
- /* First we set the volume in which the sigmas have to be calculated: the normal rpl_sigma_volume, */
- /* or the extended rpl_sigma_volume for margins. */
+ // We compute the sigmas for source, range compensator and patient
+ // as described in the Hong's paper.
+ // First we set the volume in which the sigmas have to be calculated:
+ // the normal rpl_sigma_volume, or the extended rpl_sigma_volume
+ // for margins.
Rpl_volume* sigma_vol;
Rpl_volume* ct_vol;
@@ -27,23 +30,23 @@ void compute_sigmas (
if (size == "small")
{
sigma_vol = beam->sigma_vol;
- ct_vol = beam->rpl_ct_vol_HU;
- rgl_vol = beam->rpl_vol;
+ ct_vol = beam->hu_samp_vol;
+ rgl_vol = beam->rsp_accum_vol;
}
else
{
sigma_vol = beam->sigma_vol_lg;
- ct_vol = beam->rpl_ct_vol_HU_lg;
+ ct_vol = beam->rpl_vol_samp_lg;
rgl_vol = beam->rpl_vol_lg;
}
/* Now that the volumes were defined, we can compute the sigmas in them and do the quadratic sigmas sum */
/* sigma^2 patient */
- compute_sigma_pt (sigma_vol, rgl_vol, ct_vol, plan, beam, energy);
+ compute_sigma_pt (sigma_vol, rgl_vol, ct_vol, beam, energy);
/* + sigma^2 source */
if (beam->get_source_size() > 0)
{
- compute_sigma_source(sigma_vol, rgl_vol, plan, beam, energy);
+ compute_sigma_source (sigma_vol, rgl_vol, beam, energy);
}
else
{
@@ -52,7 +55,7 @@ void compute_sigmas (
/* + sigma^2 range compensator */
if (beam->get_aperture()->have_range_compensator_image() && energy > 1)
{
- compute_sigma_range_compensator(sigma_vol, rgl_vol, plan, beam, energy, margins);
+ compute_sigma_range_compensator(sigma_vol, rgl_vol, beam, energy, margins);
}
else
{
@@ -83,7 +86,6 @@ void compute_sigma_pt (
Rpl_volume* sigma_vol,
Rpl_volume* rpl_volume,
Rpl_volume* ct_vol,
- Rt_plan* plan,
const Rt_beam* beam,
float energy)
{
@@ -91,17 +93,18 @@ void compute_sigma_pt (
if (beam->get_homo_approx() == 'y')
{
- sigma_max = compute_sigma_pt_homo(sigma_vol, rpl_volume, energy);
+ sigma_max = compute_sigma_pt_homo (sigma_vol, rpl_volume, energy);
}
else
{
- sigma_max = compute_sigma_pt_hetero(sigma_vol, rpl_volume, ct_vol, energy);
+ sigma_max = compute_sigma_pt_hetero (sigma_vol, rpl_volume, ct_vol, energy);
}
printf("Sigma patient computed - sigma_pt_max = %lg mm.\n", sigma_max);
return;
}
-float compute_sigma_pt_homo (
+float
+compute_sigma_pt_homo (
Rpl_volume* sigma_vol,
Rpl_volume* rpl_vol,
float energy)
@@ -116,60 +119,61 @@ float compute_sigma_pt_homo (
printf("Error: rpl_vol & sigma_vol have different dimensions. Sigma volume not built\n");
return 0;
}
- /* At this time, sigma_vol contains the range length, WITHOUT range compensator */
+ // At this time, sigma_vol contains the range length,
+ // WITHOUT range compensator
float* sigma_volume = (float*) sigma_vol->get_vol()->img;
float* rpl_img = (float*) rpl_vol->get_vol()->img;
- unsigned char* ap_img = NULL;
double x_over_range = 0;
- if (rpl_vol->get_aperture()->have_aperture_image())
- {
+ unsigned char* ap_img = 0;
+ if (rpl_vol->get_aperture()->have_aperture_image()) {
ap_img = (unsigned char*) rpl_vol->get_aperture()->get_aperture_volume()->img;
}
- /* Hong method to calculate the sigma value for homogeneous medium */
- /* Range value in water extracted from a fit based on 1-250MeV from the NIST data - ranges in mm */
+ /* Hong method to calculate the sigma value for homogeneous medium */
+ /* Range value in water extracted from a fit based on 1-250MeV
+ from the NIST data - ranges in mm */
double range = 10 * get_proton_range(energy);
- /* Sigma0 value from the Hong fit - See paper Hong "A pencil beam algorithm for proton dose calculation" - sigma in mm: x10 */
+ // Sigma0 value from the Hong fit - See paper Hong "A pencil beam
+ // algorithm for proton dose calculation" - sigma in mm: x10
double sigma0 = 0.02275 * range + 1.2085E-6 * range * range;
/* Calculation of the sigma values from the medium equivalent depth */
- for (int i = 0; i < dim[0] * dim [1]; i++)
- {
- for (int k = 0; k < dim[2]; k++)
- {
- idx = k * dim[0] * dim[1] +i;
- if (!rpl_vol->get_aperture()->have_aperture_image() || (rpl_vol->get_aperture()->have_aperture_image() && ap_img[i] > 0))
+ for (int i = 0; i < dim[0] * dim [1]; i++) {
+ for (int k = 0; k < dim[2]; k++) {
+ idx = k * dim[0] * dim[1] + i;
+ if (ap_img && ap_img[i] == 0) {
+ continue;
+ }
+ if (rpl_img[idx] <= 0)
{
- if (rpl_img[idx] <= 0)
- {
- sigma_volume[idx] = 0;
- }
- else if (rpl_img[idx] >= range)
- {
- sigma_volume[idx] = sigma0 * sigma0; // sigma will contains the square of the sigmas to do the quadratic sum
+ sigma_volume[idx] = 0;
+ }
+ else if (rpl_img[idx] >= range)
+ {
+ // sigma will contains the square of the sigmas to do
+ // the quadratic sum
+ sigma_volume[idx] = sigma0 * sigma0;
- /* sigma_max update */
- if (sigma0 > sigma_max)
- {
- sigma_max = sigma0;
- }
- }
- else
+ /* sigma_max update */
+ if (sigma0 > sigma_max)
{
- x_over_range = rpl_img[idx] / range;
+ sigma_max = sigma0;
+ }
+ }
+ else
+ {
+ x_over_range = rpl_img[idx] / range;
- /* sigma = y0 * Hong (x/range) */
- sigma_volume[idx] = sigma0 * x_over_range * ( 0.26232 + 0.64298 * x_over_range + 0.0952393 * x_over_range * x_over_range);
-
- /* sigma_max update */
- if (sigma_volume[idx] > sigma_max)
- {
- sigma_max = sigma_volume[idx];
- }
- sigma_volume[idx] *= sigma_volume[idx]; // We return sigma^2 to sigma_vol
+ /* sigma = y0 * Hong (x/range) */
+ sigma_volume[idx] = sigma0 * x_over_range * ( 0.26232 + 0.64298 * x_over_range + 0.0952393 * x_over_range * x_over_range);
+
+ if (sigma_volume[idx] > sigma_max) {
+ sigma_max = sigma_volume[idx];
}
+ // We return sigma^2 to sigma_vol
+ sigma_volume[idx] *= sigma_volume[idx];
}
}
}
@@ -178,19 +182,19 @@ float compute_sigma_pt_homo (
float compute_sigma_pt_hetero (
Rpl_volume* sigma_vol,
- Rpl_volume* rgl_vol,
+ Rpl_volume* rpl_vol,
Rpl_volume* ct_vol,
float energy)
{
float sigma_max = 0;
float* sigma_img = (float*) sigma_vol->get_vol()->img;
- float* rpl_img = (float*) rgl_vol->get_vol()->img;
+ float* rpl_img = (float*) rpl_vol->get_vol()->img;
float* ct_img = (float*) ct_vol->get_vol()->img;
unsigned char* ap_img = 0;
- if (rgl_vol->get_aperture()->have_aperture_image())
+ if (rpl_vol->get_aperture()->have_aperture_image())
{
- ap_img = (unsigned char*) rgl_vol->get_aperture()->get_aperture_volume()->img;
+ ap_img = (unsigned char*) rpl_vol->get_aperture()->get_aperture_volume()->img;
}
plm_long dim[3] = { sigma_vol->get_vol()->dim[0], sigma_vol->get_vol()->dim[1], sigma_vol->get_vol()->dim[2]};
@@ -203,7 +207,7 @@ float compute_sigma_pt_hetero (
float spacing = sigma_vol->get_vol()->spacing[2]/10; // in cm to correspond to the Highland formula
float E = energy;
- float mc2 = (float) PROTON_REST_MASS; /* proton mass at rest (MeV) */
+ float mc2 = (float) PROTON_REST_MASS; /* proton mass at rest (MeV) */
float c = (float) LIGHT_SPEED; /* speed of light (m/s) */
float p = 0.0; /* Proton momentum (passed in) */
float v = 0.0; /* Proton velocity (passed in) */
@@ -219,10 +223,10 @@ float compute_sigma_pt_hetero (
printf ("sigma_img: %d %d %d\n", (int) sigma_vol->get_vol()->dim[0],
(int) sigma_vol->get_vol()->dim[1], (int) sigma_vol->get_vol()->dim[2]);
printf("dim: %d %d %d\n", (int) dim[0], (int) dim[1], (int) dim[2]);
-
+
for (int apert_idx = 0; apert_idx < dim[0] * dim[1]; apert_idx++)
{
- if (!rgl_vol->get_aperture()->have_aperture_image() || (rgl_vol->get_aperture()->have_aperture_image() && ap_img[apert_idx] > 0))
+ if (!rpl_vol->get_aperture()->have_aperture_image() || (rpl_vol->get_aperture()->have_aperture_image() && ap_img[apert_idx] > 0))
{
int first_non_null_loc = 0;
for (int s = 0; s < dim[2]; s++)
@@ -250,13 +254,16 @@ float compute_sigma_pt_hetero (
}
}
- /* Step 2: Each pixel in the volume will receive its sigma (in reality y0) value, according to the differential Highland formula */
-
+ // Step 2: Each pixel in the volume will receive its sigma
+ // (in reality y0) value, according to the differential
+ // Highland formula */
std::vector<double> pv_cache (dim[2], 0);
std::vector<double> inv_rad_len (dim[2], 0);
std::vector<double> stop_cache (dim[2], 0);
- E = energy; // we set the energy of the particles to the nominal energy for this ray
+ // we set the energy of the particles to the nominal energy
+ // for this ray
+ E = energy;
for (int s = first_non_null_loc; s < dim[2]; s++)
{
@@ -264,9 +271,11 @@ float compute_sigma_pt_hetero (
v = c*sqrt(1-pow((mc2/(E+mc2)),2)); //in m.s-1
pv_cache[s] = p * v;
+ /* GCS FIX: The X0 depends on radiation length, not
+ proton stopping power. Yuck. */
+ // dE/dx_mat = dE /dx_watter * STPR (lut in g/cm2)
inv_rad_len[s] = 1.0f / compute_X0_from_HU(HU_ray[s]);
- stop_cache[s] = compute_PrSTPR_from_HU(HU_ray[s]) * get_proton_stop(E); // dE/dx_mat = dE /dx_watter * STPR (lut in g/cm2)
-
+ stop_cache[s] = compute_PrSTPR_from_HU(HU_ray[s]) * get_proton_stop(E);
sum = 0;
inverse_rad_length_integrated = 0;
@@ -328,7 +337,10 @@ float compute_sigma_pt_hetero (
return sigma_max;
}
-void compute_sigma_source (Rpl_volume* sigma_vol, Rpl_volume* rpl_volume, Rt_plan* plan, const Rt_beam *beam, float energy)
+void
+compute_sigma_source (
+ Rpl_volume* sigma_vol, Rpl_volume* rpl_volume,
+ const Rt_beam *beam, float energy)
{
/* Method of the Hong's algorithm - See Hong's paper */
float* sigma_img = (float*) sigma_vol->get_vol()->img;
@@ -343,8 +355,8 @@ void compute_sigma_source (Rpl_volume* sigma_vol, Rpl_volume* rpl_volume, Rt_pla
/* MD Fix: Why plan->ap->nrm is incorrect at this point??? */
double nrm[3] = {0,0,0};
- vec3_sub3(nrm, beam->get_source_position(), beam->get_isocenter_position());
- vec3_normalize1(nrm);
+ vec3_sub3 (nrm, beam->get_source_position(), beam->get_isocenter_position());
+ vec3_normalize1 (nrm);
plm_long dim[3] = { sigma_vol->get_vol()->dim[0], sigma_vol->get_vol()->dim[1], sigma_vol->get_vol()->dim[2]};
float range = get_proton_range(energy);
@@ -353,7 +365,7 @@ void compute_sigma_source (Rpl_volume* sigma_vol, Rpl_volume* rpl_volume, Rt_pla
{
if (ap_img[i] > 0)
{
- Ray_data* ray_data = &sigma_vol->get_Ray_data()[i];
+ Ray_data* ray_data = &sigma_vol->get_ray_data()[i];
proj = -vec3_dot(ray_data->ray, nrm);
dist_cp = vec3_dist(ray_data->cp,beam->get_source_position());
@@ -377,15 +389,17 @@ void compute_sigma_source (Rpl_volume* sigma_vol, Rpl_volume* rpl_volume, Rt_pla
}
}
}
- printf("Sigma source computed - sigma_source_max = %lg mm.\n", sigma_max);
- return;
+ printf ("Sigma source computed - sigma_source_max = %lg mm.\n", sigma_max);
}
-void compute_sigma_range_compensator(Rpl_volume* sigma_vol, Rpl_volume* rpl_volume, Rt_plan* plan, const Rt_beam *beam, float energy, int* margins)
+void
+compute_sigma_range_compensator (
+ Rpl_volume* sigma_vol, Rpl_volume* rpl_volume,
+ const Rt_beam *beam, float energy, int* margins)
{
- /* There are two methods for computing the beam spread due to a range compensator */
+ /* There are two methods for computing the beam spread due to a range compensator */
/* Method1 rc_MC_model: Hong's algorithm (Highland)- See Hong's paper */
- /* Method2: model built on Monte Carlo simulations - Paper still unpublished */
+ /* Method2: model built on Monte Carlo simulations - Paper still unpublished */
/* The range compensator is supposed to be made of lucite and placed right after the aperture*/
if (energy < 1)
@@ -396,17 +410,17 @@ void compute_sigma_range_compensator(Rpl_volume* sigma_vol, Rpl_volume* rpl_volu
/* Range value in lucite extracted from a fit based on 1-250MeV from the NIST data - ranges in mm */
double range = 10 * get_proton_range((double) energy);
- /* Theta0 computation */
- double theta0 = 0;
+ /* Theta0 computation */
+ double theta0 = 0;
- if (beam->get_rc_MC_model() != 'y')
- {
- theta0 = get_theta0_Highland(range);
- }
- else
- {
- theta0 = get_theta0_MC(energy);
- }
+ if (beam->get_rc_MC_model() != 'y')
+ {
+ theta0 = get_theta0_Highland(range);
+ }
+ else
+ {
+ theta0 = get_theta0_MC(energy);
+ }
/* sigma calculation and length computations */
float* sigma_img = (float*) sigma_vol->get_vol()->img;
@@ -440,41 +454,39 @@ void compute_sigma_range_compensator(Rpl_volume* sigma_vol, Rpl_volume* rpl_volu
double sigma;
double nrm[3] = {0,0,0};
- /* MD Fix: Why plan->ap->nrm is incorrect at this point??? */
- vec3_sub3(nrm, beam->get_source_position(), beam->get_isocenter_position());
+ /* MD Fix: Why plan->ap->nrm is incorrect at this point??? */
+ vec3_sub3 (nrm, beam->get_source_position(), beam->get_isocenter_position());
vec3_normalize1(nrm);
- if (margins[0] == 0 && margins[1] == 0 || beam->get_flavor() != 'h')
- {
- for (int i = 0; i < dim[0] * dim[1]; i++)
- {
+ if (margins[0] == 0 && margins[1] == 0) {
+ for (int i = 0; i < dim[0] * dim[1]; i++) {
/* calculation of sigma_srm, see graph A3 from the Hong's paper */
- if (!rpl_volume->get_aperture()->have_aperture_image() || (ap_img && ap_img[i] > 0))
+ if (!rpl_volume->get_aperture()->have_aperture_image() || (ap_img && ap_img[i] > 0))
{
- Ray_data* ray_data = &sigma_vol->get_Ray_data()[i];
+ Ray_data* ray_data = &sigma_vol->get_ray_data()[i];
proj = -vec3_dot(ray_data->ray, nrm);
- if (proj == 0)
- {
- printf("error: some rays are perpendicular to the beam axis \n");
- return;
- }
+ if (proj == 0)
+ {
+ printf("error: some rays are perpendicular to the beam axis \n");
+ return;
+ }
dist_cp = vec3_dist(ray_data->cp, beam->get_source_position());
rc_over_range = rc_img[i] / proj * PMMA_DENSITY * PMMA_STPR / range; // energy is >1, so range > 0 (range is in water: rho * WER)
if (rc_over_range < 1)
{
- if (beam->get_rc_MC_model() != 'y')
- {
- theta_srm = theta0 * get_theta_rel_Highland(rc_over_range);
- rc_eff = get_scat_or_Highland(rc_over_range) * rc_img[i];
- }
- else
- {
- theta_srm = theta0 * get_theta_rel_MC(rc_over_range);
- rc_eff = get_scat_or_MC(rc_over_range) * rc_img[i];
- }
+ if (beam->get_rc_MC_model() != 'y')
+ {
+ theta_srm = theta0 * get_theta_rel_Highland(rc_over_range);
+ rc_eff = get_scat_or_Highland(rc_over_range) * rc_img[i];
+ }
+ else
+ {
+ theta_srm = theta0 * get_theta_rel_MC(rc_over_range);
+ rc_eff = get_scat_or_MC(rc_over_range) * rc_img[i];
+ }
for (int j = 0; j < dim[2]; j++)
{
@@ -526,31 +538,31 @@ void compute_sigma_range_compensator(Rpl_volume* sigma_vol, Rpl_volume* rpl_volu
/* calculation of sigma_srm, see graph A3 from the Hong's paper */
if (!rpl_volume->get_aperture()->have_aperture_image() || (rpl_volume->get_aperture()->have_aperture_image() && ap_img[idx2d_sm] > 0))
{
- Ray_data* ray_data = &sigma_vol->get_Ray_data()[idx2d_lg];
+ Ray_data* ray_data = &sigma_vol->get_ray_data()[idx2d_lg];
- proj = -vec3_dot(ray_data->ray, nrm);
+ proj = -vec3_dot(ray_data->ray, nrm);
- if (proj == 0)
- {
- printf("error: some rays are perpendicular to the beam axis \n");
- return;
- }
+ if (proj == 0)
+ {
+ printf("error: some rays are perpendicular to the beam axis \n");
+ return;
+ }
- dist_cp = vec3_dist(ray_data->cp, beam->get_source_position());
+ dist_cp = vec3_dist(ray_data->cp, beam->get_source_position());
rc_over_range = rc_img[idx2d_sm] / proj * PMMA_DENSITY * PMMA_STPR / range; // energy is >1, so range > 0
if (rc_over_range < 1)
{
- if (beam->get_rc_MC_model() != 'y')
- {
- theta_srm = theta0 * get_theta_rel_Highland(rc_over_range);
- rc_eff = get_scat_or_Highland(rc_over_range) * rc_img[idx2d_sm];
- }
- else
- {
- theta_srm = theta0 * get_theta_rel_MC(rc_over_range);
- rc_eff = get_scat_or_MC(rc_over_range) * rc_img[idx2d_sm];
- }
+ if (beam->get_rc_MC_model() != 'y')
+ {
+ theta_srm = theta0 * get_theta_rel_Highland(rc_over_range);
+ rc_eff = get_scat_or_Highland(rc_over_range) * rc_img[idx2d_sm];
+ }
+ else
+ {
+ theta_srm = theta0 * get_theta_rel_MC(rc_over_range);
+ rc_eff = get_scat_or_MC(rc_over_range) * rc_img[idx2d_sm];
+ }
for (int k = 0; k < dim[2]; k++)
{
diff --git a/src/plastimatch/dose/rt_sigma.h b/src/plastimatch/dose/rt_sigma.h
index b09ef0a..1a69706 100644
--- a/src/plastimatch/dose/rt_sigma.h
+++ b/src/plastimatch/dose/rt_sigma.h
@@ -7,11 +7,11 @@
#include "rt_plan.h"
#include "rpl_volume.h"
-void compute_sigmas(Rt_plan* plan, const Rt_beam* beam, float energy, float* sigma_max, std::string size, int* margins);
-void compute_sigma_pt(Rpl_volume* sigma_vol, Rpl_volume* rpl_volume, Rpl_volume* ct_vol, Rt_plan* plan, const Rt_beam* beam, float energy);
-float compute_sigma_pt_homo(Rpl_volume* sigma_vol, Rpl_volume* rpl_vol, float energy);
-float compute_sigma_pt_hetero(Rpl_volume* sigma_vol, Rpl_volume* rgl_vol, Rpl_volume* ct_vol, float energy);
-void compute_sigma_source(Rpl_volume* sigma_vol, Rpl_volume* rpl_volume, Rt_plan* plan, const Rt_beam* beam, float energy);
-void compute_sigma_range_compensator(Rpl_volume* sigma_vol, Rpl_volume* rpl_volume, Rt_plan* plan, const Rt_beam* beam, float energy, int* margins);
+void compute_sigmas (const Rt_beam* beam, float energy, float* sigma_max, std::string size, int* margins);
+void compute_sigma_pt (Rpl_volume* sigma_vol, Rpl_volume* rpl_volume, Rpl_volume* ct_vol, const Rt_beam* beam, float energy);
+float compute_sigma_pt_homo (Rpl_volume* sigma_vol, Rpl_volume* rpl_vol, float energy);
+float compute_sigma_pt_hetero (Rpl_volume* sigma_vol, Rpl_volume* rgl_vol, Rpl_volume* ct_vol, float energy);
+void compute_sigma_source (Rpl_volume* sigma_vol, Rpl_volume* rpl_volume, const Rt_beam* beam, float energy);
+void compute_sigma_range_compensator (Rpl_volume* sigma_vol, Rpl_volume* rpl_volume, const Rt_beam* beam, float energy, int* margins);
#endif
diff --git a/src/plastimatch/dose/rt_spot_map.cxx b/src/plastimatch/dose/rt_spot_map.cxx
new file mode 100755
index 0000000..b5dc209
--- /dev/null
+++ b/src/plastimatch/dose/rt_spot_map.cxx
@@ -0,0 +1,55 @@
+/* -----------------------------------------------------------------------
+ See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
+ ----------------------------------------------------------------------- */
+#include "plmdose_config.h"
+#include <list>
+#include "rt_spot_map.h"
+
+class Rt_spot_map_private {
+public:
+ std::list<Rt_spot> spot_list;
+};
+
+Rt_spot_map::Rt_spot_map ()
+{
+ d_ptr = new Rt_spot_map_private;
+}
+
+Rt_spot_map::~Rt_spot_map ()
+{
+ delete d_ptr;
+}
+
+void
+Rt_spot_map::add_spot (
+ float xpos,
+ float ypos,
+ float energy,
+ float sigma,
+ float weight)
+{
+ d_ptr->spot_list.push_back (
+ Rt_spot (xpos, ypos, energy, sigma, weight));
+}
+
+size_t
+Rt_spot_map::num_spots () const
+{
+ return d_ptr->spot_list.size ();
+}
+
+const std::list<Rt_spot>&
+Rt_spot_map::get_spot_list () const
+{
+ return d_ptr->spot_list;
+}
+
+void
+Rt_spot_map::load_spot_map (const std::string& fn)
+{
+}
+
+void
+Rt_spot_map::save_spot_map (const std::string& fn) const
+{
+}
diff --git a/src/plastimatch/dose/rt_spot_map.h b/src/plastimatch/dose/rt_spot_map.h
new file mode 100755
index 0000000..f8a7f2d
--- /dev/null
+++ b/src/plastimatch/dose/rt_spot_map.h
@@ -0,0 +1,43 @@
+/* -----------------------------------------------------------------------
+ See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
+ ----------------------------------------------------------------------- */
+#ifndef _rt_spot_map_h_
+#define _rt_spot_map_h_
+
+#include "plmdose_config.h"
+#include "smart_pointer.h"
+
+class Rt_spot_map_private;
+
+class PLMDOSE_API Rt_spot {
+public:
+ Rt_spot (
+ float xpos, float ypos, float energy, float sigma, float weight)
+ : xpos(xpos), ypos(ypos), energy(energy), sigma(sigma), weight(weight)
+ {}
+public:
+ float xpos;
+ float ypos;
+ float energy;
+ float sigma;
+ float weight;
+};
+
+class PLMDOSE_API Rt_spot_map {
+public:
+ SMART_POINTER_SUPPORT (Rt_spot_map);
+ Rt_spot_map_private *d_ptr;
+public:
+ Rt_spot_map ();
+ ~Rt_spot_map ();
+public:
+ void add_spot (
+ float xpos, float ypos, float energy, float sigma, float weight);
+ size_t num_spots () const;
+ const std::list<Rt_spot>& get_spot_list () const;
+
+ void load_spot_map (const std::string& fn);
+ void save_spot_map (const std::string& fn) const;
+};
+
+#endif
diff --git a/src/plastimatch/dose/wed_parms.h b/src/plastimatch/dose/wed_parms.h
old mode 100644
new mode 100755
index ad03b93..c162d98
--- a/src/plastimatch/dose/wed_parms.h
+++ b/src/plastimatch/dose/wed_parms.h
@@ -6,6 +6,7 @@
#include "plmdose_config.h"
#include <string>
+#include "plm_int.h"
class PLMDOSE_API Wed_Parms {
public:
@@ -13,7 +14,6 @@ public:
~Wed_Parms ();
bool parse_args (int argc, char** argv);
- //void parse_group (int argc, char** argv, int line);
private:
void parse_config (const char* config_fn);
@@ -41,9 +41,6 @@ public:
std::string output_dew_ct_fn; /* output: ct in world coordinates */
std::string output_dew_dose_fn; /* output: dose in world coordinates */
-// std::string output_ap_fn; /* output: aperture volume */
-// std::string output_depth_fn; /* output: depth volume */
-
/* [BEAM] */
bool have_ray_step;
float ray_step; /* Uniform ray step size (mm) */
@@ -53,7 +50,7 @@ public:
/* [APERTURE] */
float vup[3];
- int ires[2];
+ plm_long ires[2];
bool have_ic;
bool have_ires;
float ic[2];
diff --git a/src/plastimatch/opencl/CMakeLists.txt b/src/plastimatch/opencl/CMakeLists.txt
old mode 100755
new mode 100644
diff --git a/src/plastimatch/opencl/autotune_opencl.cxx b/src/plastimatch/opencl/autotune_opencl.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/opencl/autotune_opencl.h b/src/plastimatch/opencl/autotune_opencl.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/reconstruct/drr.cxx b/src/plastimatch/reconstruct/drr.cxx
index b843b66..77a17a4 100644
--- a/src/plastimatch/reconstruct/drr.cxx
+++ b/src/plastimatch/reconstruct/drr.cxx
@@ -14,6 +14,7 @@
#include "drr_cuda.h"
#include "drr_opencl.h"
#include "drr_trilin.h"
+#include "file_util.h"
#include "plm_int.h"
#include "plm_math.h"
#include "proj_image.h"
@@ -183,7 +184,11 @@ drr_ray_trace_image (
FILE *details_fp = 0;
if (options->output_details_fn != "") {
- details_fp = fopen (options->output_details_fn.c_str(), "w");
+ details_fp = plm_fopen (options->output_details_fn.c_str(), "w");
+ if (!details_fp) {
+ print_and_exit ("Failed to open %s for write\n",
+ options->output_details_fn.c_str());
+ }
}
/* Compute the drr pixels */
diff --git a/src/plastimatch/reconstruct/drr_opencl.cxx b/src/plastimatch/reconstruct/drr_opencl.cxx
index eeef2ab..5575f6b 100644
--- a/src/plastimatch/reconstruct/drr_opencl.cxx
+++ b/src/plastimatch/reconstruct/drr_opencl.cxx
@@ -97,7 +97,6 @@ drr_opencl_ray_trace_image (
cl_float4 ocl_nrm, ocl_lower_limit, ocl_upper_limit;
cl_float ocl_sad;
cl_int4 ocl_vol_dim;
- cl_int2 ocl_proj_dim;
/* Copy ic to device (convert from double to float) */
opencl_idx(ocl_ic,0) = proj->pmat->ic[0];
@@ -146,10 +145,6 @@ drr_opencl_ray_trace_image (
opencl_idx(ocl_vol_dim,1) = vol->dim[1];
opencl_idx(ocl_vol_dim,2) = vol->dim[2];
- /* Copy projection image dim (convert from size_t to int) */
- opencl_idx(ocl_proj_dim,0) = proj->dim[0];
- opencl_idx(ocl_proj_dim,1) = proj->dim[1];
-
/* Set drr kernel arguments */
opencl_set_kernel_args (
&dev_state->ocl_dev,
diff --git a/src/plastimatch/reconstruct/fdk.cxx b/src/plastimatch/reconstruct/fdk.cxx
old mode 100644
new mode 100755
index 4e09c99..8fb663b
--- a/src/plastimatch/reconstruct/fdk.cxx
+++ b/src/plastimatch/reconstruct/fdk.cxx
@@ -567,7 +567,7 @@ project_volume_onto_image_reference (
double ip[3]; /* ip = image position */
double s; /* s = projection of vp onto s axis */
vp[0] = (double) (vol->origin[0] + i * vol->spacing[0]);
- mat43_mult_vec3 (ip, pmat->matrix, vp); /* ip = matrix * vp */
+ mat43_mult_vec4 (ip, pmat->matrix, vp); /* ip = matrix * vp */
ip[0] = pmat->ic[0] + ip[0] / ip[2];
ip[1] = pmat->ic[1] + ip[1] / ip[2];
/* Distance on cenral axis from voxel center to source */
diff --git a/src/plastimatch/register/CMakeLists.txt b/src/plastimatch/register/CMakeLists.txt
index c9d4528..1349d30 100644
--- a/src/plastimatch/register/CMakeLists.txt
+++ b/src/plastimatch/register/CMakeLists.txt
@@ -22,57 +22,65 @@ endif ()
## SOURCE FILES
##-----------------------------------------------------------------------------
set (PLMREGISTER_LIBRARY_SRC
- bspline.cxx
+ bspline.cxx bspline.h
bspline_loop.txx
- bspline_landmarks.cxx
+ bspline_landmarks.cxx bspline_landmarks.h
bspline_gm.cxx bspline_gm.h
bspline_gm.txx
bspline_mi.cxx bspline_mi.h
bspline_mi.txx
- bspline_mi_hist.cxx
bspline_mse.cxx bspline_mse.h
bspline_mse.txx
- bspline_optimize.cxx
- bspline_optimize_lbfgsb.cxx
- bspline_optimize_liblbfgs.cxx
- bspline_optimize_nlopt.cxx
- bspline_optimize_steepest.cxx
+ bspline_optimize.cxx bspline_optimize.h
+ bspline_optimize_lbfgsb.cxx bspline_optimize_lbfgsb.h
+ bspline_optimize_liblbfgs.cxx bspline_optimize_liblbfgs.h
+ bspline_optimize_nlopt.cxx bspline_optimize_nlopt.h
+ bspline_optimize_steepest.cxx bspline_optimize_steepest.h
bspline_parms.cxx bspline_parms.h
bspline_score.cxx bspline_score.h
bspline_stage.cxx bspline_stage.h
bspline_state.cxx bspline_state.h
bspline_regularize.cxx bspline_regularize.h
- bspline_regularize_analytic.cxx
- bspline_regularize_numeric.cxx
+ bspline_regularize_analytic.cxx bspline_regularize_analytic.h
+ bspline_regularize_numeric.cxx bspline_regularize_numeric.h
bspline_regularize_semi_analytic.cxx
- demons.cxx
- itk_align_center.cxx itk_align_center.h
- itk_demons.cxx
- itk_demons.cxx
- itk_demons_util.cxx
- itk_fsf_demons.cxx
- itk_diff_demons.cxx
- itk_log_demons.cxx
- itk_sym_log_demons.cxx
+ demons.cxx demons.h
demons_cpu.cxx
- demons_state.cxx
- gpuit_demons.cxx
- itk_optimizer.cxx
- itk_registration.cxx
- itk_registration_observer.cxx
- itk_tps.cxx
- landmark_warp.cxx
- process_parms.cxx
- rbf_cluster.cxx
- rbf_gauss.cxx
- rbf_wendland.cxx
+ demons_opencl_p.h
+ demons_state.cxx demons_state.h
+ gpuit_demons.cxx gpuit_demons.h
+ groupwise_parms.cxx groupwise_parms.h
+ histogram.cxx histogram.h
+ itk_align_center.cxx itk_align_center.h
+ itk_demons.cxx itk_demons.h
+ itk_demons_registration_filter.h
+ itk_demons_util.cxx itk_demons_util.h
+ itk_diff_demons.cxx itk_diff_demons.h
+ itk_fsf_demons.cxx itk_fsf_demons.h
+ itk_log_demons.cxx itk_log_demons.h
+ itk_sym_log_demons.cxx itk_sym_log_demons.h
+ itk_optimizer.cxx itk_optimizer.h
+ itk_registration.cxx itk_registration.h
+ itk_registration_observer.cxx itk_registration_private.h
+ itk_sym_log_demons.h
+ itk_tps.cxx itk_tps.h
+ joint_histogram.cxx joint_histogram.h
+ landmark_warp.cxx landmark_warp.h
+ metric_parms.cxx metric_parms.h
+ metric_state.cxx metric_state.h
+ process_parms.cxx process_parms.h
+ rbf_cluster.cxx rbf_cluster.h
+ rbf_gauss.cxx rbf_gauss.h
+ rbf_wendland.cxx rbf_wendland.h
registration.cxx registration.h
- registration_data.cxx
- registration_metric_type.cxx registration_metric_type.h
+ registration_data.cxx registration_data.h
registration_parms.cxx registration_parms.h
registration_resample.cxx registration_resample.h
- shared_parms.cxx
- stage_parms.cxx
+ registration_similarity_data.h
+ registration_util.cxx registration_util.h
+ shared_parms.cxx shared_parms.h
+ similarity_metric_type.cxx similarity_metric_type.h
+ stage_parms.cxx stage_parms.h
translation_grid_search.cxx translation_grid_search.h
translation_mi.cxx translation_mi.h
translation_mse.cxx translation_mse.h
diff --git a/src/plastimatch/register/bspline.cxx b/src/plastimatch/register/bspline.cxx
index 4a52dab..7bb8093 100644
--- a/src/plastimatch/register/bspline.cxx
+++ b/src/plastimatch/register/bspline.cxx
@@ -38,7 +38,6 @@
#include "bspline_interpolate.h"
#include "bspline_landmarks.h"
#include "bspline_mi.h"
-#include "bspline_mi_hist.h"
#include "bspline_mse.h"
#include "bspline_optimize.h"
#include "bspline_parms.h"
@@ -48,6 +47,7 @@
#include "delayload.h"
#include "file_util.h"
#include "interpolate_macros.h"
+#include "joint_histogram.h"
#include "logfile.h"
#include "plm_math.h"
#include "plm_timer.h"
@@ -68,7 +68,8 @@
// Author: James Shackleford
// Data: July 30th, 2009
////////////////////////////////////////////////////////////////////////////////
-int* calc_offsets(int* tile_dims, int* cdims)
+int*
+calc_offsets (int* tile_dims, int* cdims)
{
int vox_per_tile = (tile_dims[0] * tile_dims[1] * tile_dims[2]);
int pad = 32 - (vox_per_tile % 32);
@@ -99,7 +100,8 @@ int* calc_offsets(int* tile_dims, int* cdims)
// Author: James Shackleford
// Data: July 13th, 2009
////////////////////////////////////////////////////////////////////////////////
-void find_knots (
+void
+find_knots (
plm_long* knots,
plm_long tile_num,
plm_long* rdims,
@@ -117,11 +119,6 @@ void find_knots (
tile_loc[0] = tile_num % num_tiles_x;
tile_loc[1] = ((tile_num - tile_loc[0]) / num_tiles_x) % num_tiles_y;
tile_loc[2] = ((((tile_num - tile_loc[0]) / num_tiles_x) / num_tiles_y) % num_tiles_z);
- /*
- tile_loc[0] = tile_num % rdims[0];
- tile_loc[1] = ((tile_num - tile_loc[0]) / rdims[0]) % rdims[1];
- tile_loc[2] = ((((tile_num - tile_loc[0]) / rdims[0]) / rdims[1]) % rdims[2]);
- */
// Tiles do not start on the edges of the grid, so we
// push them to the center of the control grid.
@@ -131,17 +128,17 @@ void find_knots (
// Find 64 knots' [x,y,z] coordinates
// and convert into a linear knot index
- for (k = -1; k < 3; k++)
- for (j = -1; j < 3; j++)
+ for (k = -1; k < 3; k++) {
+ for (j = -1; j < 3; j++) {
for (i = -1; i < 3; i++)
{
knots[idx++] = (cdims[0]*cdims[1]*(tile_loc[2]+k)) + (cdims[0]*(tile_loc[1]+j)) + (tile_loc[0]+i);
}
-
+ }
+ }
}
-
/* -----------------------------------------------------------------------
Debugging routines
----------------------------------------------------------------------- */
@@ -198,10 +195,10 @@ bspline_save_debug_state (
fn = parms->debug_dir + "/" + buf;
bxf->save (fn.c_str());
- if (parms->metric_type[0] == REGISTRATION_METRIC_MI_MATTES) {
+ if (bst->has_metric_type (SIMILARITY_METRIC_MI_MATTES)) {
sprintf (buf, "%02d_", parms->debug_stage);
fn = parms->debug_dir + "/" + buf;
- bst->mi_hist->dump_hist (bst->feval, fn);
+ bst->get_mi_hist()->dump_hist (bst->feval, fn);
}
}
}
@@ -297,9 +294,9 @@ bspline_condense_smetric_grad (float* cond_x, float* cond_y, float* cond_z,
for (kidx=0; kidx < bxf->num_knots; kidx++) {
for (sidx=0; sidx<64; sidx++) {
- ssd->smetric_grad[3*kidx + 0] += cond_x[64*kidx + sidx];
- ssd->smetric_grad[3*kidx + 1] += cond_y[64*kidx + sidx];
- ssd->smetric_grad[3*kidx + 2] += cond_z[64*kidx + sidx];
+ ssd->curr_smetric_grad[3*kidx + 0] += cond_x[64*kidx + sidx];
+ ssd->curr_smetric_grad[3*kidx + 1] += cond_y[64*kidx + sidx];
+ ssd->curr_smetric_grad[3*kidx + 2] += cond_z[64*kidx + sidx];
}
}
}
@@ -308,7 +305,7 @@ static void
logfile_print_score (float score)
{
if (score < 10. && score > -10.) {
- logfile_printf (" %1.8f ", score);
+ logfile_printf (" %1.7f ", score);
} else {
logfile_printf (" %9.3f ", score);
}
@@ -338,45 +335,56 @@ report_score (
}
/* Compute total time */
+ double total_smetric_time = 0;
double total_time = 0;
- std::vector<double>::const_iterator it_time = ssd->time_smetric.begin();
- while (it_time != ssd->time_smetric.end()) {
- total_time += *it_time;
- ++it_time;
+ plm_long hack_num_vox = 0;
+ std::vector<Metric_score>::const_iterator it_mr
+ = ssd->metric_record.begin();
+ while (it_mr != ssd->metric_record.end()) {
+ total_time += it_mr->time;
+ if (hack_num_vox == 0) {
+ hack_num_vox = it_mr->num_vox;
+ }
+ ++it_mr;
}
+ total_smetric_time = total_time;
total_time += ssd->time_rmetric;
/* First line, iterations, score, misc stats */
logfile_printf ("[%2d,%3d] ", bst->it, bst->feval);
- if (reg_parms->lambda > 0 || blm->num_landmarks > 0
- || parms->metric_type.size() > 1)
+ if (reg_parms->lambda > 0
+ || blm->num_landmarks > 0
+ || bst->similarity_data.size() > 1)
{
logfile_printf ("SCORE ");
} else {
- logfile_printf ("%-6s", registration_metric_type_string (
- parms->metric_type[0]));
+ logfile_printf ("%-6s",
+ bst->similarity_data.front()->metric_string());
}
- logfile_print_score (ssd->score);
+ logfile_print_score (ssd->total_score);
logfile_printf (
"NV %6d GM %9.3f GN %9.3g [ %9.3f s ]\n",
- ssd->num_vox, ssd_grad_mean, sqrt (ssd_grad_norm), total_time);
+ hack_num_vox, ssd_grad_mean, sqrt (ssd_grad_norm), total_time);
/* Second line */
- if (reg_parms->lambda > 0 || blm->num_landmarks > 0
- || parms->metric_type.size() > 1)
+ if (reg_parms->lambda > 0
+ || blm->num_landmarks > 0
+ || bst->similarity_data.size() > 1)
{
logfile_printf (" ");
- /* Part 1 - smetric(s) */
- std::vector<float>::const_iterator it_sm = ssd->smetric.begin();
- std::vector<Registration_metric_type>::const_iterator it_st
- = parms->metric_type.begin();
- while (it_sm != ssd->smetric.end()) {
- logfile_printf ("%-6s",
- registration_metric_type_string (*it_st));
- logfile_print_score (*it_sm);
- ++it_sm, ++it_st;
+ /* Part 1 - smetric(s) */
+ /* GCS FIX: It should not be that one of these is a list
+ and the other is a vector. */
+ std::vector<Metric_score>::const_iterator it_mr
+ = ssd->metric_record.begin();
+ std::list<Metric_state::Pointer>::const_iterator it_st
+ = bst->similarity_data.begin();
+ while (it_mr != ssd->metric_record.end()) {
+ logfile_printf ("%-6s", (*it_st)->metric_string());
+ logfile_print_score (it_mr->score);
+ ++it_mr, ++it_st;
}
- if (ssd->smetric.size() > 1
+ if (ssd->metric_record.size() > 1
&& (reg_parms->lambda > 0 || blm->num_landmarks > 0))
{
logfile_printf ("\n");
@@ -396,7 +404,7 @@ report_score (
/* Part 4 - timing */
if (reg_parms->lambda > 0) {
logfile_printf ("[ %9.3f | %9.3f ]",
- ssd->time_smetric[0], ssd->time_rmetric);
+ total_smetric_time, ssd->time_rmetric);
}
}
logfile_printf ("\n");
@@ -416,37 +424,48 @@ bspline_score (Bspline_optimize *bod)
/* Zero out the score for this iteration */
bst->ssd.reset_score ();
- /* Compute similarity metrics */
- std::vector<Registration_metric_type>::const_iterator it_metric
- = parms->metric_type.begin();
- std::vector<float>::const_iterator it_lambda
- = parms->metric_lambda.begin();
+ /* Compute similarity metric. This is done for each metric
+ and each similarity metric within each image plane. */
+ std::list<Metric_state::Pointer>::const_iterator it_sd;
bst->sm = 0;
- while (it_metric != parms->metric_type.end()
- && it_lambda != parms->metric_lambda.end())
+ for (it_sd = bst->similarity_data.begin();
+ it_sd != bst->similarity_data.end(); ++it_sd)
{
+ bst->set_metric_state (*it_sd);
+ bst->initialize_similarity_images ();
Plm_timer timer;
timer.start ();
- bst->ssd.smetric.push_back (0.f);
- if (*it_metric == REGISTRATION_METRIC_MSE) {
+
+ switch ((*it_sd)->metric_type) {
+ case SIMILARITY_METRIC_DMAP:
+ case SIMILARITY_METRIC_MSE:
bspline_score_mse (bod);
- }
- else if (*it_metric == REGISTRATION_METRIC_MI_MATTES) {
+ break;
+ case SIMILARITY_METRIC_MI_MATTES:
bspline_score_mi (bod);
- }
- else if (*it_metric == REGISTRATION_METRIC_GM) {
+ break;
+ case SIMILARITY_METRIC_GM:
bspline_score_gm (bod);
- }
- else {
- print_and_exit ("Unknown similarity metric in bspline_score()\n");
+ break;
+ default:
+ print_and_exit (
+ "Unknown similarity metric in bspline_score()\n");
+ break;
}
- bst->ssd.accumulate_grad (*it_lambda);
-
- bst->ssd.time_smetric.push_back (timer.report ());
+ bst->ssd.metric_record.push_back (
+ Metric_score (bst->ssd.curr_smetric, timer.report (),
+ bst->ssd.curr_num_vox));
+#if defined (commentout)
+ printf (">> %f + %f * %f ->",
+ bst->ssd.total_score, (*it_sd)->metric_lambda,
+ bst->ssd.curr_smetric);
+#endif
+ bst->ssd.accumulate ((*it_sd)->metric_lambda);
+#if defined (commentout)
+ printf (" %f\n", bst->ssd.total_score);
+#endif
bst->sm ++;
- ++it_metric;
- ++it_lambda;
}
/* Compute regularization */
@@ -459,10 +478,10 @@ bspline_score (Bspline_optimize *bod)
bspline_landmarks_score (parms, bst, bxf);
}
- /* Compute total score */
- bst->ssd.score = bst->ssd.smetric[0] + reg_parms->lambda * bst->ssd.rmetric;
+ /* Update total score with regularization and landmarks */
+ bst->ssd.total_score += reg_parms->lambda * bst->ssd.rmetric;
if (blm->num_landmarks > 0) {
- bst->ssd.score += blm->landmark_stiffness * bst->ssd.lmetric;
+ bst->ssd.total_score += blm->landmark_stiffness * bst->ssd.lmetric;
}
/* Report results of this iteration */
diff --git a/src/plastimatch/register/bspline.h b/src/plastimatch/register/bspline.h
index 6c30b0f..38472cd 100644
--- a/src/plastimatch/register/bspline.h
+++ b/src/plastimatch/register/bspline.h
@@ -8,7 +8,7 @@
#include "plm_int.h"
#include <string>
-class Bspline_mi_hist_set;
+class Joint_histogram;
class Bspline_optimize;
class Bspline_parms;
class Bspline_score;
@@ -33,7 +33,6 @@ PLMREGISTER_API void bspline_save_debug_state (
Bspline_state *bst,
Bspline_xform* bxf
);
-void dump_xpm_hist (Bspline_mi_hist_set* mi_hist, char* file_base, int iter);
void bspline_condense_smetric_grad (
float* cond_x, float* cond_y, float* cond_z,
Bspline_xform* bxf,
diff --git a/src/plastimatch/register/bspline_gm.h b/src/plastimatch/register/bspline_gm.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/register/bspline_gm.txx b/src/plastimatch/register/bspline_gm.txx
index a14c55c..33d9660 100755
--- a/src/plastimatch/register/bspline_gm.txx
+++ b/src/plastimatch/register/bspline_gm.txx
@@ -15,8 +15,8 @@ public:
public:
Bspline_gm_k (Bspline_optimize *bod)
{
- Bspline_parms *parms = bod->get_bspline_parms ();
- Volume *moving_grad = parms->moving_grad;
+ Bspline_state *bst = bod->get_bspline_state ();
+ Volume *moving_grad = bst->moving_grad;
m_grad = (float*) moving_grad->img;
score_acc = 0.;
}
@@ -70,7 +70,7 @@ public:
/* Update cost function gradient */
ssd->update_smetric_grad_b (bxf, pidx, qidx, dc_dv);
- ssd->num_vox++;
+ ssd->curr_num_vox++;
}
};
diff --git a/src/plastimatch/register/bspline_loop.txx b/src/plastimatch/register/bspline_loop.txx
index 0236260..4f04de6 100755
--- a/src/plastimatch/register/bspline_loop.txx
+++ b/src/plastimatch/register/bspline_loop.txx
@@ -38,10 +38,10 @@ bspline_loop_voxel_serial (
Bspline_xform *bxf = bod->get_bspline_xform ();
Bspline_score* ssd = &bst->ssd;
- Volume *fixed = parms->fixed;
- Volume *moving = parms->moving;
- Volume *fixed_roi = parms->fixed_roi;
- Volume *moving_roi = parms->moving_roi;
+ Volume *fixed = bst->fixed;
+ Volume *moving = bst->moving;
+ Volume *fixed_roi = bst->fixed_roi;
+ Volume *moving_roi = bst->moving_roi;
plm_long fijk[3], fidx; /* Indices within fixed image (vox) */
float mijk[3]; /* Indices within moving image (vox) */
@@ -164,10 +164,10 @@ bspline_loop_tile_serial (
Bspline_xform *bxf = bod->get_bspline_xform ();
Bspline_score* ssd = &bst->ssd;
- Volume *fixed = parms->fixed;
- Volume *moving = parms->moving;
- Volume *fixed_roi = parms->fixed_roi;
- Volume *moving_roi = parms->moving_roi;
+ Volume *fixed = bst->fixed;
+ Volume *moving = bst->moving;
+ Volume *fixed_roi = bst->fixed_roi;
+ Volume *moving_roi = bst->moving_roi;
float* f_img = (float*) fixed->img;
float* m_img = (float*) moving->img;
@@ -207,8 +207,6 @@ bspline_loop_tile_serial (
// Serial across tiles
plm_long pidx;
LOOP_THRU_VOL_TILES (pidx, bxf) {
- int rc;
-
int ijk_tile[3];
plm_long q[3];
@@ -217,14 +215,9 @@ bspline_loop_tile_serial (
float mijk[3]; /* Indices within moving image (vox) */
float mxyz[3]; /* Position within moving image (mm) */
plm_long mijk_f[3], midx_f; /* Floor */
- plm_long mijk_r[3], midx_r; /* Round */
-
+ plm_long mijk_r[3]; /* Round */
float dxyz[3];
-
float li_1[3], li_2[3];
- float m_val, diff;
-
- float dc_dv[3];
float sets_x[64];
float sets_y[64];
@@ -294,7 +287,6 @@ bspline_loop_tile_serial (
// Find linear indices for moving image
midx_f = volume_index (moving->dim, mijk_f);
- midx_r = volume_index (moving->dim, mijk_r);
/* Run the target function */
bspline_loop_user.loop_function (
@@ -357,10 +349,10 @@ bspline_loop_tile_parallel (
Bspline_xform *bxf = bod->get_bspline_xform ();
Bspline_score* ssd = &bst->ssd;
- Volume *fixed = parms->fixed;
- Volume *moving = parms->moving;
- Volume *fixed_roi = parms->fixed_roi;
- Volume *moving_roi = parms->moving_roi;
+ Volume *fixed = bst->fixed;
+ Volume *moving = bst->moving;
+ Volume *fixed_roi = bst->fixed_roi;
+ Volume *moving_roi = bst->moving_roi;
float* f_img = (float*) fixed->img;
float* m_img = (float*) moving->img;
diff --git a/src/plastimatch/register/bspline_mi.cxx b/src/plastimatch/register/bspline_mi.cxx
index 5091f60..e453d8a 100644
--- a/src/plastimatch/register/bspline_mi.cxx
+++ b/src/plastimatch/register/bspline_mi.cxx
@@ -20,19 +20,18 @@
#include "bspline_macros.h"
#include "bspline_mi.h"
#include "bspline_mi.txx"
-#include "bspline_mi_hist.h"
#include "bspline_optimize.h"
#include "bspline_parms.h"
#include "bspline_state.h"
#include "file_util.h"
#include "interpolate.h"
#include "interpolate_macros.h"
+#include "joint_histogram.h"
#include "logfile.h"
#include "mha_io.h"
#include "plm_math.h"
#include "volume_macros.h"
#include "volume.h"
-#include "xpm.h"
/* Some neat debug facilities
* Will probably move these somewhere more appropriate soon
@@ -190,7 +189,7 @@ bspline_mi_hist_lookup (
long m_idxs[2], /* Output: Moving marginal indices */
long f_idxs[1], /* Output: Fixed marginal indices */
float fxs[2], /* Output: Fraction contribution at indices */
- Bspline_mi_hist_set* mi_hist, /* Input: The histogram */
+ Joint_histogram* mi_hist, /* Input: The histogram */
float f_val, /* Input: Intensity of fixed image */
float m_val /* Input: Intensity of moving image */
)
@@ -252,7 +251,7 @@ bspline_mi_hist_lookup (
based on m_val, but one bin based on f_val. */
inline void
bspline_mi_hist_add (
- Bspline_mi_hist_set* mi_hist, /* The histogram */
+ Joint_histogram* mi_hist, /* The histogram */
float f_val, /* Intensity of fixed image */
float m_val, /* Intensity of moving image */
float amt /* How much to add to histogram */
@@ -281,7 +280,7 @@ bspline_mi_hist_add (
/* This algorithm uses a un-normalized score. */
static float
-mi_hist_score_omp (Bspline_mi_hist_set* mi_hist, int num_vox)
+mi_hist_score_omp (Joint_histogram* mi_hist, int num_vox)
{
double* f_hist = mi_hist->f_hist;
double* m_hist = mi_hist->m_hist;
@@ -354,221 +353,12 @@ compute_dS_dP (
return dS_dP;
}
-void dump_xpm_hist (Bspline_mi_hist_set* mi_hist, char* file_base, int iter)
-{
- int z;
- char c;
-
- // Graph Properties
- int graph_offset_x = 10;
- int graph_offset_y = 10;
- int graph_padding = 20;
- int graph_bar_height = 100;
- int graph_bar_width = 5;
- int graph_bar_spacing = (int)((float)graph_bar_width * (7.0/5.0));
- plm_long graph_color_levels = 22;
-
- // int fixed_bar_height; // max bar height (pixels)
- // int moving_bar_height;
- plm_long joint_color;
-
- float fixed_scale; // pixels per amt
- float moving_scale;
- float joint_scale;
-
- float moving_max_val=0;
- float fixed_max_val=0;
- float joint_max_val=0;
-
- int fixed_total_width = mi_hist->fixed.bins * graph_bar_spacing;
- int moving_total_width = mi_hist->moving.bins * graph_bar_spacing;
-
- int graph_moving_x_pos = graph_offset_x + graph_bar_height + graph_padding;
- int graph_moving_y_pos = graph_offset_y + fixed_total_width + graph_padding + graph_bar_height;
-
- int graph_fixed_x_pos = graph_offset_x;
- int graph_fixed_y_pos = graph_offset_y + fixed_total_width;
-
- int border_padding = 5;
- int border_width = moving_total_width + 2*border_padding;
- int border_height = fixed_total_width + 2*border_padding;
- int border_x_pos = graph_moving_x_pos - border_padding;
- int border_y_pos = graph_offset_y - border_padding + (int)((float)graph_bar_width * (2.0/5.0));
-
- int canvas_width = 2*graph_offset_x + graph_bar_height + moving_total_width + graph_padding;
- int canvas_height = 2*graph_offset_y + graph_bar_height + fixed_total_width + graph_padding;
-
- double *m_hist = mi_hist->m_hist;
- double *f_hist = mi_hist->f_hist;
- double *j_hist = mi_hist->j_hist;
-
- char filename[20];
-
- sprintf(filename, "%s_%04i.xpm", file_base, iter);
-
- // ----------------------------------------------
- // Find max value for fixed
- for(plm_long i=0; i<mi_hist->fixed.bins; i++)
- if (f_hist[i] > fixed_max_val)
- fixed_max_val = f_hist[i];
-
- // Find max value for moving
- for(plm_long i=0; i<mi_hist->moving.bins; i++)
- if (m_hist[i] > moving_max_val)
- moving_max_val = m_hist[i];
-
- // Find max value for joint
- // (Ignoring bin 0)
- for(plm_long j=0; j<mi_hist->fixed.bins; j++) {
- for(plm_long i=0; i<mi_hist->moving.bins; i++) {
- if ( (i > 0) && (j > 1) )
- if (j_hist[j*mi_hist->moving.bins + i] > joint_max_val)
- joint_max_val = j_hist[j*mi_hist->moving.bins + i];
- }
- }
-
-
- // Generate scaling factors
- fixed_scale = (float)graph_bar_height / fixed_max_val;
- moving_scale = (float)graph_bar_height / moving_max_val;
- joint_scale = (float)graph_color_levels / joint_max_val;
- // ----------------------------------------------
-
-
-
- // ----------------------------------------------
- // Pull out a canvas and brush!
- Xpm_canvas* xpm = new Xpm_canvas (canvas_width, canvas_height, 1);
- Xpm_brush* brush = new Xpm_brush;
-
- // setup the palette
- xpm->add_color ('a', 0xFFFFFF); // white
- xpm->add_color ('b', 0x000000); // black
- xpm->add_color ('z', 0xFFCC00); // orange
-
- // generate a nice BLUE->RED gradient
- c = 'c';
- z = 0x0000FF;
- for (plm_long i=0; i<(graph_color_levels+1); i++)
- {
- xpm->add_color (c, z);
-
- z -= 0x00000B; // BLUE--
- z += 0x0B0000; // RED++
-
- c = (char)((int)c + 1); // LETTER++
- }
-
- // Prime the XPM Canvas
- xpm->prime ('a');
- // ----------------------------------------------
-
-
- printf("Drawing Histograms... ");
-
-
- /* Generate Moving Histogram */
- brush->set_type (XPM_BOX);
- brush->set_color ('b');
- brush->set_pos (graph_moving_x_pos, graph_moving_y_pos);
- brush->set_width (graph_bar_width);
- brush->set_height (0);
-
- int tmp_h;
- for(plm_long i=0; i<mi_hist->moving.bins; i++)
- {
- tmp_h = (int)(m_hist[i] * moving_scale);
- brush->set_height (tmp_h);
- brush->set_y (graph_moving_y_pos - tmp_h);
- xpm->draw (brush);
- brush->inc_x (graph_bar_spacing);
- }
-
-
- /* Generate Fixed Histogram */
- brush->set_type (XPM_BOX);
- brush->set_color ('b');
- brush->set_pos (graph_fixed_x_pos, graph_fixed_y_pos);
- brush->set_width (0);
- brush->set_height (graph_bar_width);
-
- for (plm_long i=0; i<mi_hist->fixed.bins; i++)
- {
- brush->set_width ((int)(f_hist[i] * fixed_scale));
- xpm->draw (brush);
- brush->inc_x ((-1)*graph_bar_spacing);
- }
-
-
- /* Generate Joint Histogram */
- brush->set_type (XPM_BOX);
- brush->set_color ('b');
- brush->set_pos (graph_moving_x_pos, graph_fixed_y_pos);
- brush->set_width (graph_bar_width);
- brush->set_height (graph_bar_width);
-
- z = 0;
- for(plm_long j=0; j<mi_hist->fixed.bins; j++) {
- for(plm_long i=0; i<mi_hist->moving.bins; i++) {
- joint_color = (size_t)(j_hist[z++] * joint_scale);
- if (joint_color > 0) {
- // special handling for bin 0
- if (joint_color > graph_color_levels) {
- // printf ("Clamp @ P(%i,%i)\n", i, j);
- // brush.color = (char)(graph_color_levels + 99);
- brush->set_color ('z');
- } else {
- brush->set_color ((char)(joint_color + 99));
- }
- } else {
- brush->set_color ('a');
- }
- xpm->draw (brush);
- brush->inc_x (graph_bar_spacing);
- }
- // get ready to render new row
- brush->set_x (graph_moving_x_pos);
- brush->inc_y ((-1)*graph_bar_spacing);
- }
-
- /* Generate Joint Histogram Border */
- brush->set_type (XPM_BOX); // top
- brush->set_color ('b');
- brush->set_pos (border_x_pos, border_y_pos);
- brush->set_width (border_width);
- brush->set_height (1);
- xpm->draw (brush);
-
- brush->set_width (1); // left
- brush->set_height (border_height);
- xpm->draw (brush);
-
- brush->set_width (border_width); // bottom
- brush->set_height (1);
- brush->inc_y (border_height);
- xpm->draw (brush);
-
- brush->set_width (1); // right
- brush->set_height (border_height);
- brush->set_pos (border_width, border_y_pos);
- xpm->draw (brush);
-
- printf("done.\n");
-
- // Write to file
- xpm->write (filename);
-
- delete xpm;
- delete brush;
-}
-
-
/* Use 1 histogram per thread so we are
* thread safe when employing multi-core */
#if (OPENMP_FOUND)
static inline void
bspline_mi_hist_add_pvi_8_omp_v2 (
- Bspline_mi_hist_set* mi_hist,
+ Joint_histogram* mi_hist,
double* f_hist_omp,
double* m_hist_omp,
double* j_hist_omp,
@@ -643,7 +433,7 @@ bspline_mi_hist_add_pvi_8_omp_v2 (
#if (OPENMP_FOUND)
static inline void
bspline_mi_hist_add_pvi_8_omp_crits (
- Bspline_mi_hist_set* mi_hist,
+ Joint_histogram* mi_hist,
Volume *fixed,
Volume *moving,
int fidx,
@@ -723,7 +513,7 @@ bspline_mi_hist_add_pvi_8_omp_crits (
#if (OPENMP_FOUND)
static inline void
bspline_mi_hist_add_pvi_8_omp (
- Bspline_mi_hist_set* mi_hist,
+ Joint_histogram* mi_hist,
Volume *fixed,
Volume *moving,
int fidx,
@@ -806,7 +596,7 @@ bspline_mi_hist_add_pvi_8_omp (
#if defined (commentout)
static inline void
bspline_mi_hist_add_pvi_6 (
- Bspline_mi_hist_set* mi_hist,
+ Joint_histogram* mi_hist,
Volume *fixed,
Volume *moving,
int fidx,
@@ -891,7 +681,7 @@ bspline_mi_hist_add_pvi_6 (
static inline void
bspline_mi_pvi_8_dc_dv (
float dc_dv[3], /* Output */
- Bspline_mi_hist_set* mi_hist, /* Input */
+ Joint_histogram* mi_hist, /* Input */
Bspline_state *bst, /* Input */
Volume *fixed, /* Input */
Volume *moving, /* Input */
@@ -980,7 +770,7 @@ bspline_mi_pvi_8_dc_dv (
idx_jbin = offset_fbin + idx_mbin;
if (j_hist[idx_jbin] > 0.0001) {
dS_dP = logf((num_vox_f * j_hist[idx_jbin])
- / (f_hist[idx_fbin] * m_hist[idx_mbin])) - ssd->smetric[0];
+ / (f_hist[idx_fbin] * m_hist[idx_mbin])) - ssd->curr_smetric;
dc_dv[0] -= dw[3*idx_pv+0] * dS_dP;
dc_dv[1] -= dw[3*idx_pv+1] * dS_dP;
dc_dv[2] -= dw[3*idx_pv+2] * dS_dP;
@@ -1006,7 +796,7 @@ bspline_mi_pvi_8_dc_dv (
static inline void
bspline_mi_pvi_6_dc_dv (
float dc_dv[3], /* Output */
- Bspline_mi_hist_set* mi_hist, /* Input */
+ Joint_histogram* mi_hist, /* Input */
Bspline_state *bst, /* Input */
Volume *fixed, /* Input */
Volume *moving, /* Input */
@@ -1042,7 +832,7 @@ bspline_mi_pvi_6_dc_dv (
mkqs, fzqs);
/* PARTIAL VALUE INTERPOLATION - 6 neighborhood */
- float smetric = ssd->smetric[0];
+ float smetric = ssd->curr_smetric;
midx_f = (mkqs[1] * moving->dim[1] + mjqs[1]) * moving->dim[0] + miqs[1];
bspline_mi_hist_lookup (j_idxs, m_idxs, f_idxs, fxs,
mi_hist, f_img[fidx], m_img[midx_f]);
@@ -1121,11 +911,11 @@ bspline_score_i_mi (
Bspline_state *bst = bod->get_bspline_state ();
Bspline_xform *bxf = bod->get_bspline_xform ();
- Volume *fixed = parms->fixed;
- Volume *moving = parms->moving;
+ Volume *fixed = bst->fixed;
+ Volume *moving = bst->moving;
Bspline_score* ssd = &bst->ssd;
- Bspline_mi_hist_set* mi_hist = bst->mi_hist;
+ Joint_histogram* mi_hist = bst->get_mi_hist();
long pidx;
float num_vox_f;
@@ -1256,14 +1046,14 @@ bspline_score_i_mi (
if (f_hist[i] > f_hist[mi_hist->fixed.big_bin]) {
mi_hist->fixed.big_bin = i;
}
- ssd->num_vox += f_hist[i];
+ ssd->curr_num_vox += f_hist[i];
}
/* Fill in the missing histogram bin */
for (plm_long i=0; i<mi_hist->moving.bins; i++) {
mhis += m_hist[i];
}
- m_hist[mi_hist->moving.big_bin] = (double)ssd->num_vox - mhis;
+ m_hist[mi_hist->moving.big_bin] = (double) ssd->curr_num_vox - mhis;
/* Look for the biggest moving histogram bin */
@@ -1282,7 +1072,7 @@ bspline_score_i_mi (
jhis += j_hist[j*mi_hist->moving.bins + i];
}
}
- j_hist[mi_hist->joint.big_bin] = (double)ssd->num_vox - jhis;
+ j_hist[mi_hist->joint.big_bin] = (double) ssd->curr_num_vox - jhis;
/* Look for the biggest joint histogram bin */
@@ -1324,8 +1114,8 @@ bspline_score_i_mi (
}
/* Compute score */
- ssd->smetric[0] = mi_hist_score_omp (mi_hist, ssd->num_vox);
- num_vox_f = (float) ssd->num_vox;
+ ssd->curr_smetric = mi_hist_score_omp (mi_hist, ssd->curr_num_vox);
+ num_vox_f = (float) ssd->curr_num_vox;
/* PASS 2 - Compute Gradient (Parallel across tiles) */
#pragma omp parallel for
@@ -1424,7 +1214,7 @@ bspline_score_i_mi (
}
#endif
- mse_score = mse_score / ssd->num_vox;
+ mse_score = mse_score / ssd->curr_num_vox;
}
#endif
@@ -1445,11 +1235,11 @@ bspline_score_h_mi (
Bspline_state *bst = bod->get_bspline_state ();
Bspline_xform *bxf = bod->get_bspline_xform ();
- Volume *fixed = parms->fixed;
- Volume *moving = parms->moving;
+ Volume *fixed = bst->fixed;
+ Volume *moving = bst->moving;
Bspline_score* ssd = &bst->ssd;
- Bspline_mi_hist_set* mi_hist = bst->mi_hist;
+ Joint_histogram* mi_hist = bst->get_mi_hist();
float diff;
float* f_img = (float*) fixed->img;
float* m_img = (float*) moving->img;
@@ -1480,8 +1270,8 @@ bspline_score_h_mi (
float* cond_y = (float*)malloc(cond_size);
float* cond_z = (float*)malloc(cond_size);
- Volume* fixed_roi = parms->fixed_roi;
- Volume* moving_roi = parms->moving_roi;
+ Volume* fixed_roi = bst->fixed_roi;
+ Volume* moving_roi = bst->moving_roi;
#if 0
Volume* dbg_vol = volume_clone_empty (moving);
@@ -1563,7 +1353,7 @@ bspline_score_h_mi (
/* Compute intensity difference */
diff = m_val - f_img[fidx];
mse_score += diff * diff;
- ssd->num_vox ++;
+ ssd->curr_num_vox ++;
} /* LOOP_THRU_ROI_X */
} /* LOOP_THRU_ROI_Y */
@@ -1580,8 +1370,8 @@ bspline_score_h_mi (
}
/* Compute score */
- ssd->smetric[0] = mi_hist_score_omp (mi_hist, ssd->num_vox);
- num_vox_f = (float) ssd->num_vox;
+ ssd->curr_smetric = mi_hist_score_omp (mi_hist, ssd->curr_num_vox);
+ num_vox_f = (float) ssd->curr_num_vox;
/* PASS 2 - Compute Gradient (Parallel across tiles) */
#pragma omp parallel for
@@ -1696,7 +1486,7 @@ bspline_score_h_mi (
fclose (fp);
}
- mse_score = mse_score / ssd->num_vox;
+ mse_score = mse_score / ssd->curr_num_vox;
if (parms->debug) {
printf ("<< MSE %3.3f >>\n", mse_score);
}
@@ -1718,11 +1508,11 @@ bspline_score_g_mi (
Bspline_state *bst = bod->get_bspline_state ();
Bspline_xform *bxf = bod->get_bspline_xform ();
- Volume *fixed = parms->fixed;
- Volume *moving = parms->moving;
+ Volume *fixed = bst->fixed;
+ Volume *moving = bst->moving;
Bspline_score* ssd = &bst->ssd;
- Bspline_mi_hist_set* mi_hist = bst->mi_hist;
+ Joint_histogram* mi_hist = bst->get_mi_hist();
float diff;
float* f_img = (float*) fixed->img;
float* m_img = (float*) moving->img;
@@ -1815,7 +1605,7 @@ bspline_score_g_mi (
/* Compute intensity difference */
diff = m_val - f_img[fidx];
mse_score += diff * diff;
- ssd->num_vox ++;
+ ssd->curr_num_vox ++;
} /* LOOP_THRU_ROI_X */
} /* LOOP_THRU_ROI_Y */
@@ -1827,8 +1617,8 @@ bspline_score_g_mi (
}
/* Compute score */
- ssd->smetric[0] = mi_hist_score_omp (mi_hist, ssd->num_vox);
- num_vox_f = (float) ssd->num_vox;
+ ssd->curr_smetric = mi_hist_score_omp (mi_hist, ssd->curr_num_vox);
+ num_vox_f = (float) ssd->curr_num_vox;
/* PASS 2 - Compute Gradient (Parallel across tiles) */
#pragma omp parallel for
@@ -1937,7 +1727,7 @@ bspline_score_g_mi (
}
#endif
- mse_score = mse_score / ssd->num_vox;
+ mse_score = mse_score / ssd->curr_num_vox;
if (parms->debug) {
printf ("<< MSE %3.3f >>\n", mse_score);
}
@@ -1966,11 +1756,11 @@ bspline_score_f_mi (
Bspline_state *bst = bod->get_bspline_state ();
Bspline_xform *bxf = bod->get_bspline_xform ();
- Volume *fixed = parms->fixed;
- Volume *moving = parms->moving;
+ Volume *fixed = bst->fixed;
+ Volume *moving = bst->moving;
Bspline_score* ssd = &bst->ssd;
- Bspline_mi_hist_set* mi_hist = bst->mi_hist;
+ Joint_histogram* mi_hist = bst->get_mi_hist();
int pidx;
float num_vox_f;
@@ -2072,14 +1862,14 @@ bspline_score_f_mi (
if (f_hist[i] > f_hist[mi_hist->fixed.big_bin]) {
mi_hist->fixed.big_bin = i;
}
- ssd->num_vox += f_hist[i];
+ ssd->curr_num_vox += f_hist[i];
}
/* Fill in the missing histogram bin */
for(plm_long i=0; i<mi_hist->moving.bins; i++) {
mhis += m_hist[i];
}
- m_hist[mi_hist->moving.big_bin] = (double)ssd->num_vox - mhis;
+ m_hist[mi_hist->moving.big_bin] = (double) ssd->curr_num_vox - mhis;
/* Look for the biggest moving histogram bin */
@@ -2096,7 +1886,7 @@ bspline_score_f_mi (
jhis += j_hist[j*mi_hist->moving.bins + i];
}
}
- j_hist[mi_hist->joint.big_bin] = (double)ssd->num_vox - jhis;
+ j_hist[mi_hist->joint.big_bin] = (double) ssd->curr_num_vox - jhis;
/* Look for the biggest joint histogram bin */
@@ -2134,8 +1924,8 @@ bspline_score_f_mi (
}
/* Compute score */
- ssd->smetric[0] = mi_hist_score_omp (mi_hist, ssd->num_vox);
- num_vox_f = (float) ssd->num_vox;
+ ssd->curr_smetric = mi_hist_score_omp (mi_hist, ssd->curr_num_vox);
+ num_vox_f = (float) ssd->curr_num_vox;
/* PASS 2 - Compute Gradient (Parallel across tiles) */
#pragma omp parallel for
@@ -2234,7 +2024,7 @@ bspline_score_f_mi (
}
#endif
- mse_score = mse_score / ssd->num_vox;
+ mse_score = mse_score / ssd->curr_num_vox;
}
#endif
@@ -2258,11 +2048,11 @@ bspline_score_e_mi (
Bspline_state *bst = bod->get_bspline_state ();
Bspline_xform *bxf = bod->get_bspline_xform ();
- Volume *fixed = parms->fixed;
- Volume *moving = parms->moving;
+ Volume *fixed = bst->fixed;
+ Volume *moving = bst->moving;
Bspline_score* ssd = &bst->ssd;
- Bspline_mi_hist_set* mi_hist = bst->mi_hist;
+ Joint_histogram* mi_hist = bst->get_mi_hist();
long pidx;
float num_vox_f;
@@ -2389,14 +2179,14 @@ bspline_score_e_mi (
if (f_hist[i] > f_hist[mi_hist->fixed.big_bin]) {
mi_hist->fixed.big_bin = i;
}
- ssd->num_vox += f_hist[i];
+ ssd->curr_num_vox += f_hist[i];
}
/* Fill in the missing histogram bin */
for (plm_long i=0; i<mi_hist->moving.bins; i++) {
mhis += m_hist[i];
}
- m_hist[mi_hist->moving.big_bin] = (double)ssd->num_vox - mhis;
+ m_hist[mi_hist->moving.big_bin] = (double) ssd->curr_num_vox - mhis;
/* Look for the biggest moving histogram bin */
@@ -2415,7 +2205,7 @@ bspline_score_e_mi (
jhis += j_hist[j*mi_hist->moving.bins + i];
}
}
- j_hist[mi_hist->joint.big_bin] = (double)ssd->num_vox - jhis;
+ j_hist[mi_hist->joint.big_bin] = (double) ssd->curr_num_vox - jhis;
/* Look for the biggest joint histogram bin */
@@ -2457,8 +2247,8 @@ bspline_score_e_mi (
}
/* Compute score */
- ssd->smetric[0] = mi_hist_score_omp (mi_hist, ssd->num_vox);
- num_vox_f = (float) ssd->num_vox;
+ ssd->curr_smetric = mi_hist_score_omp (mi_hist, ssd->curr_num_vox);
+ num_vox_f = (float) ssd->curr_num_vox;
/* PASS 2 - Compute Gradient (Parallel across tiles) */
#pragma omp parallel for
@@ -2573,7 +2363,7 @@ bspline_score_e_mi (
}
#endif
- mse_score = mse_score / ssd->num_vox;
+ mse_score = mse_score / ssd->curr_num_vox;
}
#endif
@@ -2593,11 +2383,11 @@ bspline_score_d_mi (
Bspline_state *bst = bod->get_bspline_state ();
Bspline_xform *bxf = bod->get_bspline_xform ();
- Volume *fixed = parms->fixed;
- Volume *moving = parms->moving;
+ Volume *fixed = bst->fixed;
+ Volume *moving = bst->moving;
Bspline_score* ssd = &bst->ssd;
- Bspline_mi_hist_set* mi_hist = bst->mi_hist;
+ Joint_histogram* mi_hist = bst->get_mi_hist();
plm_long rijk[3];
float diff;
float* f_img = (float*) fixed->img;
@@ -2714,7 +2504,7 @@ bspline_score_d_mi (
/* Compute intensity difference */
diff = m_val - f_img[fidx];
mse_score += diff * diff;
- ssd->num_vox ++;
+ ssd->curr_num_vox ++;
} /* LOOP_THRU_ROI_X */
} /* LOOP_THRU_ROI_Y */
@@ -2747,8 +2537,8 @@ bspline_score_d_mi (
}
/* Compute score */
- ssd->smetric[0] = mi_hist_score_omp (mi_hist, ssd->num_vox);
- num_vox_f = (float) ssd->num_vox;
+ ssd->curr_smetric = mi_hist_score_omp (mi_hist, ssd->curr_num_vox);
+ num_vox_f = (float) ssd->curr_num_vox;
/* PASS 2 - Compute Gradient (Parallel across tiles) */
#pragma omp parallel for
@@ -2857,7 +2647,7 @@ bspline_score_d_mi (
}
#endif
- mse_score = mse_score / ssd->num_vox;
+ mse_score = mse_score / ssd->curr_num_vox;
if (parms->debug) {
printf ("<< MSE %3.3f >>\n", mse_score);
}
@@ -2873,13 +2663,13 @@ bspline_score_c_mi (
Bspline_state *bst = bod->get_bspline_state ();
Bspline_xform *bxf = bod->get_bspline_xform ();
- Volume *fixed = parms->fixed;
- Volume *moving = parms->moving;
- Volume* fixed_roi = parms->fixed_roi;
- Volume* moving_roi = parms->moving_roi;
+ Volume *fixed = bst->fixed;
+ Volume *moving = bst->moving;
+ Volume *fixed_roi = bst->fixed_roi;
+ Volume *moving_roi = bst->moving_roi;
Bspline_score* ssd = &bst->ssd;
- Bspline_mi_hist_set* mi_hist = bst->mi_hist;
+ Joint_histogram* mi_hist = bst->get_mi_hist();
//plm_long rijk[3];
plm_long fijk[3], fidx;
float mijk[3];
@@ -2985,7 +2775,7 @@ bspline_score_c_mi (
/* Compute intensity difference */
diff = m_val - f_img[fidx];
mse_score += diff * diff;
- ssd->num_vox++;
+ ssd->curr_num_vox++;
} /* LOOP_THRU_ROI_X */
} /* LOOP_THRU_ROI_Y */
@@ -3019,8 +2809,8 @@ bspline_score_c_mi (
}
/* Compute score */
- ssd->smetric[0] = mi_hist->compute_score (ssd->num_vox);
- num_vox_f = (float) ssd->num_vox;
+ ssd->curr_smetric = mi_hist->compute_score (ssd->curr_num_vox);
+ num_vox_f = (float) ssd->curr_num_vox;
/* PASS 2 - Compute gradient */
LOOP_Z (fijk, fxyz, fixed) {
@@ -3095,7 +2885,7 @@ bspline_score_c_mi (
}
#endif
- mse_score = mse_score / ssd->num_vox;
+ mse_score = mse_score / ssd->curr_num_vox;
}
/* Mutual information version of implementation "k" */
@@ -3107,7 +2897,7 @@ bspline_score_k_mi (
Bspline_parms *parms = bod->get_bspline_parms ();
Bspline_state *bst = bod->get_bspline_state ();
Bspline_score* ssd = &bst->ssd;
- Bspline_mi_hist_set* mi_hist = bst->mi_hist;
+ Joint_histogram* mi_hist = bst->get_mi_hist();
double* f_hist = mi_hist->f_hist;
double* m_hist = mi_hist->m_hist;
@@ -3150,7 +2940,7 @@ bspline_score_k_mi (
}
/* Compute score */
- ssd->smetric[0] = mi_hist->compute_score (ssd->num_vox);
+ ssd->curr_smetric = mi_hist->compute_score (ssd->curr_num_vox);
/* Create/initialize bspline_loop_user (PASS 2) */
Bspline_mi_k_pass_2 blu2 (bod);
@@ -3169,7 +2959,7 @@ bspline_score_l_mi (
Bspline_parms *parms = bod->get_bspline_parms ();
Bspline_state *bst = bod->get_bspline_state ();
Bspline_score* ssd = &bst->ssd;
- Bspline_mi_hist_set* mi_hist = bst->mi_hist;
+ Joint_histogram* mi_hist = bst->get_mi_hist();
double* f_hist = mi_hist->f_hist;
double* m_hist = mi_hist->m_hist;
@@ -3212,7 +3002,7 @@ bspline_score_l_mi (
}
/* Compute score */
- ssd->smetric[bst->sm] = mi_hist->compute_score (ssd->num_vox);
+ ssd->curr_smetric = mi_hist->compute_score (ssd->curr_num_vox);
/* Create/initialize bspline_loop_user (PASS 2) */
Bspline_mi_k_pass_2 blu2 (bod);
@@ -3228,9 +3018,10 @@ bspline_score_mi (
)
{
Bspline_parms *parms = bod->get_bspline_parms ();
+ Bspline_state *bst = bod->get_bspline_state ();
- Volume* fixed_roi = parms->fixed_roi;
- Volume* moving_roi = parms->moving_roi;
+ Volume* fixed_roi = bst->fixed_roi;
+ Volume* moving_roi = bst->moving_roi;
bool have_roi = fixed_roi || moving_roi;
bool have_histogram_minmax_val =
(parms->mi_fixed_image_minVal!=0)
diff --git a/src/plastimatch/register/bspline_mi.h b/src/plastimatch/register/bspline_mi.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/register/bspline_mi.txx b/src/plastimatch/register/bspline_mi.txx
index b0f4d58..3f64ed1 100755
--- a/src/plastimatch/register/bspline_mi.txx
+++ b/src/plastimatch/register/bspline_mi.txx
@@ -9,7 +9,7 @@
static inline void
bspline_mi_pvi_8_dc_dv_dcos (
float dc_dv[3], /* Output */
- Bspline_mi_hist_set* mi_hist, /* Input */
+ Joint_histogram* mi_hist, /* Input */
Bspline_state *bst, /* Input */
const Volume *fixed, /* Input */
const Volume *moving, /* Input */
@@ -94,7 +94,7 @@ bspline_mi_pvi_8_dc_dv_dcos (
}
idx_jbin = offset_fbin + idx_mbin;
if (j_hist[idx_jbin] > 0.0001) {
- dS_dP = logf((num_vox_f * j_hist[idx_jbin]) / (f_hist[idx_fbin] * m_hist[idx_mbin])) - ssd->smetric[0];
+ dS_dP = logf((num_vox_f * j_hist[idx_jbin]) / (f_hist[idx_fbin] * m_hist[idx_mbin])) - ssd->curr_smetric;
dc_dv[0] -= dw[3*idx_pv+0] * dS_dP;
dc_dv[1] -= dw[3*idx_pv+1] * dS_dP;
dc_dv[2] -= dw[3*idx_pv+2] * dS_dP;
@@ -123,12 +123,12 @@ class Bspline_mi_k_pass_1
{
public:
double score_acc;
- Bspline_mi_hist_set *mi_hist;
+ Joint_histogram *mi_hist;
public:
Bspline_mi_k_pass_1 (Bspline_optimize *bod) {
score_acc = 0.f;
}
- void set_mi_hist (Bspline_mi_hist_set *mi_hist) {
+ void set_mi_hist (Joint_histogram *mi_hist) {
this->mi_hist = mi_hist;
}
public:
@@ -168,7 +168,7 @@ public:
);
/* Keep track of voxels used */
- ssd->num_vox++;
+ ssd->curr_num_vox++;
}
};
@@ -176,13 +176,13 @@ class Bspline_mi_k_pass_2
{
public:
float num_vox_f;
- Bspline_mi_hist_set *mi_hist;
+ Joint_histogram *mi_hist;
public:
Bspline_mi_k_pass_2 (Bspline_optimize *bod) {
Bspline_score* ssd = bod->get_bspline_state()->get_bspline_score();
- num_vox_f = (float) ssd->num_vox;
+ num_vox_f = (float) ssd->curr_num_vox;
}
- void set_mi_hist (Bspline_mi_hist_set *mi_hist) {
+ void set_mi_hist (Joint_histogram *mi_hist) {
this->mi_hist = mi_hist;
}
public:
diff --git a/src/plastimatch/register/bspline_mi_hist.h b/src/plastimatch/register/bspline_mi_hist.h
deleted file mode 100755
index 2f0e833..0000000
--- a/src/plastimatch/register/bspline_mi_hist.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* -----------------------------------------------------------------------
- See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
- ----------------------------------------------------------------------- */
-#ifndef _bspline_mi_hist_h_
-#define _bspline_mi_hist_h_
-
-#include "plmregister_config.h"
-#include <string>
-#include "plm_int.h"
-
-/* Maximum # of bins for a vopt histogram */
-#define VOPT_RES 1000
-
-class Volume;
-
-/* -----------------------------------------------------------------------
- Types
- ----------------------------------------------------------------------- */
-enum Mi_hist_type {
- HIST_EQSP,
- HIST_VOPT
-};
-
-class PLMREGISTER_API Bspline_mi_hist {
-public:
- Bspline_mi_hist (
- Mi_hist_type type = HIST_EQSP,
- plm_long bins = 32);
- ~Bspline_mi_hist ();
-public:
- /* Used by all histogram types */
- enum Mi_hist_type type; /* Type of histograms */
- plm_long bins; /* # of bins in histogram */
- float offset; /* minimum voxel intensity */
- plm_long big_bin; /* fullest bin index */
- float delta; /* bin OR key spacing */
-
- /* For V-Optimal Histograms */
- plm_long keys; /* # of keys */
- int* key_lut; /* bin keys lookup table */
-};
-
-class PLMREGISTER_API Bspline_mi_hist_set {
-public:
- Bspline_mi_hist_set ();
- Bspline_mi_hist_set (
- Mi_hist_type type,
- plm_long fixed_bins,
- plm_long moving_bins);
- ~Bspline_mi_hist_set ();
-public:
- void initialize (Volume *fixed, Volume *moving);
- void reset_histograms ();
- void dump_hist (int it, const std::string& prefix);
-
- void add_pvi_8 (
- const Volume *fixed,
- const Volume *moving,
- int fidx,
- int mvf,
- float li_1[3], /* Fraction of interpolant in lower index */
- float li_2[3]); /* Fraction of interpolant in upper index */
-
- float compute_score (int num_vox);
-
-public:
- Bspline_mi_hist moving;
- Bspline_mi_hist fixed;
- Bspline_mi_hist joint; // JAS: for big_bin
- double* m_hist;
- double* f_hist;
- double* j_hist;
-protected:
- void allocate ();
-};
-
-#endif
diff --git a/src/plastimatch/register/bspline_mse.cxx b/src/plastimatch/register/bspline_mse.cxx
index b976b2d..210dbb8 100644
--- a/src/plastimatch/register/bspline_mse.cxx
+++ b/src/plastimatch/register/bspline_mse.cxx
@@ -55,15 +55,16 @@ bspline_score_normalize (
to exit prematurely.
However, the best score is not currently stored in the state.
*/
- if (ssd->num_vox < MIN_VOX) {
- ssd->smetric[bst->sm] = FLT_MAX;
+ if (ssd->curr_num_vox < MIN_VOX) {
+ ssd->curr_smetric = FLT_MAX;
for (int i = 0; i < bxf->num_coeff; i++) {
- ssd->smetric_grad[i] = 0;
+ ssd->curr_smetric_grad[i] = 0;
}
} else {
- ssd->smetric[bst->sm] = raw_score / ssd->num_vox;
+ ssd->curr_smetric = raw_score / ssd->curr_num_vox;
for (int i = 0; i < bxf->num_coeff; i++) {
- ssd->smetric_grad[i] = 2 * ssd->smetric_grad[i] / ssd->num_vox;
+ ssd->curr_smetric_grad[i]
+ = 2 * ssd->curr_smetric_grad[i] / ssd->curr_num_vox;
}
}
}
@@ -84,9 +85,9 @@ bspline_score_i_mse (
Bspline_state *bst = bod->get_bspline_state ();
Bspline_xform *bxf = bod->get_bspline_xform ();
- Volume *fixed = parms->fixed;
- Volume *moving = parms->moving;
- Volume *moving_grad = parms->moving_grad;
+ Volume *fixed = bst->fixed;
+ Volume *moving = bst->moving;
+ Volume *moving_grad = bst->moving_grad;
Bspline_score* ssd = &bst->ssd;
double score_tile;
@@ -102,8 +103,8 @@ bspline_score_i_mse (
float* cond_y = (float*)malloc(cond_size);
float* cond_z = (float*)malloc(cond_size);
- Volume* fixed_roi = parms->fixed_roi;
- Volume* moving_roi = parms->moving_roi;
+ Volume* fixed_roi = bst->fixed_roi;
+ Volume* moving_roi = bst->moving_roi;
static int it = 0;
@@ -270,7 +271,7 @@ bspline_score_i_mse (
} /* LOOP_THRU_VOL_TILES */
- ssd->num_vox = num_vox;
+ ssd->curr_num_vox = num_vox;
/* Now we have a ton of bins and each bin's 64 slots are full.
* Let's sum each bin's 64 slots. The result with be dc_dp. */
@@ -311,9 +312,9 @@ bspline_score_h_mse (
Bspline_state *bst = bod->get_bspline_state ();
Bspline_xform *bxf = bod->get_bspline_xform ();
- Volume *fixed = parms->fixed;
- Volume *moving = parms->moving;
- Volume *moving_grad = parms->moving_grad;
+ Volume *fixed = bst->fixed;
+ Volume *moving = bst->moving;
+ Volume *moving_grad = bst->moving_grad;
Bspline_score* ssd = &bst->ssd;
double score_tile;
@@ -456,7 +457,7 @@ bspline_score_h_mse (
// Store the score!
score_tile += diff * diff;
- ssd->num_vox++;
+ ssd->curr_num_vox++;
// Compute dc_dv
dc_dv[0] = diff * m_grad[3 * idx_moving_round + 0];
@@ -527,9 +528,9 @@ bspline_score_g_mse (
Bspline_state *bst = bod->get_bspline_state ();
Bspline_xform *bxf = bod->get_bspline_xform ();
- Volume *fixed = parms->fixed;
- Volume *moving = parms->moving;
- Volume *moving_grad = parms->moving_grad;
+ Volume *fixed = bst->fixed;
+ Volume *moving = bst->moving;
+ Volume *moving_grad = bst->moving_grad;
Bspline_score* ssd = &bst->ssd;
double score_tile;
@@ -706,7 +707,7 @@ bspline_score_g_mse (
} /* LOOP_THRU_VOL_TILES */
- ssd->num_vox = num_vox;
+ ssd->curr_num_vox = num_vox;
/* Now we have a ton of bins and each bin's 64 slots are full.
* Let's sum each bin's 64 slots. The result with be dc_dp. */
@@ -739,9 +740,9 @@ bspline_score_c_mse (
Bspline_state *bst = bod->get_bspline_state ();
Bspline_xform *bxf = bod->get_bspline_xform ();
- Volume *fixed = parms->fixed;
- Volume *moving = parms->moving;
- Volume *moving_grad = parms->moving_grad;
+ Volume *fixed = bst->fixed;
+ Volume *moving = bst->moving;
+ Volume *moving_grad = bst->moving_grad;
Bspline_score* ssd = &bst->ssd;
plm_long fijk[3], fv; /* Indices within fixed image (vox) */
@@ -874,7 +875,7 @@ bspline_score_c_mse (
}
score_acc += diff * diff;
- ssd->num_vox++;
+ ssd->curr_num_vox++;
} /* LOOP_THRU_ROI_X */
} /* LOOP_THRU_ROI_Y */
@@ -949,13 +950,9 @@ bspline_score_mse (
{
Bspline_parms *parms = bod->get_bspline_parms ();
Bspline_state *bst = bod->get_bspline_state ();
- Bspline_xform *bxf = bod->get_bspline_xform ();
-
- Regularization_parms* reg_parms = parms->reg_parms;
- Bspline_landmarks* blm = parms->blm;
- Volume* fixed_roi = parms->fixed_roi;
- Volume* moving_roi = parms->moving_roi;
+ Volume* fixed_roi = bst->fixed_roi;
+ Volume* moving_roi = bst->moving_roi;
bool have_roi = fixed_roi || moving_roi;
/* CPU Implementations */
diff --git a/src/plastimatch/register/bspline_mse.h b/src/plastimatch/register/bspline_mse.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/register/bspline_mse.txx b/src/plastimatch/register/bspline_mse.txx
index 1a01c13..727981b 100755
--- a/src/plastimatch/register/bspline_mse.txx
+++ b/src/plastimatch/register/bspline_mse.txx
@@ -15,8 +15,8 @@ public:
public:
Bspline_mse_k (Bspline_optimize *bod)
{
- Bspline_parms *parms = bod->get_bspline_parms ();
- Volume *moving_grad = parms->moving_grad;
+ Bspline_state *bst = bod->get_bspline_state ();
+ Volume *moving_grad = bst->moving_grad;
m_grad = (float*) moving_grad->img;
score_acc = 0.;
}
@@ -64,7 +64,7 @@ public:
this->score_acc += diff * diff;
/* Update voxel count */
- ssd->num_vox++;
+ ssd->curr_num_vox++;
/* Compute spatial gradient using nearest neighbors */
dc_dv[0] = diff * m_grad[3*mvr+0]; /* x component */
@@ -73,7 +73,6 @@ public:
/* Update cost function gradient */
ssd->update_smetric_grad_b (bxf, pidx, qidx, dc_dv);
- ssd->num_vox++;
}
};
@@ -97,8 +96,8 @@ public:
public:
Bspline_mse_l (Bspline_optimize *bod)
{
- Bspline_parms *parms = bod->get_bspline_parms ();
- Volume *moving_grad = parms->moving_grad;
+ Bspline_state *bst = bod->get_bspline_state ();
+ Volume *moving_grad = bst->moving_grad;
m_grad = (float*) moving_grad->img;
score_acc = 0.;
}
@@ -148,7 +147,7 @@ public:
this->score_acc += diff * diff;
/* Update voxel count */
- ssd->num_vox++;
+ ssd->curr_num_vox++;
/* Compute spatial gradient using nearest neighbors */
dc_dv[0] = diff * m_grad[3*mvr+0]; /* x component */
diff --git a/src/plastimatch/register/bspline_optimize.cxx b/src/plastimatch/register/bspline_optimize.cxx
index ddff731..4b6ee64 100644
--- a/src/plastimatch/register/bspline_optimize.cxx
+++ b/src/plastimatch/register/bspline_optimize.cxx
@@ -32,10 +32,7 @@ public:
Bspline_optimize::Bspline_optimize ()
{
d_ptr = new Bspline_optimize_private;
-
- fixed = 0;
- moving = 0;
- moving_grad = 0;
+ d_ptr->bst = Bspline_state::New ();
}
Bspline_optimize::~Bspline_optimize ()
@@ -43,37 +40,6 @@ Bspline_optimize::~Bspline_optimize ()
delete d_ptr;
}
-void
-Bspline_optimize::initialize (Bspline_xform *bxf, Bspline_parms *parms)
-{
- d_ptr->parms = parms;
- d_ptr->bst = Bspline_state::New ();
- d_ptr->bxf = bxf;
-
- d_ptr->bst->initialize (bxf, parms);
-}
-
-static void
-log_parms (Bspline_parms* parms)
-{
- logfile_printf ("BSPLINE PARMS\n");
- logfile_printf ("max_its = %d\n", parms->max_its);
- logfile_printf ("max_feval = %d\n", parms->max_feval);
-}
-
-static void
-log_bxf_header (Bspline_xform* bxf)
-{
- logfile_printf ("BSPLINE XFORM HEADER\n");
- logfile_printf ("vox_per_rgn = %d %d %d\n",
- bxf->vox_per_rgn[0], bxf->vox_per_rgn[1], bxf->vox_per_rgn[2]);
- logfile_printf ("roi_offset = %d %d %d\n",
- bxf->roi_offset[0], bxf->roi_offset[1], bxf->roi_offset[2]);
- logfile_printf ("roi_dim = %d %d %d\n",
- bxf->roi_dim[0], bxf->roi_dim[1], bxf->roi_dim[2]);
- logfile_printf ("img_dc = %s\n", bxf->dc.get_string().c_str());
-}
-
static void
bspline_optimize_select (
Bspline_optimize *bod
@@ -119,26 +85,36 @@ bspline_optimize_select (
}
void
-bspline_optimize (
- Bspline_xform *bxf,
- Bspline_parms *parms
+Bspline_optimize::optimize (
)
{
- Bspline_optimize bod;
- bod.initialize (bxf, parms);
+ Bspline_parms *parms = this->get_bspline_parms ();
+ Bspline_state *bst = this->get_bspline_state ();
+ Bspline_xform *bxf = this->get_bspline_xform ();
+
+ d_ptr->bst->initialize (bxf, parms);
+
+ /* GCS FIX: The below does not belong in bspline_state. And it should
+ be done if any similarity metric is MI. */
+ /* JAS Fix 2011.09.14
+ * The MI algorithm will get stuck for a set of coefficients all equaling
+ * zero due to the method we use to compute the cost function gradient.
+ * However, it is possible we could be inheriting coefficients from a
+ * prior stage, so we must check for inherited coefficients before
+ * applying an initial offset to the coefficient array. */
+ if (bst->has_metric_type (SIMILARITY_METRIC_MI_MATTES)) {
+ bxf->jitter_if_zero ();
+ }
- log_parms (parms);
- log_bxf_header (bxf);
+ parms->log ();
+ bxf->log_header ();
+ bst->log_metric ();
- /* GCS FIX -- this should move into Bspline_state() constructor */
/* Initialize histograms */
- if (parms->metric_type[0] == REGISTRATION_METRIC_MI_MATTES) {
- bod.get_bspline_state()->mi_hist->initialize (
- parms->fixed, parms->moving);
- }
+ bst->initialize_mi_histograms ();
/* Do the optimization */
- bspline_optimize_select (&bod);
+ bspline_optimize_select (this);
}
Bspline_parms*
@@ -158,3 +134,15 @@ Bspline_optimize::get_bspline_xform ()
{
return d_ptr->bxf;
}
+
+void
+Bspline_optimize::set_bspline_parms (Bspline_parms *parms)
+{
+ d_ptr->parms = parms;
+}
+
+void
+Bspline_optimize::set_bspline_xform (Bspline_xform *bxf)
+{
+ d_ptr->bxf = bxf;
+}
diff --git a/src/plastimatch/register/bspline_optimize.h b/src/plastimatch/register/bspline_optimize.h
index a037c2b..f71147f 100644
--- a/src/plastimatch/register/bspline_optimize.h
+++ b/src/plastimatch/register/bspline_optimize.h
@@ -20,16 +20,12 @@ public:
Bspline_optimize ();
~Bspline_optimize ();
public:
- Volume *fixed;
- Volume *moving;
- Volume *moving_grad;
-public:
- void initialize (Bspline_xform *bxf, Bspline_parms *parms);
-
- /* Get raw objects, needed by CUDA code */
Bspline_parms* get_bspline_parms ();
Bspline_state* get_bspline_state ();
Bspline_xform* get_bspline_xform ();
+ void set_bspline_parms (Bspline_parms *parms);
+ void set_bspline_xform (Bspline_xform *bxf);
+ void optimize ();
};
PLMREGISTER_C_API void bspline_optimize (
diff --git a/src/plastimatch/register/bspline_optimize_lbfgsb.cxx b/src/plastimatch/register/bspline_optimize_lbfgsb.cxx
index c48753f..cb64c96 100644
--- a/src/plastimatch/register/bspline_optimize_lbfgsb.cxx
+++ b/src/plastimatch/register/bspline_optimize_lbfgsb.cxx
@@ -140,8 +140,6 @@ Nocedal_optimizer::Nocedal_optimizer (Bspline_optimize *bod)
/* If iprint is 1, the file iterate.dat will be created */
iprint = 0;
- //factr = 1.0e+7;
- //pgtol = 1.0e-5;
factr = parms->lbfgsb_factr;
pgtol = parms->lbfgsb_pgtol;
@@ -220,8 +218,8 @@ bspline_optimize_lbfgsb (
bspline_score (bod);
/* Save coeff if best score */
- if (ssd->score < best_score) {
- best_score = ssd->score;
+ if (ssd->total_score < best_score) {
+ best_score = ssd->total_score;
for (int i = 0; i < bxf->num_coeff; i++) {
best_coeff[i] = bxf->coeff[i];
}
@@ -235,11 +233,11 @@ bspline_optimize_lbfgsb (
/* Save some debugging information */
bspline_save_debug_state (parms, bst, bxf);
if (parms->debug) {
- fprintf (fp, "%f\n", ssd->score);
+ fprintf (fp, "%f\n", ssd->total_score);
}
/* Copy from C to fortran (float -> double) */
- optimizer.f = ssd->score;
+ optimizer.f = ssd->total_score;
for (int i = 0; i < bxf->num_coeff; i++) {
optimizer.g[i] = ssd->total_grad[i];
}
@@ -253,14 +251,14 @@ bspline_optimize_lbfgsb (
/* Check convergence tolerance */
if (old_best_score != DBL_MAX) {
- double score_diff = old_best_score - ssd->score;
+ double score_diff = old_best_score - ssd->total_score;
if (score_diff < parms->convergence_tol
&& bst->it >= parms->min_its)
{
break;
}
}
- old_best_score = ssd->score;
+ old_best_score = ssd->total_score;
/* Update line search start location */
printf ("Update lss_coeff\n");
diff --git a/src/plastimatch/register/bspline_optimize_liblbfgs.cxx b/src/plastimatch/register/bspline_optimize_liblbfgs.cxx
index ae543f2..c6c6e5a 100644
--- a/src/plastimatch/register/bspline_optimize_liblbfgs.cxx
+++ b/src/plastimatch/register/bspline_optimize_liblbfgs.cxx
@@ -47,7 +47,7 @@ evaluate (
bst->feval ++;
/* Return cost */
- return (lbfgsfloatval_t) bst->ssd.score;
+ return (lbfgsfloatval_t) bst->ssd.total_score;
}
static int
diff --git a/src/plastimatch/register/bspline_optimize_nlopt.cxx b/src/plastimatch/register/bspline_optimize_nlopt.cxx
index a4e719e..e029740 100644
--- a/src/plastimatch/register/bspline_optimize_nlopt.cxx
+++ b/src/plastimatch/register/bspline_optimize_nlopt.cxx
@@ -46,7 +46,7 @@ bspline_optimize_nlopt_score (
}
/* Return cost */
- return (double) bst->ssd.score;
+ return (double) bst->ssd.total_score;
}
void
diff --git a/src/plastimatch/register/bspline_optimize_steepest.cxx b/src/plastimatch/register/bspline_optimize_steepest.cxx
index 1bfd11a..7ecc89f 100644
--- a/src/plastimatch/register/bspline_optimize_steepest.cxx
+++ b/src/plastimatch/register/bspline_optimize_steepest.cxx
@@ -12,7 +12,6 @@
#endif
#include "bspline.h"
-#include "bspline_cuda.h"
#include "bspline_optimize.h"
#include "bspline_optimize_steepest.h"
#include "bspline_parms.h"
@@ -53,9 +52,10 @@ bspline_optimize_steepest_trace (
fp = fopen("scores.txt", "w");
}
+ // GCS FIX: I'm pretty sure the below makes no sense.
// JAS 04.19.2010
// For Testing...
- if (parms->metric_type[0] == REGISTRATION_METRIC_MI_MATTES) {
+ if (bst->has_metric_type (SIMILARITY_METRIC_MI_MATTES)) {
alpha = 1.0f;
printf ("Using alpha_0 (%f)\n", alpha);
}
@@ -73,7 +73,7 @@ bspline_optimize_steepest_trace (
/* Get score and gradient */
bspline_score (bod);
- old_score = bst->ssd.score;
+ old_score = bst->ssd.total_score;
/* Get search direction */
ssd_grad_norm = 0;
@@ -92,7 +92,7 @@ bspline_optimize_steepest_trace (
/* Save some debugging information */
bspline_save_debug_state (parms, bst, bxf);
if (parms->debug) {
- fprintf (fp, "%f\n", ssd->score);
+ fprintf (fp, "%f\n", ssd->total_score);
}
while (bst->it < parms->max_its && bst->feval < parms->max_feval) {
@@ -111,7 +111,7 @@ bspline_optimize_steepest_trace (
bspline_score (bod);
/* Compute gain ratio with linear model */
- gr = (old_score - bst->ssd.score) / htg;
+ gr = (old_score - bst->ssd.total_score) / htg;
if (gr < 0) {
/* Cost increased. Keep search direction and reduce trust rgn. */
alpha = 0.5 * alpha;
@@ -133,7 +133,7 @@ bspline_optimize_steepest_trace (
/* Save some debugging information */
bspline_save_debug_state (parms, bst, bxf);
if (parms->debug) {
- fprintf (fp, "%f\n", ssd->score);
+ fprintf (fp, "%f\n", ssd->total_score);
}
/* If score was reduced, we accept the line search (fall through).
@@ -151,7 +151,7 @@ bspline_optimize_steepest_trace (
success ++;
memcpy (x, bxf->coeff, bxf->num_coeff * sizeof(float));
memcpy (grad_backup, ssd->total_grad, bxf->num_coeff * sizeof(float));
- score_backup = ssd->score;
+ score_backup = ssd->total_score;
sprintf (filename, "grad_%04i.csv", success);
trace = fopen(filename, "w");
printf ("Capturing Gradient (grad_%04i.csv)\n", success);
@@ -167,14 +167,14 @@ bspline_optimize_steepest_trace (
printf ("\t");
bspline_score (bod);
- fprintf (trace, "%d, %10.10f\n", i, bst->ssd.score);
+ fprintf (trace, "%d, %10.10f\n", i, bst->ssd.total_score);
fflush(trace);
}
fclose (trace);
printf ("Finished Capturing Gradient.\n\n");
memcpy (ssd->total_grad, grad_backup, bxf->num_coeff * sizeof(float));
- ssd->score = score_backup;
+ ssd->total_score = score_backup;
/* Start new line search */
ssd_grad_norm = 0;
@@ -187,12 +187,12 @@ bspline_optimize_steepest_trace (
h[i] = - ssd->total_grad[i] / ssd_grad_norm;
htg -= h[i] * ssd->total_grad[i];
}
- old_score = bst->ssd.score;
+ old_score = bst->ssd.total_score;
}
/* Save best result */
memcpy (bxf->coeff, x, bxf->num_coeff * sizeof(float));
- bst->ssd.score = old_score;
+ bst->ssd.total_score = old_score;
if (parms->debug) {
fclose (fp);
@@ -234,9 +234,10 @@ bspline_optimize_steepest_trust (
fp = fopen("scores.txt", "w");
}
+ // GCS FIX: I'm pretty sure the below makes no sense.
// JAS 04.19.2010
// For testing...
- if (parms->metric_type[0] == REGISTRATION_METRIC_MI_MATTES) {
+ if (bst->has_metric_type (SIMILARITY_METRIC_MI_MATTES)) {
alpha = 1.0f;
printf ("Using alpha_0 (%f)\n", alpha);
}
@@ -252,7 +253,7 @@ bspline_optimize_steepest_trust (
/* Get score and gradient */
bspline_score (bod);
- old_score = bst->ssd.score;
+ old_score = bst->ssd.total_score;
/* Get search direction */
ssd_grad_norm = 0;
@@ -272,7 +273,7 @@ bspline_optimize_steepest_trust (
/* Save some debugging information */
bspline_save_debug_state (parms, bst, bxf);
if (parms->debug) {
- fprintf (fp, "%f\n", ssd->score);
+ fprintf (fp, "%f\n", ssd->total_score);
}
while (bst->it < parms->max_its && bst->feval < parms->max_feval) {
@@ -291,7 +292,7 @@ bspline_optimize_steepest_trust (
bspline_score (bod);
/* Compute gain ratio with linear model */
- gr = (old_score - bst->ssd.score) / htg;
+ gr = (old_score - bst->ssd.total_score) / htg;
if (gr < 0) {
/* Cost increased. Keep search direction and reduce trust rgn. */
alpha = 0.5 * alpha;
@@ -313,7 +314,7 @@ bspline_optimize_steepest_trust (
/* Save some debugging information */
bspline_save_debug_state (parms, bst, bxf);
if (parms->debug) {
- fprintf (fp, "%f\n", ssd->score);
+ fprintf (fp, "%f\n", ssd->total_score);
}
/* If score was reduced, we accept the line search */
@@ -334,12 +335,12 @@ bspline_optimize_steepest_trust (
h[i] = - ssd->total_grad[i] / ssd_grad_norm;
htg -= h[i] * ssd->total_grad[i];
}
- old_score = bst->ssd.score;
+ old_score = bst->ssd.total_score;
}
/* Save best result */
memcpy (bxf->coeff, x, bxf->num_coeff * sizeof(float));
- bst->ssd.score = old_score;
+ bst->ssd.total_score = old_score;
if (parms->debug) {
fclose (fp);
@@ -379,7 +380,7 @@ bspline_optimize_steepest_naive (
/* Get score and gradient */
bspline_score (bod);
- old_score = bst->ssd.score;
+ old_score = bst->ssd.total_score;
/* Set alpha based on norm gradient */
ssd_grad_norm = 0;
@@ -395,7 +396,7 @@ bspline_optimize_steepest_naive (
/* Save some debugging information */
bspline_save_debug_state (parms, bst, bxf);
if (parms->debug) {
- fprintf (fp, "%f\n", ssd->score);
+ fprintf (fp, "%f\n", ssd->total_score);
}
while (bst->it < parms->max_its && bst->feval < parms->max_feval) {
@@ -416,19 +417,19 @@ bspline_optimize_steepest_naive (
bspline_score (bod);
/* Update gamma */
- if (bst->ssd.score < old_score) {
+ if (bst->ssd.total_score < old_score) {
gamma *= gain;
} else {
gamma /= gain;
}
- old_score = bst->ssd.score;
+ old_score = bst->ssd.total_score;
/* Give a little feedback to the user */
bspline_display_coeff_stats (bxf);
/* Save some debugging information */
bspline_save_debug_state (parms, bst, bxf);
if (parms->debug) {
- fprintf (fp, "%f\n", ssd->score);
+ fprintf (fp, "%f\n", ssd->total_score);
}
}
diff --git a/src/plastimatch/register/bspline_parms.cxx b/src/plastimatch/register/bspline_parms.cxx
index 46cf12b..bf4b1ad 100644
--- a/src/plastimatch/register/bspline_parms.cxx
+++ b/src/plastimatch/register/bspline_parms.cxx
@@ -6,14 +6,12 @@
#include "bspline_parms.h"
#include "bspline_landmarks.h"
#include "bspline_regularize.h"
+#include "logfile.h"
Bspline_parms::Bspline_parms ()
{
this->threading = BTHR_CPU;
this->optimization = BOPT_LBFGSB;
- this->metric_type.push_back (REGISTRATION_METRIC_MSE);
- this->metric_lambda.push_back (1.0);
- this->implementation = '\0';
this->min_its = 0;
this->max_its = 10;
this->max_feval = 10;
@@ -36,12 +34,6 @@ Bspline_parms::Bspline_parms ()
this->lbfgsb_pgtol = 1.0e-5;
this->lbfgsb_mmax = -1;
- this->fixed = 0;
- this->moving = 0;
- this->fixed_grad = 0;
- this->moving_grad = 0;
- this->fixed_roi = 0;
- this->moving_roi = 0;
this->fixed_stiffness = 0;
this->reg_parms = new Regularization_parms;
@@ -57,3 +49,11 @@ Bspline_parms::~Bspline_parms ()
delete this->blm;
delete this->reg_parms;
}
+
+void
+Bspline_parms::log ()
+{
+ logfile_printf ("BSPLINE PARMS\n");
+ logfile_printf ("max_its = %d\n", this->max_its);
+ logfile_printf ("max_feval = %d\n", this->max_feval);
+}
diff --git a/src/plastimatch/register/bspline_parms.h b/src/plastimatch/register/bspline_parms.h
index 6fee4be..0a98378 100644
--- a/src/plastimatch/register/bspline_parms.h
+++ b/src/plastimatch/register/bspline_parms.h
@@ -5,11 +5,13 @@
#define _bspline_parms_h_
#include "plmregister_config.h"
+#include <list>
#include <string>
#include <vector>
-#include "bspline_mi_hist.h"
#include "double_align8.h"
-#include "registration_metric_type.h"
+#include "joint_histogram.h"
+#include "metric_state.h"
+#include "similarity_metric_type.h"
#include "smart_pointer.h"
enum BsplineOptimization {
@@ -37,52 +39,56 @@ public:
Bspline_parms ();
~Bspline_parms ();
public:
- enum BsplineThreading threading;
+ /* General optimizer parms */
enum BsplineOptimization optimization;
- std::vector<Registration_metric_type> metric_type;
- std::vector<float> metric_lambda;
- char implementation; /* Implementation ('a', 'b', etc.) */
int min_its; /* Miniumum iterations (line searches) */
int max_its; /* Max iterations (line searches) */
int max_feval; /* Max function evaluations */
+ double_align8 convergence_tol; /* When to stop iterations based on score */
+
+ /* LBFGSB optimizer parms */
+ double_align8 lbfgsb_factr; /* Function value tolerance for L-BFGS-B */
+ double_align8 lbfgsb_pgtol; /* Projected grad tolerance for L-BFGS-B */
+ int lbfgsb_mmax; /* Number of rows in M matrix */
+
+ /* Debugging */
int debug; /* Create grad & histogram files */
std::string debug_dir; /* Directory where to create debug files */
int debug_stage; /* Used to tag debug files by stage */
+ char* xpm_hist_dump; /* Pointer to base string of hist dumps */
+
+ /* Threading */
+ enum BsplineThreading threading;
int gpuid; /* Sets GPU to use for multi-gpu machines */
- double_align8 convergence_tol; /* When to stop iterations based on score */
- /* MI parms */
+ /*! \brief Implementation ('a', 'b', etc.) -- to be moved into
+ Stage_similarity_data */
+ char implementation;
+
+ /* MI similarity metric */
enum Mi_hist_type mi_hist_type;
plm_long mi_hist_fixed_bins;
plm_long mi_hist_moving_bins;
+ /* Image ROI selection */
float mi_fixed_image_minVal;
float mi_fixed_image_maxVal;
float mi_moving_image_minVal;
float mi_moving_image_maxVal;
- /* LBFGSB optimizer parms */
- double_align8 lbfgsb_factr; /* Function value tolerance for L-BFGS-B */
- double_align8 lbfgsb_pgtol; /* Projected grad tolerance for L-BFGS-B */
- int lbfgsb_mmax; /* Number of rows in M matrix */
-
- /* Image Volumes - these are not owned by Bspline_parms */
- Volume* fixed;
- Volume* moving;
- Volume* fixed_grad;
- Volume* moving_grad;
- Volume* fixed_roi;
- Volume* moving_roi;
- Volume* fixed_stiffness;
-
/* Regularization */
- Regularization_parms* reg_parms; /* Regularization Parameters */
+ Regularization_parms* reg_parms;
+ Volume* fixed_stiffness;
/* Landmarks */
Bspline_landmarks* blm; /* Landmarks parameters */
- float rbf_radius; /* Radius of RBF; if rbf_radius>0, RBF are used */
- float rbf_young_modulus; /* Penalty for the large 2nd derivative of RBF vector field */
- char* xpm_hist_dump; /* Pointer to base string of hist dumps */
+ /*! \brief Radius of RBF; if rbf_radius>0, RBF are used */
+ float rbf_radius;
+ /*! \brief Penalty for the large 2nd derivative of RBF vector field */
+ float rbf_young_modulus;
+
+public:
+ void log ();
};
#endif
diff --git a/src/plastimatch/register/bspline_regularize.cxx b/src/plastimatch/register/bspline_regularize.cxx
index fe15ef0..d85dcf2 100644
--- a/src/plastimatch/register/bspline_regularize.cxx
+++ b/src/plastimatch/register/bspline_regularize.cxx
@@ -12,8 +12,6 @@ Bspline_regularize::Bspline_regularize ()
/* all methods */
this->reg_parms = 0;
this->bxf = 0;
- this->fixed = 0;
- this->moving = 0;
this->fixed_stiffness = 0;
/* semi-analytic method */
diff --git a/src/plastimatch/register/bspline_regularize.h b/src/plastimatch/register/bspline_regularize.h
index 2d07ea3..c7eaba9 100644
--- a/src/plastimatch/register/bspline_regularize.h
+++ b/src/plastimatch/register/bspline_regularize.h
@@ -33,8 +33,6 @@ public:
Regularization_parms *reg_parms;
Bspline_xform *bxf;
- Volume* fixed;
- Volume* moving;
Volume* fixed_stiffness;
/* numeric methods */
diff --git a/src/plastimatch/register/bspline_score.cxx b/src/plastimatch/register/bspline_score.cxx
index 2c18a8d..e1a805b 100644
--- a/src/plastimatch/register/bspline_score.cxx
+++ b/src/plastimatch/register/bspline_score.cxx
@@ -8,21 +8,24 @@
Bspline_score::Bspline_score ()
{
- this->score = 0;
+ this->total_score = 0;
+ this->total_grad = 0;
+
this->lmetric = 0;
this->rmetric = 0;
- this->num_vox = 0;
this->num_coeff = 0;
- this->smetric_grad = 0;
- this->total_grad = 0;
+
+ this->curr_num_vox = 0;
+ this->curr_smetric = 0;
+ this->curr_smetric_grad = 0;
this->time_rmetric = 0;
}
Bspline_score::~Bspline_score ()
{
- delete[] smetric_grad;
+ delete[] curr_smetric_grad;
delete[] total_grad;
}
@@ -30,38 +33,42 @@ void
Bspline_score::set_num_coeff (plm_long num_coeff)
{
this->num_coeff = num_coeff;
- delete[] this->smetric_grad;
+ delete[] this->curr_smetric_grad;
delete[] this->total_grad;
- this->smetric_grad = new float[num_coeff];
+ this->curr_smetric_grad = new float[num_coeff];
this->total_grad = new float[num_coeff];
}
void
Bspline_score::reset_smetric_grad ()
{
- memset (this->smetric_grad, 0, this->num_coeff * sizeof(float));
+ memset (this->curr_smetric_grad, 0, this->num_coeff * sizeof(float));
}
void
Bspline_score::reset_score ()
{
- this->score = 0;
+ this->total_score = 0;
+ memset (this->total_grad, 0, this->num_coeff * sizeof(float));
this->lmetric = 0;
this->rmetric = 0;
- this->smetric.clear();
- this->num_vox = 0;
- memset (this->smetric_grad, 0, this->num_coeff * sizeof(float));
- memset (this->total_grad, 0, this->num_coeff * sizeof(float));
- this->time_smetric.clear();
+ this->metric_record.clear();
+ this->curr_num_vox = 0;
+ this->curr_smetric = 0;
+ memset (this->curr_smetric_grad, 0, this->num_coeff * sizeof(float));
this->time_rmetric = 0;
}
void
-Bspline_score::accumulate_grad (float lambda)
+Bspline_score::accumulate (float lambda)
{
+ this->total_score += lambda * this->curr_smetric;
for (plm_long i = 0; i < this->num_coeff; i++) {
- this->total_grad[i] += lambda * this->smetric_grad[i];
+ this->total_grad[i] += lambda * this->curr_smetric_grad[i];
}
+
+ this->curr_smetric = 0;
+ this->curr_num_vox = 0;
this->reset_smetric_grad ();
}
@@ -72,7 +79,7 @@ Bspline_score::update_smetric_grad (
plm_long qidx,
const float dc_dv[3])
{
- this->update_grad (this->smetric_grad, bxf, p, qidx, dc_dv);
+ this->update_grad (this->curr_smetric_grad, bxf, p, qidx, dc_dv);
}
void
@@ -92,7 +99,7 @@ Bspline_score::update_smetric_grad_b (
plm_long qidx,
const float dc_dv[3])
{
- this->update_grad_b (this->smetric_grad, bxf, pidx, qidx, dc_dv);
+ this->update_grad_b (this->curr_smetric_grad, bxf, pidx, qidx, dc_dv);
}
void
diff --git a/src/plastimatch/register/bspline_score.h b/src/plastimatch/register/bspline_score.h
index b8c8a49..a01abc9 100644
--- a/src/plastimatch/register/bspline_score.h
+++ b/src/plastimatch/register/bspline_score.h
@@ -10,31 +10,55 @@
class Bspline_xform;
+class PLMREGISTER_API Metric_score
+{
+public:
+ Metric_score () {
+ score = 0.f;
+ time = 0.f;
+ num_vox = 0;
+ }
+ Metric_score (float score, float time, plm_long num_vox)
+ : score(score), time(time), num_vox(num_vox) {
+ score = 0.f;
+ time = 0.f;
+ num_vox = 0;
+ }
+public:
+ float score;
+ double time;
+ plm_long num_vox;
+};
+
class PLMREGISTER_API Bspline_score
{
public:
Bspline_score ();
~Bspline_score ();
public:
- float score; /* Total Score (sent to optimizer) */
+ float total_score; /* Total Score (sent to optimizer) */
+ float* total_grad; /* Total cost function gradient */
+
float lmetric; /* Landmark metric */
float rmetric; /* Regularization metric */
- std::vector<float> smetric; /* Similarity metric */
- plm_long num_vox; /* Number of voxel with correspondence */
+ /*! \brief The metric_record keeps track of score statistics
+ for reporting purposes */
+ std::vector<Metric_score> metric_record;
+
plm_long num_coeff; /* Size of gradient vector = num coefficents */
- float* smetric_grad; /* Gradient of score for current smetric */
- float* total_grad; /* Total cost function gradient wrt coefficients */
- /* Time to compute similarity metric */
- std::vector<double> time_smetric;
+ float curr_smetric; /* Current smetric value */
+ float* curr_smetric_grad; /* Gradient of score for current smetric */
+ plm_long curr_num_vox; /* Number of voxel with correspondence */
+
/* Time to compute regularization metric */
double time_rmetric;
public:
void set_num_coeff (plm_long num_coeff);
void reset_smetric_grad ();
void reset_score ();
- void accumulate_grad (float lambda);
+ void accumulate (float lambda);
void update_smetric_grad (
const Bspline_xform* bxf,
const plm_long p[3],
diff --git a/src/plastimatch/register/bspline_stage.cxx b/src/plastimatch/register/bspline_stage.cxx
index 9fa08e6..3cfa277 100644
--- a/src/plastimatch/register/bspline_stage.cxx
+++ b/src/plastimatch/register/bspline_stage.cxx
@@ -13,6 +13,7 @@
#include "bspline_regularize.h"
#include "bspline_parms.h"
#include "bspline_stage.h"
+#include "bspline_xform.h"
#include "logfile.h"
#include "mha_io.h"
#include "plm_image_header.h"
@@ -33,18 +34,14 @@
class Bspline_stage_private {
public:
- Registration_parms *regp;
Registration_data *regd;
const Stage_parms *stage;
Xform *xf_in;
Xform::Pointer xf_out;
- Bspline_parms bsp_parms;
- Volume::Pointer fixed_ss;
- Volume::Pointer moving_ss;
- Volume::Pointer moving_grad;
- Volume::Pointer f_roi_ss;
- Volume::Pointer m_roi_ss;
+ Bspline_parms parms;
+ Bspline_optimize bod;
+
Volume::Pointer f_stiffness_ss;
public:
Bspline_stage_private () {
@@ -53,13 +50,11 @@ public:
};
Bspline_stage::Bspline_stage (
- Registration_parms *regp,
Registration_data *regd,
const Stage_parms *stage,
Xform *xf_in)
{
d_ptr = new Bspline_stage_private;
- d_ptr->regp = regp;
d_ptr->regd = regd;
d_ptr->stage = stage;
d_ptr->xf_in = xf_in;
@@ -102,11 +97,8 @@ update_roi (Volume::Pointer& roi, Volume::Pointer& image, float min_val,
void
Bspline_stage::run_stage ()
{
- Xform *xf_out = d_ptr->xf_out.get();
- Bspline_parms *bsp_parms = &d_ptr->bsp_parms;
-
/* Run bspline optimization */
- bspline_optimize (xf_out->get_gpuit_bsp(), bsp_parms);
+ d_ptr->bod.optimize ();
}
void
@@ -117,58 +109,54 @@ Bspline_stage::initialize ()
const Shared_parms *shared = d_ptr->stage->get_shared_parms();
Xform *xf_in = d_ptr->xf_in;
Xform *xf_out = d_ptr->xf_out.get();
- Bspline_parms *bsp_parms = &d_ptr->bsp_parms;
+ Bspline_optimize *bod = &d_ptr->bod;
+ Bspline_parms *parms = &d_ptr->parms;
+ Bspline_state *bst = bod->get_bspline_state ();
- Plm_image_header pih;
+ /* Tell bod what parameters to use */
+ d_ptr->bod.set_bspline_parms (parms);
- logfile_printf ("Converting fixed\n");
- Volume::Pointer& fixed = regd->fixed_image->get_volume_float ();
- logfile_printf ("Converting moving\n");
- Volume::Pointer& moving = regd->moving_image->get_volume_float ();
- logfile_printf ("Done.\n");
+ /* Set up metric state */
+ populate_similarity_list (bst->similarity_data, regd, stage);
- Volume::Pointer m_roi;
- Volume::Pointer f_roi;
+ /* Transform input xform to bspline and give to bod */
+ Plm_image_header pih;
+ pih.set (bst->similarity_data.front()->fixed_ss);
+ xform_to_gpuit_bsp (xf_out, xf_in, &pih, stage->grid_spac);
+ Bspline_xform *bxf = xf_out->get_gpuit_bsp();
+ d_ptr->bod.set_bspline_xform (bxf);
/* Set roi's */
- if (shared->fixed_roi_enable && regd->fixed_roi) {
- f_roi = regd->fixed_roi->get_volume_uchar();
- }
- if (shared->moving_roi_enable && regd->moving_roi) {
- m_roi = regd->moving_roi->get_volume_uchar();
+ Volume::Pointer m_roi;
+ Volume::Pointer f_roi;
+ if (shared->fixed_roi_enable && regd->get_fixed_roi()) {
+ f_roi = regd->get_fixed_roi()->get_volume_uchar();
}
-
- /* Convert images to gpuit format */
- fixed->convert (PT_FLOAT); /* Maybe not necessary? */
- moving->convert (PT_FLOAT); /* Maybe not necessary? */
-
- /* Subsample images */
- d_ptr->fixed_ss = registration_resample_volume (
- fixed, stage, stage->resample_rate_fixed);
- d_ptr->moving_ss = registration_resample_volume (
- moving, stage, stage->resample_rate_moving);
-
- /* Gradient magnitude uses different fixed and moving images */
- if (stage->metric_type[0] == REGISTRATION_METRIC_GM) {
- d_ptr->fixed_ss = volume_gradient_magnitude (d_ptr->fixed_ss);
- d_ptr->moving_ss = volume_gradient_magnitude (d_ptr->moving_ss);
+ if (shared->moving_roi_enable && regd->get_moving_roi()) {
+ m_roi = regd->get_moving_roi()->get_volume_uchar();
}
/* Copy parameters from stage_parms to bspline_parms */
- bsp_parms->mi_fixed_image_minVal = stage->mi_fixed_image_minVal;
- bsp_parms->mi_fixed_image_maxVal = stage->mi_fixed_image_maxVal;
- bsp_parms->mi_moving_image_minVal = stage->mi_moving_image_minVal;
- bsp_parms->mi_moving_image_maxVal = stage->mi_moving_image_maxVal;
-
- //Check if min/max values for moving image are set (correctly)
- if ((bsp_parms->mi_moving_image_minVal!=0
- || bsp_parms->mi_moving_image_maxVal!=0)
- && (bsp_parms->mi_moving_image_minVal <
- bsp_parms->mi_moving_image_maxVal))
+ parms->mi_fixed_image_minVal = stage->mi_fixed_image_minVal;
+ parms->mi_fixed_image_maxVal = stage->mi_fixed_image_maxVal;
+ parms->mi_moving_image_minVal = stage->mi_moving_image_minVal;
+ parms->mi_moving_image_maxVal = stage->mi_moving_image_maxVal;
+
+ /* GCS FIX BEGIN */
+ /* BSpline code needs work to support multi-planar imaging
+ until that is done, this should maintain the old behavior */
+ Volume::Pointer fixed = regd->get_fixed_image()->get_volume_float();
+ Volume::Pointer moving = regd->get_moving_image()->get_volume_float();
+
+ // Check if min/max values for moving image are set (correctly)
+ if ((parms->mi_moving_image_minVal!=0
+ || parms->mi_moving_image_maxVal!=0)
+ && (parms->mi_moving_image_minVal <
+ parms->mi_moving_image_maxVal))
{
bool fill=!m_roi;
- //create new moving roi if not available
+ // create new moving roi if not available
if (!m_roi)
{
m_roi = Volume::New ();
@@ -176,50 +164,47 @@ Bspline_stage::initialize ()
moving->direction_cosines, PT_UCHAR);
}
- //Modify fixed roi according to min and max values for moving image
- update_roi (m_roi, moving, bsp_parms->mi_moving_image_minVal,
- bsp_parms->mi_moving_image_maxVal,fill);
+ // Modify fixed roi according to min and max values for moving image
+ update_roi (m_roi, moving, parms->mi_moving_image_minVal,
+ parms->mi_moving_image_maxVal,fill);
}
- //Check if min/max values for fixed image are set (correctly)
- if ((bsp_parms->mi_fixed_image_minVal!=0
- || bsp_parms->mi_fixed_image_maxVal!=0)
- && (bsp_parms->mi_fixed_image_minVal <
- bsp_parms->mi_fixed_image_maxVal))
+ // Check if min/max values for fixed image are set (correctly)
+ if ((parms->mi_fixed_image_minVal!=0
+ || parms->mi_fixed_image_maxVal!=0)
+ && (parms->mi_fixed_image_minVal <
+ parms->mi_fixed_image_maxVal))
{
bool fill=!f_roi;
- //create new fixed roi if not available
- if(!f_roi)
+ // create new fixed roi if not available
+ if (!f_roi)
{
f_roi = Volume::New ();
f_roi->create (fixed->dim, fixed->origin, fixed->spacing,
fixed->direction_cosines, PT_UCHAR);
}
- //Modify fixed roi according to min and max values for fixed image
- update_roi (f_roi, fixed, bsp_parms->mi_fixed_image_minVal,
- bsp_parms->mi_fixed_image_maxVal, fill);
+ // Modify fixed roi according to min and max values for fixed image
+ update_roi (f_roi, fixed, parms->mi_fixed_image_minVal,
+ parms->mi_fixed_image_maxVal, fill);
}
/* Subsample rois (if we are using them) */
if (m_roi) {
- d_ptr->m_roi_ss = volume_subsample_vox_legacy_nn (
- m_roi, stage->resample_rate_moving);
+ Volume::Pointer m_roi_ss =
+ volume_subsample_vox_legacy_nn (
+ m_roi, stage->resample_rate_moving);
+ bst->similarity_data.front()->moving_roi = m_roi_ss;
}
if (f_roi) {
- d_ptr->f_roi_ss = volume_subsample_vox_legacy_nn (
- f_roi, stage->resample_rate_fixed);
+ Volume::Pointer f_roi_ss =
+ volume_subsample_vox_legacy_nn (
+ f_roi, stage->resample_rate_fixed);
+ bst->similarity_data.front()->fixed_roi = f_roi_ss;
}
- logfile_printf ("moving_ss size = %d %d %d\n",
- d_ptr->moving_ss->dim[0],
- d_ptr->moving_ss->dim[1],
- d_ptr->moving_ss->dim[2]);
- logfile_printf ("fixed_ss size = %d %d %d\n",
- d_ptr->fixed_ss->dim[0],
- d_ptr->fixed_ss->dim[1],
- d_ptr->fixed_ss->dim[2]);
+ /* GCS FIX END */
/* Subsample stiffness */
if (shared->fixed_stiffness_enable && regd->fixed_stiffness) {
@@ -229,122 +214,98 @@ Bspline_stage::initialize ()
stiffness, stage, stage->resample_rate_fixed);
}
- /* Make spatial gradient image */
- Volume *moving_grad = volume_make_gradient (d_ptr->moving_ss.get());
- d_ptr->moving_grad = Volume::New (moving_grad);
-
- /* --- Initialize parms --- */
-
- /* Images */
- bsp_parms->fixed = d_ptr->fixed_ss.get();
- bsp_parms->moving = d_ptr->moving_ss.get();
- bsp_parms->moving_grad = d_ptr->moving_grad.get();
- if (f_roi) {
- bsp_parms->fixed_roi = d_ptr->f_roi_ss.get();
- }
- if (m_roi) {
- bsp_parms->moving_roi = d_ptr->m_roi_ss.get();
- }
+ /* Stiffness image */
if (d_ptr->f_stiffness_ss) {
- bsp_parms->fixed_stiffness = d_ptr->f_stiffness_ss.get();
+ parms->fixed_stiffness = d_ptr->f_stiffness_ss.get();
}
/* Optimization */
if (stage->optim_type == OPTIMIZATION_STEEPEST) {
- bsp_parms->optimization = BOPT_STEEPEST;
+ parms->optimization = BOPT_STEEPEST;
} else if (stage->optim_type == OPTIMIZATION_LIBLBFGS) {
- bsp_parms->optimization = BOPT_LIBLBFGS;
+ parms->optimization = BOPT_LIBLBFGS;
} else {
- bsp_parms->optimization = BOPT_LBFGSB;
- }
- bsp_parms->lbfgsb_pgtol = stage->pgtol;
- bsp_parms->lbfgsb_mmax = stage->lbfgsb_mmax;
-
- /* Metric */
- bsp_parms->metric_type = stage->metric_type;
- bsp_parms->metric_lambda = stage->metric_lambda;
- for (size_t i = 0; i < stage->metric_type.size(); i++) {
- if (bsp_parms->metric_type[i] == REGISTRATION_METRIC_MI_VW) {
- bsp_parms->metric_type[i] = REGISTRATION_METRIC_MI_MATTES;
- }
+ parms->optimization = BOPT_LBFGSB;
}
+ parms->lbfgsb_pgtol = stage->pgtol;
+ parms->lbfgsb_mmax = stage->lbfgsb_mmax;
/* Threading */
switch (stage->threading_type) {
case THREADING_CPU_SINGLE:
if (stage->alg_flavor == 0) {
- bsp_parms->implementation = 'h';
+ parms->implementation = 'h';
} else {
- bsp_parms->implementation = stage->alg_flavor;
+ parms->implementation = stage->alg_flavor;
}
- bsp_parms->threading = BTHR_CPU;
+ parms->threading = BTHR_CPU;
break;
case THREADING_CPU_OPENMP:
if (stage->alg_flavor == 0) {
- bsp_parms->implementation = 'g';
+ parms->implementation = 'g';
} else {
- bsp_parms->implementation = stage->alg_flavor;
+ parms->implementation = stage->alg_flavor;
}
- bsp_parms->threading = BTHR_CPU;
+ parms->threading = BTHR_CPU;
break;
case THREADING_CUDA:
if (stage->alg_flavor == 0) {
- bsp_parms->implementation = 'j';
+ parms->implementation = 'j';
} else {
- bsp_parms->implementation = stage->alg_flavor;
+ parms->implementation = stage->alg_flavor;
}
- bsp_parms->threading = BTHR_CUDA;
+ parms->threading = BTHR_CUDA;
break;
default:
print_and_exit ("Undefined impl type in gpuit_bspline\n");
}
- logfile_printf ("Algorithm flavor = %c\n", bsp_parms->implementation);
- logfile_printf ("Threading = %d\n", bsp_parms->threading);
+ logfile_printf ("Algorithm flavor = %c\n", parms->implementation);
+ logfile_printf ("Threading = %d\n", parms->threading);
if (stage->threading_type == THREADING_CUDA) {
- bsp_parms->gpuid = stage->gpuid;
- logfile_printf ("GPU ID = %d\n", bsp_parms->gpuid);
+ parms->gpuid = stage->gpuid;
+ logfile_printf ("GPU ID = %d\n", parms->gpuid);
}
/* Regularization */
- bsp_parms->reg_parms->lambda = stage->regularization_lambda;
+ parms->reg_parms->lambda = stage->regularization_lambda;
switch (stage->regularization_type) {
case REGULARIZATION_NONE:
- bsp_parms->reg_parms->lambda = 0.0f;
+ parms->reg_parms->lambda = 0.0f;
break;
case REGULARIZATION_BSPLINE_ANALYTIC:
if (stage->threading_type == THREADING_CPU_OPENMP) {
- bsp_parms->reg_parms->implementation = 'c';
+ parms->reg_parms->implementation = 'c';
} else {
- bsp_parms->reg_parms->implementation = 'b';
+ parms->reg_parms->implementation = 'b';
}
break;
case REGULARIZATION_BSPLINE_SEMI_ANALYTIC:
- bsp_parms->reg_parms->implementation = 'd';
+ parms->reg_parms->implementation = 'd';
break;
case REGULARIZATION_BSPLINE_NUMERIC:
- bsp_parms->reg_parms->implementation = 'a';
+ parms->reg_parms->implementation = 'a';
break;
default:
print_and_exit ("Undefined regularization type in gpuit_bspline\n");
}
if (stage->regularization_lambda != 0) {
- bsp_parms->reg_parms->lambda = stage->regularization_lambda;
+ parms->reg_parms->lambda = stage->regularization_lambda;
}
logfile_printf ("Regularization: flavor = %c lambda = %f\n",
- bsp_parms->reg_parms->implementation,
- bsp_parms->reg_parms->lambda);
+ parms->reg_parms->implementation,
+ parms->reg_parms->lambda);
/* Mutual information histograms */
- bsp_parms->mi_hist_type = stage->mi_hist_type;
- bsp_parms->mi_hist_fixed_bins = stage->mi_hist_fixed_bins;
- bsp_parms->mi_hist_moving_bins = stage->mi_hist_moving_bins;
+ parms->mi_hist_type = stage->mi_hist_type;
+ parms->mi_hist_fixed_bins = stage->mi_hist_fixed_bins;
+ parms->mi_hist_moving_bins = stage->mi_hist_moving_bins;
/* Other stuff */
- bsp_parms->min_its = stage->min_its;
- bsp_parms->max_its = stage->max_its;
- bsp_parms->max_feval = stage->max_its;
- bsp_parms->convergence_tol = stage->convergence_tol;
+ parms->min_its = stage->min_its;
+ parms->max_its = stage->max_its;
+ parms->max_feval = stage->max_its;
+ parms->convergence_tol = stage->convergence_tol;
/* Landmarks */
if (regd->fixed_landmarks && regd->moving_landmarks) {
@@ -352,37 +313,34 @@ Bspline_stage::initialize ()
regd->fixed_landmarks->get_count(),
regd->moving_landmarks->get_count(),
stage->landmark_stiffness);
- bsp_parms->blm->set_landmarks (regd->fixed_landmarks,
+ parms->blm->set_landmarks (regd->fixed_landmarks,
regd->moving_landmarks);
- bsp_parms->blm->landmark_implementation = stage->landmark_flavor;
- bsp_parms->blm->landmark_stiffness = stage->landmark_stiffness;
+ parms->blm->landmark_implementation = stage->landmark_flavor;
+ parms->blm->landmark_stiffness = stage->landmark_stiffness;
}
- /* Transform input xform to gpuit vector field */
- pih.set_from_gpuit (d_ptr->fixed_ss->dim,
- d_ptr->fixed_ss->origin, d_ptr->fixed_ss->spacing,
- d_ptr->fixed_ss->direction_cosines);
- xform_to_gpuit_bsp (xf_out, xf_in, &pih, stage->grid_spac);
-
/* Set debugging directory */
if (stage->debug_dir != "") {
- bsp_parms->debug = 1;
- bsp_parms->debug_dir = stage->debug_dir;
- bsp_parms->debug_stage = stage->stage_no;
+ parms->debug = 1;
+ parms->debug_dir = stage->debug_dir;
+ parms->debug_stage = stage->stage_no;
logfile_printf ("Set debug directory to %s (%d)\n",
- bsp_parms->debug_dir.c_str(), bsp_parms->debug_stage);
+ parms->debug_dir.c_str(), parms->debug_stage);
/* Write fixed, moving, moving_grad */
std::string fn;
- fn = string_format ("%s/%02d/moving.mha",
- bsp_parms->debug_dir.c_str(), bsp_parms->debug_stage);
- write_mha (fn.c_str(), d_ptr->moving_ss.get());
fn = string_format ("%s/%02d/fixed.mha",
- bsp_parms->debug_dir.c_str(), bsp_parms->debug_stage);
- write_mha (fn.c_str(), d_ptr->fixed_ss.get());
+ parms->debug_dir.c_str(), parms->debug_stage);
+ write_mha (fn.c_str(),
+ bst->similarity_data.front()->fixed_ss.get());
+ fn = string_format ("%s/%02d/moving.mha",
+ parms->debug_dir.c_str(), parms->debug_stage);
+ write_mha (fn.c_str(),
+ bst->similarity_data.front()->moving_ss.get());
fn = string_format ("%s/%02d/moving_grad.mha",
- bsp_parms->debug_dir.c_str(), bsp_parms->debug_stage);
- write_mha (fn.c_str(), d_ptr->moving_grad.get());
+ parms->debug_dir.c_str(), parms->debug_stage);
+ write_mha (fn.c_str(),
+ bst->similarity_data.front()->moving_grad.get());
}
}
@@ -393,13 +351,12 @@ Bspline_stage::cleanup ()
Xform::Pointer
do_gpuit_bspline_stage (
- Registration_parms* regp,
Registration_data* regd,
const Xform::Pointer& xf_in,
const Stage_parms* stage)
{
Xform::Pointer xf_out = Xform::New ();
- Bspline_stage pb (regp, regd, stage, xf_in.get());
+ Bspline_stage pb (regd, stage, xf_in.get());
pb.run_stage ();
xf_out = pb.d_ptr->xf_out;
return xf_out;
diff --git a/src/plastimatch/register/bspline_stage.h b/src/plastimatch/register/bspline_stage.h
index f8413ac..7107d20 100644
--- a/src/plastimatch/register/bspline_stage.h
+++ b/src/plastimatch/register/bspline_stage.h
@@ -18,7 +18,6 @@ public:
Bspline_stage_private *d_ptr;
public:
Bspline_stage (
- Registration_parms *regp,
Registration_data *regd,
const Stage_parms *stage,
Xform *xf_in);
@@ -33,7 +32,6 @@ protected:
Xform::Pointer
do_gpuit_bspline_stage (
- Registration_parms* regp,
Registration_data* regd,
const Xform::Pointer& xf_in,
const Stage_parms* stage);
diff --git a/src/plastimatch/register/bspline_state.cxx b/src/plastimatch/register/bspline_state.cxx
index 2071e7f..1cbb039 100644
--- a/src/plastimatch/register/bspline_state.cxx
+++ b/src/plastimatch/register/bspline_state.cxx
@@ -19,7 +19,6 @@
#include "bspline_interpolate.h"
#include "bspline_landmarks.h"
#include "bspline_mi.h"
-#include "bspline_mi_hist.h"
#include "bspline_mse.h"
#include "bspline_parms.h"
#include "bspline_regularize.h"
@@ -28,27 +27,27 @@
#include "delayload.h"
#include "file_util.h"
#include "interpolate_macros.h"
+#include "joint_histogram.h"
#include "logfile.h"
#include "plm_math.h"
#include "string_util.h"
-#include "registration_metric_type.h"
+#include "similarity_metric_type.h"
#include "volume.h"
#include "volume_macros.h"
static void
bspline_cuda_state_create (
- Bspline_xform* bxf,
+ Bspline_parms *parms,
Bspline_state *bst,
- Bspline_parms *parms
+ Bspline_xform* bxf
);
static void
bspline_cuda_state_destroy (
+ Bspline_parms *parms,
Bspline_state *bst,
- Bspline_parms *parms,
- Bspline_xform *bxf
+ Bspline_xform* bxf
);
-
class Bspline_state_private
{
public:
@@ -68,11 +67,12 @@ public:
Bspline_state::Bspline_state ()
{
d_ptr = new Bspline_state_private;
+ mi_hist = 0;
}
Bspline_state::~Bspline_state ()
{
- bspline_cuda_state_destroy (this, d_ptr->parms, d_ptr->bxf);
+ bspline_cuda_state_destroy (d_ptr->parms, this, d_ptr->bxf);
delete d_ptr;
}
@@ -97,62 +97,83 @@ Bspline_state::initialize (
this->ssd.set_num_coeff (bxf->num_coeff);
if (reg_parms->lambda > 0.0f) {
- rst->fixed = parms->fixed;
- rst->moving = parms->moving;
rst->fixed_stiffness = parms->fixed_stiffness;
rst->initialize (reg_parms, bxf);
}
/* Initialize MI histograms */
- this->mi_hist = 0;
- if (parms->metric_type[0] == REGISTRATION_METRIC_MI_MATTES) {
- this->mi_hist = new Bspline_mi_hist_set (
- parms->mi_hist_type,
- parms->mi_hist_fixed_bins,
- parms->mi_hist_moving_bins);
+ printf (">> Checking JH allocation\n");
+ std::list<Metric_state::Pointer>::const_iterator it;
+ for (it = this->similarity_data.begin();
+ it != this->similarity_data.end(); ++it)
+ {
+ const Metric_state::Pointer& ms = *it;
+ if (ms->metric_type == SIMILARITY_METRIC_MI_MATTES) {
+ printf (">> Performing JH allocation\n");
+ ms->mi_hist = new Joint_histogram (
+ parms->mi_hist_type,
+ parms->mi_hist_fixed_bins,
+ parms->mi_hist_moving_bins);
+ }
}
- bspline_cuda_state_create (bxf, this, parms);
-
- /* JAS Fix 2011.09.14
- * The MI algorithm will get stuck for a set of coefficients all equaling
- * zero due to the method we use to compute the cost function gradient.
- * However, it is possible we could be inheriting coefficients from a
- * prior stage, so we must check for inherited coefficients before
- * applying an initial offset to the coefficient array. */
- if (parms->metric_type[0] == REGISTRATION_METRIC_MI_MATTES) {
- bool first_iteration = true;
+ /* Landmarks */
+ blm->initialize (bxf);
+}
- for (int i=0; i<bxf->num_coeff; i++) {
- if (bxf->coeff[i] != 0.0f) {
- first_iteration = false;
- break;
- }
- }
+void
+Bspline_state::initialize_similarity_images ()
+{
+ /* GCS FIX: The below function also does other initializations
+ which do not require the similarity images, and therefore could
+ be done once per stage rather than once per image
+ */
+ /* Copy images into CUDA memory */
+ bspline_cuda_state_create (d_ptr->parms, this, d_ptr->bxf);
+}
- if (first_iteration) {
- printf ("Initializing 1st MI Stage\n");
- for (int i = 0; i < bxf->num_coeff; i++) {
- bxf->coeff[i] = 0.01f;
- }
+void
+Bspline_state::initialize_mi_histograms ()
+{
+ std::list<Metric_state::Pointer>::const_iterator it;
+ for (it = this->similarity_data.begin();
+ it != this->similarity_data.end(); ++it)
+ {
+ const Metric_state::Pointer& ms = *it;
+ if (ms->metric_type == SIMILARITY_METRIC_MI_MATTES) {
+ printf (">> Performing JH initialization\n");
+ ms->mi_hist->initialize (
+ ms->fixed_ss.get(),
+ ms->moving_ss.get());
}
}
+}
- /* Landmarks */
- blm->initialize (bxf);
+void
+Bspline_state::set_metric_state (const Metric_state::Pointer& ms)
+{
+ this->fixed = ms->fixed_ss.get();
+ this->moving = ms->moving_ss.get();
+ this->moving_grad = ms->moving_grad.get();
+ this->fixed_roi = ms->fixed_roi.get();
+ this->moving_roi = ms->moving_roi.get();
+ this->mi_hist = ms->mi_hist;
}
static void
bspline_cuda_state_create (
- Bspline_xform* bxf,
- Bspline_state *bst, /* Modified in routine */
- Bspline_parms *parms
+ Bspline_parms *parms,
+ Bspline_state *bst,
+ Bspline_xform *bxf
)
{
#if (CUDA_FOUND)
if (parms->threading != BTHR_CUDA) {
return;
}
+ if (bst->dev_ptrs) {
+ bspline_cuda_state_destroy (parms, bst, bxf);
+ }
/* Set the gpuid */
LOAD_LIBRARY_SAFE (libplmcuda);
@@ -160,15 +181,17 @@ bspline_cuda_state_create (
CUDA_selectgpu (parms->gpuid);
UNLOAD_LIBRARY (libplmcuda);
- Volume *fixed = parms->fixed;
- Volume *moving = parms->moving;
- Volume *moving_grad = parms->moving_grad;
+ Volume *fixed = bst->fixed;
+ Volume *moving = bst->moving;
+ Volume *moving_grad = bst->moving_grad;
Dev_Pointers_Bspline* dev_ptrs
= (Dev_Pointers_Bspline*) malloc (sizeof (Dev_Pointers_Bspline));
bst->dev_ptrs = dev_ptrs;
-
- if (parms->metric_type[0] == REGISTRATION_METRIC_MSE) {
+
+ /* GCS FIX: You cannot have more than one CUDA metric because
+ dev_ptrs is not defined per metric */
+ if (bst->has_metric_type (SIMILARITY_METRIC_MSE)) {
/* Be sure we loaded the CUDA plugin */
LOAD_LIBRARY_SAFE (libplmregistercuda);
LOAD_SYMBOL (CUDA_bspline_mse_init_j, libplmregistercuda);
@@ -187,7 +210,7 @@ bspline_cuda_state_create (
UNLOAD_LIBRARY (libplmregistercuda);
}
- else if (parms->metric_type[0] == REGISTRATION_METRIC_MI_MATTES) {
+ else if (bst->has_metric_type (SIMILARITY_METRIC_MI_MATTES)) {
/* Be sure we loaded the CUDA plugin */
LOAD_LIBRARY_SAFE (libplmregistercuda);
LOAD_SYMBOL (CUDA_bspline_mi_init_a, libplmregistercuda);
@@ -213,8 +236,8 @@ bspline_cuda_state_create (
static void
bspline_cuda_state_destroy (
- Bspline_state *bst,
Bspline_parms *parms,
+ Bspline_state *bst,
Bspline_xform *bxf
)
{
@@ -223,82 +246,59 @@ bspline_cuda_state_destroy (
return;
}
- Volume *fixed = parms->fixed;
- Volume *moving = parms->moving;
- Volume *moving_grad = parms->moving_grad;
+ Volume *fixed = bst->fixed;
+ Volume *moving = bst->moving;
+ Volume *moving_grad = bst->moving_grad;
- if (parms->metric_type[0] == REGISTRATION_METRIC_MSE) {
+ if (bst->has_metric_type (SIMILARITY_METRIC_MSE)) {
LOAD_LIBRARY_SAFE (libplmregistercuda);
LOAD_SYMBOL (CUDA_bspline_mse_cleanup_j, libplmregistercuda);
CUDA_bspline_mse_cleanup_j ((Dev_Pointers_Bspline *) bst->dev_ptrs, fixed, moving, moving_grad);
UNLOAD_LIBRARY (libplmregistercuda);
}
- else if (parms->metric_type[0] == REGISTRATION_METRIC_MI_MATTES) {
+ else if (bst->has_metric_type (SIMILARITY_METRIC_MI_MATTES)) {
LOAD_LIBRARY_SAFE (libplmregistercuda);
LOAD_SYMBOL (CUDA_bspline_mi_cleanup_a, libplmregistercuda);
CUDA_bspline_mi_cleanup_a ((Dev_Pointers_Bspline *) bst->dev_ptrs, fixed, moving, moving_grad);
UNLOAD_LIBRARY (libplmregistercuda);
}
-#endif
+
free (bst->dev_ptrs);
+ bst->dev_ptrs = 0;
+#endif
}
-Bspline_state *
-bspline_state_create (
- Bspline_xform *bxf,
- Bspline_parms *parms
-)
+bool
+Bspline_state::has_metric_type (Similarity_metric_type metric_type)
{
- Bspline_state *bst = (Bspline_state*) malloc (sizeof (Bspline_state));
- Regularization_parms* reg_parms = parms->reg_parms;
- Bspline_regularize* rst = &bst->rst;
- Bspline_landmarks* blm = parms->blm;
-
- memset (bst, 0, sizeof (Bspline_state));
- bst->ssd.set_num_coeff (bxf->num_coeff);
-
- if (reg_parms->lambda > 0.0f) {
- rst->fixed = parms->fixed;
- rst->moving = parms->moving;
- rst->initialize (reg_parms, bxf);
- }
-
- /* Initialize MI histograms */
- bst->mi_hist = 0;
- if (parms->metric_type[0] == REGISTRATION_METRIC_MI_MATTES) {
- bst->mi_hist = new Bspline_mi_hist_set (
- parms->mi_hist_type,
- parms->mi_hist_fixed_bins,
- parms->mi_hist_moving_bins);
- }
- bspline_cuda_state_create (bxf, bst, parms);
-
- /* JAS Fix 2011.09.14
- * The MI algorithm will get stuck for a set of coefficients all equaling
- * zero due to the method we use to compute the cost function gradient.
- * However, it is possible we could be inheriting coefficients from a
- * prior stage, so we must check for inherited coefficients before
- * applying an initial offset to the coefficient array. */
- if (parms->metric_type[0] == REGISTRATION_METRIC_MI_MATTES) {
- bool first_iteration = true;
-
- for (int i=0; i<bxf->num_coeff; i++) {
- if (bxf->coeff[i] != 0.0f) {
- first_iteration = false;
- break;
- }
- }
-
- if (first_iteration) {
- printf ("Initializing 1st MI Stage\n");
- for (int i = 0; i < bxf->num_coeff; i++) {
- bxf->coeff[i] = 0.01f;
- }
+ std::list<Metric_state::Pointer>::iterator it;
+ for (it = this->similarity_data.begin();
+ it != this->similarity_data.end(); ++it)
+ {
+ if ((*it)->metric_type == metric_type) {
+ return true;
}
}
+ return false;
+}
- /* Landmarks */
- blm->initialize (bxf);
-
- return bst;
+void
+Bspline_state::log_metric ()
+{
+ printf ("BST METRICS\n");
+ std::list<Metric_state::Pointer>::iterator it;
+ for (it = this->similarity_data.begin();
+ it != this->similarity_data.end(); ++it)
+ {
+ printf ("MET %c%c%c%c%c%c %s %f\n",
+ (*it)->fixed_ss ? '1' : '0',
+ (*it)->moving_ss ? '1' : '0',
+ (*it)->fixed_grad ? '1' : '0',
+ (*it)->moving_grad ? '1' : '0',
+ (*it)->fixed_roi ? '1' : '0',
+ (*it)->moving_roi ? '1' : '0',
+ (*it)->metric_string(),
+ (*it)->metric_lambda
+ );
+ }
}
diff --git a/src/plastimatch/register/bspline_state.h b/src/plastimatch/register/bspline_state.h
index 18645d7..fbe611b 100644
--- a/src/plastimatch/register/bspline_state.h
+++ b/src/plastimatch/register/bspline_state.h
@@ -5,16 +5,18 @@
#define _bspline_state_h_
#include "plmregister_config.h"
+#include <list>
#include <string>
-#include "bspline_mi_hist.h"
#include "bspline_regularize.h"
#include "bspline_score.h"
+#include "metric_state.h"
#include "plm_int.h"
#include "smart_pointer.h"
class Bspline_state_private;
class Bspline_parms;
+class Joint_histogram;
class PLMREGISTER_API Bspline_state {
public:
@@ -23,19 +25,44 @@ public:
public:
Bspline_state ();
~Bspline_state ();
- void initialize (Bspline_xform *bxf, Bspline_parms *parms);
public:
int sm; /* Current smetric */
int it; /* Current iterations */
int feval; /* Number of function evaluations */
Bspline_score ssd; /* Score and Gradient */
void* dev_ptrs; /* GPU Device Pointers */
- Bspline_regularize rst; /* Analytic regularization */
- Bspline_mi_hist_set *mi_hist; /* MI histograms */
+
+ /* Similarity metric */
+ std::list<Metric_state::Pointer> similarity_data;
+
+ /*! \brief Current similarity images. These are raw pointers
+ because they are passed to CUDA code. */
+ Volume *fixed;
+ Volume *moving;
+ Volume *moving_grad;
+ Volume *fixed_roi;
+ Volume *moving_roi;
+
+ Bspline_regularize rst;
+
+protected:
+ /*! \brief Current joint histogram. This is raw pointer
+ because it is passed to CUDA code. */
+ Joint_histogram *mi_hist;
+
public:
+ void initialize (Bspline_xform *bxf, Bspline_parms *parms);
+ void initialize_similarity_images ();
+ void initialize_mi_histograms ();
+ void set_metric_state (const Metric_state::Pointer& ms);
Bspline_score* get_bspline_score () {
return &ssd;
}
+ Joint_histogram* get_mi_hist () {
+ return mi_hist;
+ }
+ bool has_metric_type (Similarity_metric_type metric_type);
+ void log_metric ();
};
#endif
diff --git a/src/plastimatch/register/cuda/CMakeLists.txt b/src/plastimatch/register/cuda/CMakeLists.txt
old mode 100755
new mode 100644
index 1e31bc4..5a10bba
--- a/src/plastimatch/register/cuda/CMakeLists.txt
+++ b/src/plastimatch/register/cuda/CMakeLists.txt
@@ -30,9 +30,6 @@ set (PLMREGISTERCUDA_SRC
set (PLMREGISTERCUDA_IFACE_SRC
bspline_cuda.cxx
-# GCS: I hope this can be linked from base instead of duplicated,
-# but we'll just have to see.
-# gaussian.cxx
)
if (PLM_BUILD_VISCOUS)
diff --git a/src/plastimatch/register/cuda/bspline_cuda.cu b/src/plastimatch/register/cuda/bspline_cuda.cu
index 2174513..16fdc16 100644
--- a/src/plastimatch/register/cuda/bspline_cuda.cu
+++ b/src/plastimatch/register/cuda/bspline_cuda.cu
@@ -12,12 +12,12 @@
#include "bspline.h"
#include "bspline_cuda.h"
#include "bspline_cuda_kernels.h"
-#include "bspline_mi_hist.h"
#include "bspline_state.h"
#include "bspline_xform.h"
#include "cuda_util.h"
#include "cuda_mem.h"
#include "cuda_kernel_util.h"
+#include "joint_histogram.h"
#include "plm_int.h"
#include "volume.h"
@@ -78,7 +78,7 @@ CUDA_bspline_mi_init_a (
Volume* moving_grad
)
{
- Bspline_mi_hist_set* mi_hist = bst->mi_hist;
+ Joint_histogram* mi_hist = bst->get_mi_hist();
// Keep track of how much memory we allocated in the GPU global memory.
long unsigned GPU_Memory_Bytes = 0;
@@ -400,7 +400,8 @@ CUDA_bspline_mse_init_j (
long unsigned GPU_Memory_Bytes = 0;
printf ("Allocating GPU Memory");
-
+ fflush (stdout);
+
// Fixed Image (zero copy if possible)
// ----------------------------------------------------------
dev_ptrs->fixed_image_size = fixed->npix * fixed->pix_size;
@@ -761,7 +762,7 @@ CUDA_bspline_mi_cleanup_a (
int
CUDA_bspline_mi_hist (
Dev_Pointers_Bspline *dev_ptrs,
- Bspline_mi_hist_set* mi_hist,
+ Joint_histogram* mi_hist,
Volume* fixed,
Volume* moving,
Bspline_xform* bxf)
@@ -781,7 +782,7 @@ CUDA_bspline_mi_hist (
void
CUDA_bspline_mi_hist_fix (
Dev_Pointers_Bspline *dev_ptrs,
- Bspline_mi_hist_set* mi_hist,
+ Joint_histogram* mi_hist,
Volume* fixed,
Volume* moving,
Bspline_xform *bxf)
@@ -883,7 +884,7 @@ CUDA_bspline_mi_hist_fix (
void
CUDA_bspline_mi_hist_mov (
Dev_Pointers_Bspline *dev_ptrs,
- Bspline_mi_hist_set* mi_hist,
+ Joint_histogram* mi_hist,
Volume* fixed,
Volume* moving,
Bspline_xform *bxf)
@@ -986,7 +987,7 @@ CUDA_bspline_mi_hist_mov (
int
CUDA_bspline_mi_hist_jnt (
Dev_Pointers_Bspline *dev_ptrs,
- Bspline_mi_hist_set* mi_hist,
+ Joint_histogram* mi_hist,
Volume* fixed,
Volume* moving,
Bspline_xform *bxf)
@@ -1157,12 +1158,12 @@ CUDA_bspline_mi_grad (
Dev_Pointers_Bspline *dev_ptrs
)
{
- Bspline_mi_hist_set* mi_hist = bst->mi_hist;
+ Joint_histogram* mi_hist = bst->get_mi_hist();
GPU_Bspline_Data gbd;
build_gbd (&gbd, bxf, fixed, moving);
Bspline_score* ssd = &bst->ssd;
- float* host_grad = ssd->smetric_grad;
+ float* host_grad = ssd->curr_smetric_grad;
if ((mi_hist->fixed.bins > GPU_MAX_BINS) ||
(mi_hist->moving.bins > GPU_MAX_BINS)) {
diff --git a/src/plastimatch/register/cuda/bspline_cuda.cxx b/src/plastimatch/register/cuda/bspline_cuda.cxx
index 3a98a40..9e4b745 100644
--- a/src/plastimatch/register/cuda/bspline_cuda.cxx
+++ b/src/plastimatch/register/cuda/bspline_cuda.cxx
@@ -125,7 +125,7 @@ bspline_find_correspondence
static inline void
bspline_mi_hist_add_pvi_8 (
- Bspline_mi_hist_set* mi_hist,
+ Joint_histogram* mi_hist,
Volume *fixed,
Volume *moving,
int fv,
@@ -223,7 +223,7 @@ bspline_mi_hist_add_pvi_8 (
static inline void
bspline_mi_pvi_8_dc_dv (
float dc_dv[3], /* Output */
- Bspline_mi_hist_set* mi_hist, /* Input */
+ Joint_histogram* mi_hist, /* Input */
Bspline_state *bst, /* Input */
Volume *fixed, /* Input */
Volume *moving, /* Input */
@@ -300,7 +300,7 @@ bspline_mi_pvi_8_dc_dv (
idx_mbin = floor ((m_img[n1] - mi_hist->moving.offset) / mi_hist->moving.delta);
idx_jbin = offset_fbin + idx_mbin;
if (j_hist[idx_jbin] > 0.0001) {
- dS_dP = logf((num_vox_f * j_hist[idx_jbin]) / (f_hist[idx_fbin] * m_hist[idx_mbin])) - ssd->score;
+ dS_dP = logf((num_vox_f * j_hist[idx_jbin]) / (f_hist[idx_fbin] * m_hist[idx_mbin])) - ssd->curr_smetric;
dc_dv[0] -= dw1[0] * dS_dP;
dc_dv[1] -= dw1[1] * dS_dP;
dc_dv[2] -= dw1[2] * dS_dP;
@@ -310,7 +310,7 @@ bspline_mi_pvi_8_dc_dv (
idx_mbin = floor ((m_img[n2] - mi_hist->moving.offset) / mi_hist->moving.delta);
idx_jbin = offset_fbin + idx_mbin;
if (j_hist[idx_jbin] > 0.0001) {
- dS_dP = logf((num_vox_f * j_hist[idx_jbin]) / (f_hist[idx_fbin] * m_hist[idx_mbin])) - ssd->score;
+ dS_dP = logf((num_vox_f * j_hist[idx_jbin]) / (f_hist[idx_fbin] * m_hist[idx_mbin])) - ssd->curr_smetric;
dc_dv[0] -= dw2[0] * dS_dP;
dc_dv[1] -= dw2[1] * dS_dP;
dc_dv[2] -= dw2[2] * dS_dP;
@@ -320,7 +320,7 @@ bspline_mi_pvi_8_dc_dv (
idx_mbin = floor ((m_img[n3] - mi_hist->moving.offset) / mi_hist->moving.delta);
idx_jbin = offset_fbin + idx_mbin;
if (j_hist[idx_jbin] > 0.0001) {
- dS_dP = logf((num_vox_f * j_hist[idx_jbin]) / (f_hist[idx_fbin] * m_hist[idx_mbin])) - ssd->score;
+ dS_dP = logf((num_vox_f * j_hist[idx_jbin]) / (f_hist[idx_fbin] * m_hist[idx_mbin])) - ssd->curr_smetric;
dc_dv[0] -= dw3[0] * dS_dP;
dc_dv[1] -= dw3[1] * dS_dP;
dc_dv[2] -= dw3[2] * dS_dP;
@@ -330,7 +330,7 @@ bspline_mi_pvi_8_dc_dv (
idx_mbin = floor ((m_img[n4] - mi_hist->moving.offset) / mi_hist->moving.delta);
idx_jbin = offset_fbin + idx_mbin;
if (j_hist[idx_jbin] > 0.0001) {
- dS_dP = logf((num_vox_f * j_hist[idx_jbin]) / (f_hist[idx_fbin] * m_hist[idx_mbin])) - ssd->score;
+ dS_dP = logf((num_vox_f * j_hist[idx_jbin]) / (f_hist[idx_fbin] * m_hist[idx_mbin])) - ssd->curr_smetric;
dc_dv[0] -= dw4[0] * dS_dP;
dc_dv[1] -= dw4[1] * dS_dP;
dc_dv[2] -= dw4[2] * dS_dP;
@@ -340,7 +340,7 @@ bspline_mi_pvi_8_dc_dv (
idx_mbin = floor ((m_img[n5] - mi_hist->moving.offset) / mi_hist->moving.delta);
idx_jbin = offset_fbin + idx_mbin;
if (j_hist[idx_jbin] > 0.0001) {
- dS_dP = logf((num_vox_f * j_hist[idx_jbin]) / (f_hist[idx_fbin] * m_hist[idx_mbin])) - ssd->score;
+ dS_dP = logf((num_vox_f * j_hist[idx_jbin]) / (f_hist[idx_fbin] * m_hist[idx_mbin])) - ssd->curr_smetric;
dc_dv[0] -= dw5[0] * dS_dP;
dc_dv[1] -= dw5[1] * dS_dP;
dc_dv[2] -= dw5[2] * dS_dP;
@@ -350,7 +350,7 @@ bspline_mi_pvi_8_dc_dv (
idx_mbin = floor ((m_img[n6] - mi_hist->moving.offset) / mi_hist->moving.delta);
idx_jbin = offset_fbin + idx_mbin;
if (j_hist[idx_jbin] > 0.0001) {
- dS_dP = logf((num_vox_f * j_hist[idx_jbin]) / (f_hist[idx_fbin] * m_hist[idx_mbin])) - ssd->score;
+ dS_dP = logf((num_vox_f * j_hist[idx_jbin]) / (f_hist[idx_fbin] * m_hist[idx_mbin])) - ssd->curr_smetric;
dc_dv[0] -= dw6[0] * dS_dP;
dc_dv[1] -= dw6[1] * dS_dP;
dc_dv[2] -= dw6[2] * dS_dP;
@@ -360,7 +360,7 @@ bspline_mi_pvi_8_dc_dv (
idx_mbin = floor ((m_img[n7] - mi_hist->moving.offset) / mi_hist->moving.delta);
idx_jbin = offset_fbin + idx_mbin;
if (j_hist[idx_jbin] > 0.0001) {
- dS_dP = logf((num_vox_f * j_hist[idx_jbin]) / (f_hist[idx_fbin] * m_hist[idx_mbin])) - ssd->score;
+ dS_dP = logf((num_vox_f * j_hist[idx_jbin]) / (f_hist[idx_fbin] * m_hist[idx_mbin])) - ssd->curr_smetric;
dc_dv[0] -= dw7[0] * dS_dP;
dc_dv[1] -= dw7[1] * dS_dP;
dc_dv[2] -= dw7[2] * dS_dP;
@@ -370,7 +370,7 @@ bspline_mi_pvi_8_dc_dv (
idx_mbin = floor ((m_img[n8] - mi_hist->moving.offset) / mi_hist->moving.delta);
idx_jbin = offset_fbin + idx_mbin;
if (j_hist[idx_jbin] > 0.0001) {
- dS_dP = logf((num_vox_f * j_hist[idx_jbin]) / (f_hist[idx_fbin] * m_hist[idx_mbin])) - ssd->score;
+ dS_dP = logf((num_vox_f * j_hist[idx_jbin]) / (f_hist[idx_fbin] * m_hist[idx_mbin])) - ssd->curr_smetric;
dc_dv[0] -= dw8[0] * dS_dP;
dc_dv[1] -= dw8[1] * dS_dP;
dc_dv[2] -= dw8[2] * dS_dP;
@@ -408,7 +408,7 @@ bspline_update_grad_b_inline (Bspline_state* bst, Bspline_xform* bxf,
#endif
#if defined (commentout)
-static void display_hist_totals (Bspline_mi_hist_set *mi_hist)
+static void display_hist_totals (Joint_histogram *mi_hist)
{
plm_long i;
double tmp = 0;
@@ -433,7 +433,7 @@ static void display_hist_totals (Bspline_mi_hist_set *mi_hist)
////////////////////////////////////////////////////////////////////////////////
size_t
-CPU_MI_Hist (Bspline_mi_hist_set *mi_hist, // OUTPUT: Histograms
+CPU_MI_Hist (Joint_histogram *mi_hist, // OUTPUT: Histograms
Bspline_xform *bxf, // INPUT: Bspline X-Form
Volume* fixed, // INPUT: Fixed Image
Volume* moving) // INPUT: Moving Image
@@ -504,7 +504,7 @@ CPU_MI_Hist (Bspline_mi_hist_set *mi_hist, // OUTPUT: Histograms
static float
-CPU_MI_Score (Bspline_mi_hist_set* mi_hist, int num_vox)
+CPU_MI_Score (Joint_histogram* mi_hist, int num_vox)
{
double* f_hist = mi_hist->f_hist;
double* m_hist = mi_hist->m_hist;
@@ -530,7 +530,7 @@ CPU_MI_Score (Bspline_mi_hist_set* mi_hist, int num_vox)
#if defined (MI_GRAD_CPU)
void
-CPU_MI_Grad (Bspline_mi_hist_set *mi_hist, // OUTPUT: Histograms
+CPU_MI_Grad (Joint_histogram *mi_hist, // OUTPUT: Histograms
Bspline_state *bst, // INPUT: Bspline State
Bspline_xform *bxf, // INPUT: Bspline X-Form
Volume* fixed, // INPUT: Fixed Image
@@ -611,16 +611,16 @@ CUDA_bspline_mi_a (
Bspline_xform *bxf
)
{
- Volume *fixed = parms->fixed;
- Volume *moving = parms->moving;
- Volume *moving_grad = parms->moving_grad;
+ Volume *fixed = bst->fixed;
+ Volume *moving = bst->moving;
+ Volume *moving_grad = bst->moving_grad;
UNUSED_VARIABLE (moving_grad);
Dev_Pointers_Bspline* dev_ptrs = (Dev_Pointers_Bspline*)bst->dev_ptrs;
// --- DECLARE LOCAL VARIABLES ------------------------------
Bspline_score* ssd; // Holds the SSD "Score" information
- Bspline_mi_hist_set* mi_hist = bst->mi_hist;
+ Joint_histogram* mi_hist = bst->get_mi_hist();
double* f_hist = mi_hist->f_hist;
double* m_hist = mi_hist->m_hist;
double* j_hist = mi_hist->j_hist;
@@ -674,9 +674,9 @@ CUDA_bspline_mi_a (
if ((mi_hist->fixed.bins > GPU_MAX_BINS) ||
(mi_hist->moving.bins > GPU_MAX_BINS)) {
- ssd->num_vox = CPU_MI_Hist (mi_hist, bxf, fixed, moving);
+ ssd->curr_num_vox = CPU_MI_Hist (mi_hist, bxf, fixed, moving);
} else {
- ssd->num_vox = CUDA_bspline_mi_hist (dev_ptrs, mi_hist, fixed, moving, bxf);
+ ssd->curr_num_vox = CUDA_bspline_mi_hist (dev_ptrs, mi_hist, fixed, moving, bxf);
}
// ----------------------------------------------------------
@@ -698,7 +698,7 @@ CUDA_bspline_mi_a (
// --- COMPUTE SCORE ----------------------------------------
#if defined (MI_SCORE_CPU)
- ssd->smetric[0] = CPU_MI_Score(mi_hist, ssd->num_vox);
+ ssd->curr_smetric = CPU_MI_Score(mi_hist, ssd->curr_num_vox);
#else
// Doing this on the GPU may be silly.
// The CPU generally completes this computation extremely quickly
@@ -709,13 +709,13 @@ CUDA_bspline_mi_a (
#if defined (MI_GRAD_CPU)
CPU_MI_Grad(mi_hist, bst, bxf, fixed, moving, (float)ssd->num_vox);
#else
- float score = ssd->smetric[0];
+ float score = ssd->curr_smetric;
CUDA_bspline_mi_grad (
bst,
bxf,
fixed,
moving,
- (float)ssd->num_vox,
+ (float) ssd->curr_num_vox,
score,
dev_ptrs
);
@@ -727,8 +727,6 @@ CUDA_bspline_mi_a (
}
}
-
-
void
CUDA_bspline_mse_j (
Bspline_parms *parms,
@@ -736,9 +734,9 @@ CUDA_bspline_mse_j (
Bspline_xform *bxf
)
{
- Volume *fixed = parms->fixed;
- Volume *moving = parms->moving;
- Volume *moving_grad = parms->moving_grad;
+ Volume *fixed = bst->fixed;
+ Volume *moving = bst->moving;
+ Volume *moving_grad = bst->moving_grad;
Dev_Pointers_Bspline* dev_ptrs = (Dev_Pointers_Bspline*)bst->dev_ptrs;
@@ -789,12 +787,12 @@ CUDA_bspline_mse_j (
fixed,
bxf->vox_per_rgn,
fixed->dim,
- &(ssd->smetric[0]),
- bst->ssd.smetric_grad,
+ &(ssd->curr_smetric),
+ bst->ssd.curr_smetric_grad,
&ssd_grad_mean,
&ssd_grad_norm,
dev_ptrs,
- &(ssd->num_vox)
+ &(ssd->curr_num_vox)
);
if (parms->debug) {
diff --git a/src/plastimatch/register/cuda/bspline_cuda.h b/src/plastimatch/register/cuda/bspline_cuda.h
index d8e73e7..8588ed1 100644
--- a/src/plastimatch/register/cuda/bspline_cuda.h
+++ b/src/plastimatch/register/cuda/bspline_cuda.h
@@ -30,7 +30,7 @@
/* HARDWARE IMPOSED CONSTANTS */
#define GPU_MAX_BINS 32
-class Bspline_mi_hist_set;
+class Joint_histogram;
class Bspline_optimize;
class Bspline_parms;
class Bspline_state;
@@ -278,7 +278,7 @@ extern "C" {
int
CUDA_bspline_mi_hist (
Dev_Pointers_Bspline *dev_ptrs,
- Bspline_mi_hist_set* mi_hist,
+ Joint_histogram* mi_hist,
Volume* fixed,
Volume* moving,
Bspline_xform *bxf
@@ -287,7 +287,7 @@ extern "C" {
void
CUDA_bspline_mi_hist_fix (
Dev_Pointers_Bspline *dev_ptrs,
- Bspline_mi_hist_set* mi_hist,
+ Joint_histogram* mi_hist,
Volume* fixed,
Volume* moving,
Bspline_xform *bxf
@@ -296,7 +296,7 @@ extern "C" {
void
CUDA_bspline_mi_hist_mov (
Dev_Pointers_Bspline *dev_ptrs,
- Bspline_mi_hist_set* mi_hist,
+ Joint_histogram* mi_hist,
Volume* fixed,
Volume* moving,
Bspline_xform *bxf
@@ -305,7 +305,7 @@ extern "C" {
int
CUDA_bspline_mi_hist_jnt (
Dev_Pointers_Bspline *dev_ptrs,
- Bspline_mi_hist_set* mi_hist,
+ Joint_histogram* mi_hist,
Volume* fixed,
Volume* moving,
Bspline_xform *bxf
diff --git a/src/plastimatch/register/gpuit_demons.cxx b/src/plastimatch/register/gpuit_demons.cxx
index dd3fe32..103d0e1 100644
--- a/src/plastimatch/register/gpuit_demons.cxx
+++ b/src/plastimatch/register/gpuit_demons.cxx
@@ -29,8 +29,10 @@ do_gpuit_demons_stage_internal (
Demons_parms parms;
Plm_image_header pih;
- Volume::Pointer& fixed = regd->fixed_image->get_volume_float ();
- Volume::Pointer& moving = regd->moving_image->get_volume_float ();
+ Plm_image::Pointer fixed_image = regd->get_fixed_image();
+ Plm_image::Pointer moving_image = regd->get_moving_image();
+ Volume::Pointer& fixed = fixed_image->get_volume_float ();
+ Volume::Pointer& moving = moving_image->get_volume_float ();
Volume::Pointer moving_ss;
Volume::Pointer fixed_ss;
Volume::Pointer moving_grad;
diff --git a/src/plastimatch/register/bspline_gm.h b/src/plastimatch/register/groupwise_parms.cxx
old mode 100755
new mode 100644
similarity index 65%
copy from src/plastimatch/register/bspline_gm.h
copy to src/plastimatch/register/groupwise_parms.cxx
index 8520890..5d4fa8e
--- a/src/plastimatch/register/bspline_gm.h
+++ b/src/plastimatch/register/groupwise_parms.cxx
@@ -1,13 +1,14 @@
/* -----------------------------------------------------------------------
See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
----------------------------------------------------------------------- */
-#ifndef _bspline_gm_h_
-#define _bspline_gm_h_
-
#include "plmregister_config.h"
-class Bspline_optimize;
+#include "groupwise_parms.h"
-PLMREGISTER_API void bspline_score_gm (Bspline_optimize *bod);
+Groupwise_parms::Groupwise_parms()
+{
+}
-#endif
+Groupwise_parms::~Groupwise_parms()
+{
+}
diff --git a/src/plastimatch/register/bspline_gm.h b/src/plastimatch/register/groupwise_parms.h
old mode 100755
new mode 100644
similarity index 62%
copy from src/plastimatch/register/bspline_gm.h
copy to src/plastimatch/register/groupwise_parms.h
index 8520890..0c69eb3
--- a/src/plastimatch/register/bspline_gm.h
+++ b/src/plastimatch/register/groupwise_parms.h
@@ -1,13 +1,17 @@
/* -----------------------------------------------------------------------
See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
----------------------------------------------------------------------- */
-#ifndef _bspline_gm_h_
-#define _bspline_gm_h_
+#ifndef _groupwise_parms_h_
+#define _groupwise_parms_h_
#include "plmregister_config.h"
-class Bspline_optimize;
+class PLMREGISTER_API Groupwise_parms {
+public:
+ Groupwise_parms ();
+ ~Groupwise_parms ();
-PLMREGISTER_API void bspline_score_gm (Bspline_optimize *bod);
+public:
+};
#endif
diff --git a/src/plastimatch/register/histogram.cxx b/src/plastimatch/register/histogram.cxx
new file mode 100644
index 0000000..a564505
--- /dev/null
+++ b/src/plastimatch/register/histogram.cxx
@@ -0,0 +1,33 @@
+/* -----------------------------------------------------------------------
+ See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
+ ----------------------------------------------------------------------- */
+#include "plmregister_config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "file_util.h"
+#include "histogram.h"
+#include "logfile.h"
+#include "plm_math.h"
+#include "print_and_exit.h"
+#include "string_util.h"
+#include "volume.h"
+
+Histogram::Histogram (
+ Mi_hist_type type,
+ plm_long bins)
+{
+ this->type = type;
+ this->bins = bins;
+ this->offset = 0.f;
+ this->big_bin = 0;
+ this->delta = 0.f;
+ this->keys = 0;
+ this->key_lut = 0;
+}
+
+Histogram::~Histogram ()
+{
+ if (this->key_lut) {
+ free (this->key_lut);
+ }
+}
diff --git a/src/plastimatch/register/histogram.h b/src/plastimatch/register/histogram.h
new file mode 100644
index 0000000..ad085c4
--- /dev/null
+++ b/src/plastimatch/register/histogram.h
@@ -0,0 +1,38 @@
+/* -----------------------------------------------------------------------
+ See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
+ ----------------------------------------------------------------------- */
+#ifndef _histogram_h_
+#define _histogram_h_
+
+#include "plmregister_config.h"
+#include <string>
+#include "plm_int.h"
+
+/* Maximum # of bins for a vopt histogram */
+#define VOPT_RES 1000
+
+enum Mi_hist_type {
+ HIST_EQSP,
+ HIST_VOPT
+};
+
+class PLMREGISTER_API Histogram {
+public:
+ Histogram (
+ Mi_hist_type type = HIST_EQSP,
+ plm_long bins = 32);
+ ~Histogram ();
+public:
+ /* Used by all histogram types */
+ enum Mi_hist_type type; /* Type of histograms */
+ plm_long bins; /* # of bins in histogram */
+ float offset; /* minimum voxel intensity */
+ plm_long big_bin; /* fullest bin index */
+ float delta; /* bin OR key spacing */
+
+ /* For V-Optimal Histograms */
+ plm_long keys; /* # of keys */
+ int* key_lut; /* bin keys lookup table */
+};
+
+#endif
diff --git a/src/plastimatch/register/itk_align_center.cxx b/src/plastimatch/register/itk_align_center.cxx
index 378b7b4..a50dc97 100644
--- a/src/plastimatch/register/itk_align_center.cxx
+++ b/src/plastimatch/register/itk_align_center.cxx
@@ -26,10 +26,12 @@ itk_align_center (
Registration_data* regd, Xform *xf_out,
const Xform *xf_in, const Stage_parms* stage)
{
+ Plm_image::Pointer fixed_image = regd->get_fixed_image();
+ Plm_image::Pointer moving_image = regd->get_moving_image();
float fixed_center[3];
float moving_center[3];
- itk_volume_center (fixed_center, regd->fixed_image->itk_float());
- itk_volume_center (moving_center, regd->moving_image->itk_float());
+ itk_volume_center (fixed_center, fixed_image->itk_float());
+ itk_volume_center (moving_center, moving_image->itk_float());
itk::Array<double> trn_parms (3);
trn_parms[0] = moving_center[0] - fixed_center[0];
@@ -43,15 +45,18 @@ itk_align_center_of_gravity (
Registration_data* regd, Xform *xf_out,
const Xform *xf_in, const Stage_parms* stage)
{
- if (regd->fixed_roi != NULL && regd->moving_roi != NULL) {
- typedef itk::ImageMomentsCalculator<UCharImageType> ImageMomentsCalculatorType;
-
- ImageMomentsCalculatorType::Pointer fixedCalculator = ImageMomentsCalculatorType::New();
- fixedCalculator->SetImage(regd->fixed_roi->itk_uchar());
+ if (regd->get_fixed_roi() && regd->get_moving_roi()) {
+ typedef itk::ImageMomentsCalculator<UCharImageType>
+ ImageMomentsCalculatorType;
+
+ ImageMomentsCalculatorType::Pointer fixedCalculator
+ = ImageMomentsCalculatorType::New();
+ fixedCalculator->SetImage(regd->get_fixed_roi()->itk_uchar());
fixedCalculator->Compute();
- ImageMomentsCalculatorType::Pointer movingCalculator = ImageMomentsCalculatorType::New();
- movingCalculator->SetImage(regd->moving_roi->itk_uchar());
+ ImageMomentsCalculatorType::Pointer movingCalculator
+ = ImageMomentsCalculatorType::New();
+ movingCalculator->SetImage(regd->get_moving_roi()->itk_uchar());
movingCalculator->Compute();
ImageMomentsCalculatorType::VectorType fixedCenter;
diff --git a/src/plastimatch/register/itk_demons.cxx b/src/plastimatch/register/itk_demons.cxx
index 12b2aa6..a097b1a 100644
--- a/src/plastimatch/register/itk_demons.cxx
+++ b/src/plastimatch/register/itk_demons.cxx
@@ -88,31 +88,31 @@ set_and_subsample_masks (
const Stage_parms* stage)
{
/* Subsample fixed & moving images */
- if(regd->fixed_roi)
+ if (regd->get_fixed_roi())
{
- MaskType::Pointer fixedSpatialObjectMask = MaskType::New();
- UCharImageType::Pointer fixed_mask
- = subsample_image (regd->fixed_roi->itk_uchar(),
- stage->resample_rate_fixed[0],
- stage->resample_rate_fixed[1],
- stage->resample_rate_fixed[2],
- 0);
- fixedSpatialObjectMask->SetImage(fixed_mask);
- fixedSpatialObjectMask->Update();
- m_filter->SetFixedImageMask (fixedSpatialObjectMask);
+ MaskType::Pointer fixedSpatialObjectMask = MaskType::New();
+ UCharImageType::Pointer fixed_mask
+ = subsample_image (regd->get_fixed_roi()->itk_uchar(),
+ stage->resample_rate_fixed[0],
+ stage->resample_rate_fixed[1],
+ stage->resample_rate_fixed[2],
+ 0);
+ fixedSpatialObjectMask->SetImage(fixed_mask);
+ fixedSpatialObjectMask->Update();
+ m_filter->SetFixedImageMask (fixedSpatialObjectMask);
}
- if(regd->moving_roi)
+ if(regd->get_moving_roi())
{
- MaskType::Pointer movingSpatialObjectMask = MaskType::New();
- UCharImageType::Pointer moving_mask
- = subsample_image (regd->moving_roi->itk_uchar(),
- stage->resample_rate_fixed[0],
- stage->resample_rate_fixed[1],
- stage->resample_rate_fixed[2],
- 0);
- movingSpatialObjectMask->SetImage(moving_mask);
- movingSpatialObjectMask->Update();
- m_filter->SetMovingImageMask(movingSpatialObjectMask);
+ MaskType::Pointer movingSpatialObjectMask = MaskType::New();
+ UCharImageType::Pointer moving_mask
+ = subsample_image (regd->get_moving_roi()->itk_uchar(),
+ stage->resample_rate_fixed[0],
+ stage->resample_rate_fixed[1],
+ stage->resample_rate_fixed[2],
+ 0);
+ movingSpatialObjectMask->SetImage(moving_mask);
+ movingSpatialObjectMask->Update();
+ m_filter->SetMovingImageMask(movingSpatialObjectMask);
}
}
@@ -133,30 +133,31 @@ do_demons_stage_internal (
const Stage_parms* stage)
{
/* Subsample fixed & moving images */
+ Plm_image::Pointer fixed_image = regd->get_fixed_image();
+ Plm_image::Pointer moving_image = regd->get_moving_image();
FloatImageType::Pointer fixed_ss
- = subsample_image (regd->fixed_image->itk_float(),
- stage->resample_rate_fixed[0],
- stage->resample_rate_fixed[1],
- stage->resample_rate_fixed[2],
- stage->default_value);
+ = subsample_image (fixed_image->itk_float(),
+ stage->resample_rate_fixed[0],
+ stage->resample_rate_fixed[1],
+ stage->resample_rate_fixed[2],
+ stage->default_value);
FloatImageType::Pointer moving_ss
- = subsample_image (regd->moving_image->itk_float(),
- stage->resample_rate_moving[0],
- stage->resample_rate_moving[1],
- stage->resample_rate_moving[2],
- stage->default_value);
-
- if(stage->histoeq)
- {
+ = subsample_image (moving_image->itk_float(),
+ stage->resample_rate_moving[0],
+ stage->resample_rate_moving[1],
+ stage->resample_rate_moving[2],
+ stage->default_value);
+
+ if (stage->histoeq) {
histo_equ=HistogramMatchingFilter::New();
histo_equ->SetInput(moving_ss);
histo_equ->SetReferenceImage(fixed_ss);
histo_equ->SetNumberOfHistogramLevels(stage->num_hist_levels);
histo_equ->SetNumberOfMatchPoints(stage->num_matching_points);
m_filter->SetMovingImage (histo_equ->GetOutput());
- }
- else
- m_filter->SetMovingImage (moving_ss);
+ } else {
+ m_filter->SetMovingImage (moving_ss);
+ }
m_filter->SetFixedImage (fixed_ss);
@@ -164,8 +165,8 @@ do_demons_stage_internal (
if (xf_in->m_type != XFORM_NONE) {
xform_to_itk_vf (xf_out, xf_in, fixed_ss);
- //Set initial deformation field
- m_filter->SetInput (xf_out->get_itk_vf());
+ //Set initial deformation field
+ m_filter->SetInput (xf_out->get_itk_vf());
}
if (stage->max_its <= 0) {
diff --git a/src/plastimatch/register/itk_registration.cxx b/src/plastimatch/register/itk_registration.cxx
index 18ae8d4..b43313e 100644
--- a/src/plastimatch/register/itk_registration.cxx
+++ b/src/plastimatch/register/itk_registration.cxx
@@ -33,10 +33,12 @@
#include "itk_registration_private.h"
#include "itk_resample.h"
#include "logfile.h"
+#include "metric_parms.h"
#include "plm_image.h"
#include "plm_image_header.h"
#include "print_and_exit.h"
#include "registration_data.h"
+#include "registration_util.h"
#include "shared_parms.h"
#include "stage_parms.h"
#include "xform.h"
@@ -145,18 +147,16 @@ Itk_registration_private::compute_num_samples (
lprintf ("Setting spatial samples to %d\n",
stage->mi_num_spatial_samples);
return stage->mi_num_spatial_samples;
- } else {
- plm_long dim[3], num_voxels;
- get_image_header (dim, 0, 0, fixed_ss);
- num_voxels = dim[0] * dim[1] * dim[2];
- unsigned int num_samples
- = stage->mi_num_spatial_samples_pct * num_voxels;
- lprintf ("Setting spatial samples to %f x %d = %u\n",
- stage->mi_num_spatial_samples_pct, (int) num_voxels,
- (unsigned int)
- (stage->mi_num_spatial_samples_pct * num_voxels));
- return num_samples;
- }
+ }
+
+ plm_long num_voxels = count_fixed_voxels (regd, stage, fixed_ss);
+ unsigned int num_samples
+ = stage->mi_num_spatial_samples_pct * num_voxels;
+ lprintf ("Setting spatial samples to %f x %d = %u\n",
+ stage->mi_num_spatial_samples_pct, (int) num_voxels,
+ (unsigned int)
+ (stage->mi_num_spatial_samples_pct * num_voxels));
+ return num_samples;
}
void
@@ -202,14 +202,25 @@ Itk_registration_private::set_best_xform ()
void
Itk_registration_private::set_metric (FloatImageType::Pointer& fixed_ss)
{
- switch (stage->metric_type[0]) {
- case REGISTRATION_METRIC_MSE:
+ /* GCS FIX, split metric vector into separate items in
+ Stage_similarity_data list */
+ Metric_parms metric_parms;
+ const Shared_parms *shared = stage->get_shared_parms();
+ std::map<std::string,Metric_parms>::const_iterator metric_it;
+ for (metric_it = shared->metric.begin();
+ metric_it != shared->metric.end(); ++metric_it) {
+ metric_parms = metric_it->second;
+ break;
+ }
+
+ switch (metric_parms.metric_type) {
+ case SIMILARITY_METRIC_MSE:
{
MSEMetricType::Pointer metric = MSEMetricType::New();
registration->SetMetric(metric);
}
break;
- case REGISTRATION_METRIC_MI_VW:
+ case SIMILARITY_METRIC_MI_VW:
{
/* The metric requires a number of parameters to be
selected, including the standard deviation of the
@@ -229,7 +240,7 @@ Itk_registration_private::set_metric (FloatImageType::Pointer& fixed_ss)
registration->SetMetric(metric);
}
break;
- case REGISTRATION_METRIC_MI_MATTES:
+ case SIMILARITY_METRIC_MI_MATTES:
{
/* The metric requires two parameters to be selected: the
number of bins used to compute the entropy and the
@@ -263,7 +274,7 @@ Itk_registration_private::set_metric (FloatImageType::Pointer& fixed_ss)
registration->SetMetric(metric);
}
break;
- case REGISTRATION_METRIC_NMI:
+ case SIMILARITY_METRIC_NMI:
{
NMIMetricType::Pointer metric = NMIMetricType::New();
@@ -308,15 +319,15 @@ void
Itk_registration_private::set_roi_images ()
{
const Shared_parms *shared = stage->get_shared_parms();
- if (shared->fixed_roi_enable && regd->fixed_roi) {
+ if (shared->fixed_roi_enable && regd->get_fixed_roi()) {
Mask_SOType::Pointer roi_so = Mask_SOType::New();
- roi_so->SetImage(regd->fixed_roi->itk_uchar());
+ roi_so->SetImage(regd->get_fixed_roi()->itk_uchar());
roi_so->Update();
registration->GetMetric()->SetFixedImageMask (roi_so);
}
- if (shared->moving_roi_enable && regd->moving_roi) {
+ if (shared->moving_roi_enable && regd->get_moving_roi()) {
Mask_SOType::Pointer roi_so = Mask_SOType::New();
- roi_so->SetImage(regd->moving_roi->itk_uchar());
+ roi_so->SetImage(regd->get_moving_roi()->itk_uchar());
roi_so->Update();
registration->GetMetric()->SetMovingImageMask (roi_so);
}
@@ -680,14 +691,16 @@ itk_registration_stage (
irp.registration = RegistrationType::New();
/* Subsample fixed & moving images */
+ Plm_image::Pointer fixed_image = regd->get_fixed_image();
+ Plm_image::Pointer moving_image = regd->get_moving_image();
FloatImageType::Pointer fixed_ss = subsample_image (
- regd->fixed_image->itk_float(),
+ fixed_image->itk_float(),
stage->resample_rate_fixed[0],
stage->resample_rate_fixed[1],
stage->resample_rate_fixed[2],
stage->default_value);
FloatImageType::Pointer moving_ss = subsample_image (
- regd->moving_image->itk_float(),
+ moving_image->itk_float(),
stage->resample_rate_moving[0],
stage->resample_rate_moving[1],
stage->resample_rate_moving[2],
@@ -742,10 +755,12 @@ itk_align_center (
Registration_data* regd, Xform *xf_out,
const Xform *xf_in, const Stage_parms* stage)
{
+ Plm_image::Pointer fixed_image = regd->get_fixed_image();
+ Plm_image::Pointer moving_image = regd->get_moving_image();
float fixed_center[3];
float moving_center[3];
- itk_volume_center (fixed_center, regd->fixed_image->itk_float());
- itk_volume_center (moving_center, regd->moving_image->itk_float());
+ itk_volume_center (fixed_center, fixed_image->itk_float());
+ itk_volume_center (moving_center, moving_image->itk_float());
itk::Array<double> trn_parms (3);
trn_parms[0] = moving_center[0] - fixed_center[0];
@@ -760,15 +775,15 @@ itk_align_center_of_gravity (
const Xform *xf_in, const Stage_parms* stage)
{
- if (regd->fixed_roi != NULL && regd->moving_roi != NULL) {
+ if (regd->get_fixed_roi() && regd->get_moving_roi()) {
typedef itk::ImageMomentsCalculator<UCharImageType> ImageMomentsCalculatorType;
ImageMomentsCalculatorType::Pointer fixedCalculator = ImageMomentsCalculatorType::New();
- fixedCalculator->SetImage(regd->fixed_roi->itk_uchar());
+ fixedCalculator->SetImage(regd->get_fixed_roi()->itk_uchar());
fixedCalculator->Compute();
ImageMomentsCalculatorType::Pointer movingCalculator = ImageMomentsCalculatorType::New();
- movingCalculator->SetImage(regd->moving_roi->itk_uchar());
+ movingCalculator->SetImage(regd->get_moving_roi()->itk_uchar());
movingCalculator->Compute();
ImageMomentsCalculatorType::VectorType fixedCenter;
diff --git a/src/plastimatch/register/itk_registration_observer.cxx b/src/plastimatch/register/itk_registration_observer.cxx
index 0756eac..25e2fde 100644
--- a/src/plastimatch/register/itk_registration_observer.cxx
+++ b/src/plastimatch/register/itk_registration_observer.cxx
@@ -14,8 +14,10 @@
#include "itk_registration.h"
#include "itk_registration_private.h"
#include "logfile.h"
+#include "metric_parms.h"
#include "plm_math.h"
#include "plm_timer.h"
+#include "shared_parms.h"
#include "stage_parms.h"
/* Lots of ITK algorithms don't behave uniformly.
@@ -80,6 +82,17 @@ public:
void
Execute (const itk::Object * object, const itk::EventObject & event)
{
+ /* GCS FIX, split metric vector into separate items in
+ Stage_similarity_data list */
+ Metric_parms metric_parms;
+ const Shared_parms *shared = irp->stage->get_shared_parms();
+ std::map<std::string,Metric_parms>::const_iterator metric_it;
+ for (metric_it = shared->metric.begin();
+ metric_it != shared->metric.end(); ++metric_it) {
+ metric_parms = metric_it->second;
+ break;
+ }
+
if (typeid(event) == typeid(itk::StartEvent)) {
m_feval = 0;
m_prev_value = -DBL_MAX;
@@ -115,8 +128,8 @@ public:
double duration = timer->report ();
lprintf ("%s [%2d,%3d] %9.3f [%6.3f secs]\n",
- (irp->stage->metric_type[0] == REGISTRATION_METRIC_MSE)
- ? "MSE" : "MI",
+ (metric_parms.metric_type == SIMILARITY_METRIC_MSE)
+ ? "MSE" : "MI",
it, m_feval, val, duration);
timer->start ();
m_feval++;
@@ -139,13 +152,13 @@ public:
/* Print out score & optimizer stats */
if (irp->stage->optim_type == OPTIMIZATION_AMOEBA) {
lprintf ("%s [%3d] %9.3f ",
- (irp->stage->metric_type[0] == REGISTRATION_METRIC_MSE)
- ? "MSE" : "MI",
+ (metric_parms.metric_type == SIMILARITY_METRIC_MSE)
+ ? "MSE" : "MI",
m_feval / 2, val);
} else {
lprintf ("%s [%2d,%3d,%5.2f] %9.3f ",
- (irp->stage->metric_type[0] == REGISTRATION_METRIC_MSE)
- ? "MSE" : "MI",
+ (metric_parms.metric_type == SIMILARITY_METRIC_MSE)
+ ? "MSE" : "MI",
it, m_feval, ss, val);
}
diff --git a/src/plastimatch/register/bspline_mi_hist.cxx b/src/plastimatch/register/joint_histogram.cxx
old mode 100755
new mode 100644
similarity index 67%
rename from src/plastimatch/register/bspline_mi_hist.cxx
rename to src/plastimatch/register/joint_histogram.cxx
index 8758728..54584b3
--- a/src/plastimatch/register/bspline_mi_hist.cxx
+++ b/src/plastimatch/register/joint_histogram.cxx
@@ -4,45 +4,23 @@
#include "plmregister_config.h"
#include <stdio.h>
#include <stdlib.h>
-#include "bspline_mi_hist.h"
#include "file_util.h"
+#include "joint_histogram.h"
#include "logfile.h"
#include "plm_math.h"
#include "print_and_exit.h"
#include "string_util.h"
#include "volume.h"
+#include "xpm.h"
-Bspline_mi_hist::Bspline_mi_hist (
- Mi_hist_type type,
- plm_long bins)
-{
- //this->type = HIST_EQSP;
- //this->bins = 32;
- this->type = type;
- this->bins = bins;
- this->offset = 0.f;
- this->big_bin = 0;
- this->delta = 0.f;
-
- this->keys = 0;
- this->key_lut = 0;
-}
-
-Bspline_mi_hist::~Bspline_mi_hist ()
-{
- if (this->key_lut) {
- free (this->key_lut);
- }
-}
-
-Bspline_mi_hist_set::Bspline_mi_hist_set ()
+Joint_histogram::Joint_histogram ()
{
this->m_hist = 0;
this->f_hist = 0;
this->j_hist = 0;
}
-Bspline_mi_hist_set::Bspline_mi_hist_set (Mi_hist_type type,
+Joint_histogram::Joint_histogram (Mi_hist_type type,
plm_long fixed_bins, plm_long moving_bins)
: moving (type, moving_bins),
fixed (type, fixed_bins),
@@ -51,7 +29,7 @@ Bspline_mi_hist_set::Bspline_mi_hist_set (Mi_hist_type type,
this->allocate ();
}
-Bspline_mi_hist_set::~Bspline_mi_hist_set ()
+Joint_histogram::~Joint_histogram ()
{
delete[] this->f_hist;
delete[] this->m_hist;
@@ -59,7 +37,7 @@ Bspline_mi_hist_set::~Bspline_mi_hist_set ()
}
void
-Bspline_mi_hist_set::allocate ()
+Joint_histogram::allocate ()
{
this->m_hist = new double [this->moving.bins]();
this->f_hist = new double [this->fixed.bins]();
@@ -68,7 +46,7 @@ Bspline_mi_hist_set::allocate ()
void
-Bspline_mi_hist_set::reset_histograms ()
+Joint_histogram::reset_histograms ()
{
memset (this->f_hist, 0, this->fixed.bins * sizeof(double));
memset (this->m_hist, 0, this->moving.bins * sizeof(double));
@@ -104,7 +82,7 @@ vopt_bin_error (int start, int end, double* s_lut, double* ssq_lut, double* cnt_
static void
bspline_initialize_mi_bigbin (
double* hist,
- Bspline_mi_hist* hparms,
+ Histogram* hparms,
Volume* vol
)
{
@@ -135,7 +113,7 @@ bspline_initialize_mi_bigbin (
}
static void
-bspline_initialize_mi_hist_eqsp (Bspline_mi_hist* hparms, Volume* vol)
+bspline_initialize_mi_hist_eqsp (Histogram* hparms, Volume* vol)
{
plm_long i;
float min_vox, max_vox;
@@ -215,7 +193,7 @@ bspline_mi_hist_vopt_dump_ranges (
* http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.92.3195&rep=rep1&type=pdf
*/
static void
-bspline_initialize_mi_hist_vopt (Bspline_mi_hist* hparms, Volume* vol)
+bspline_initialize_mi_hist_vopt (Histogram* hparms, Volume* vol)
{
int idx_bin;
plm_long curr, next, bottom;
@@ -347,7 +325,7 @@ bspline_initialize_mi_hist_vopt (Bspline_mi_hist* hparms, Volume* vol)
static void
-bspline_initialize_mi_hist (Bspline_mi_hist* hparms, Volume* vol)
+bspline_initialize_mi_hist (Histogram* hparms, Volume* vol)
{
/* If user wants more than VOPT can offer, fallback to EQSP */
if ((hparms->bins > VOPT_RES) && (hparms->type == HIST_VOPT)) {
@@ -370,7 +348,7 @@ bspline_initialize_mi_hist (Bspline_mi_hist* hparms, Volume* vol)
}
void
-Bspline_mi_hist_set::initialize (Volume *fixed, Volume *moving)
+Joint_histogram::initialize (Volume *fixed, Volume *moving)
{
bspline_initialize_mi_hist (&this->fixed, fixed);
bspline_initialize_mi_hist (&this->moving, moving);
@@ -393,7 +371,7 @@ Bspline_mi_hist_set::initialize (Volume *fixed, Volume *moving)
}
void
-Bspline_mi_hist_set::dump_hist (int it, const std::string& prefix)
+Joint_histogram::dump_hist (int it, const std::string& prefix)
{
double* f_hist = this->f_hist;
double* m_hist = this->m_hist;
@@ -443,7 +421,7 @@ Bspline_mi_hist_set::dump_hist (int it, const std::string& prefix)
}
void
-Bspline_mi_hist_set::add_pvi_8
+Joint_histogram::add_pvi_8
(
const Volume *fixed,
const Volume *moving,
@@ -510,7 +488,7 @@ Bspline_mi_hist_set::add_pvi_8
/* This algorithm uses a un-normalized score. */
float
-Bspline_mi_hist_set::compute_score (int num_vox)
+Joint_histogram::compute_score (int num_vox)
{
double* f_hist = this->f_hist;
double* m_hist = this->m_hist;
@@ -535,3 +513,211 @@ Bspline_mi_hist_set::compute_score (int num_vox)
score = score / fnv;
return (float) score;
}
+
+void dump_xpm_hist (Joint_histogram* mi_hist, char* file_base, int iter)
+{
+ int z;
+ char c;
+
+ // Graph Properties
+ int graph_offset_x = 10;
+ int graph_offset_y = 10;
+ int graph_padding = 20;
+ int graph_bar_height = 100;
+ int graph_bar_width = 5;
+ int graph_bar_spacing = (int)((float)graph_bar_width * (7.0/5.0));
+ plm_long graph_color_levels = 22;
+
+ // int fixed_bar_height; // max bar height (pixels)
+ // int moving_bar_height;
+ plm_long joint_color;
+
+ float fixed_scale; // pixels per amt
+ float moving_scale;
+ float joint_scale;
+
+ float moving_max_val=0;
+ float fixed_max_val=0;
+ float joint_max_val=0;
+
+ int fixed_total_width = mi_hist->fixed.bins * graph_bar_spacing;
+ int moving_total_width = mi_hist->moving.bins * graph_bar_spacing;
+
+ int graph_moving_x_pos = graph_offset_x + graph_bar_height + graph_padding;
+ int graph_moving_y_pos = graph_offset_y + fixed_total_width + graph_padding + graph_bar_height;
+
+ int graph_fixed_x_pos = graph_offset_x;
+ int graph_fixed_y_pos = graph_offset_y + fixed_total_width;
+
+ int border_padding = 5;
+ int border_width = moving_total_width + 2*border_padding;
+ int border_height = fixed_total_width + 2*border_padding;
+ int border_x_pos = graph_moving_x_pos - border_padding;
+ int border_y_pos = graph_offset_y - border_padding + (int)((float)graph_bar_width * (2.0/5.0));
+
+ int canvas_width = 2*graph_offset_x + graph_bar_height + moving_total_width + graph_padding;
+ int canvas_height = 2*graph_offset_y + graph_bar_height + fixed_total_width + graph_padding;
+
+ double *m_hist = mi_hist->m_hist;
+ double *f_hist = mi_hist->f_hist;
+ double *j_hist = mi_hist->j_hist;
+
+ char filename[20];
+
+ sprintf(filename, "%s_%04i.xpm", file_base, iter);
+
+ // ----------------------------------------------
+ // Find max value for fixed
+ for(plm_long i=0; i<mi_hist->fixed.bins; i++)
+ if (f_hist[i] > fixed_max_val)
+ fixed_max_val = f_hist[i];
+
+ // Find max value for moving
+ for(plm_long i=0; i<mi_hist->moving.bins; i++)
+ if (m_hist[i] > moving_max_val)
+ moving_max_val = m_hist[i];
+
+ // Find max value for joint
+ // (Ignoring bin 0)
+ for(plm_long j=0; j<mi_hist->fixed.bins; j++) {
+ for(plm_long i=0; i<mi_hist->moving.bins; i++) {
+ if ( (i > 0) && (j > 1) )
+ if (j_hist[j*mi_hist->moving.bins + i] > joint_max_val)
+ joint_max_val = j_hist[j*mi_hist->moving.bins + i];
+ }
+ }
+
+
+ // Generate scaling factors
+ fixed_scale = (float)graph_bar_height / fixed_max_val;
+ moving_scale = (float)graph_bar_height / moving_max_val;
+ joint_scale = (float)graph_color_levels / joint_max_val;
+ // ----------------------------------------------
+
+
+
+ // ----------------------------------------------
+ // Pull out a canvas and brush!
+ Xpm_canvas* xpm = new Xpm_canvas (canvas_width, canvas_height, 1);
+ Xpm_brush* brush = new Xpm_brush;
+
+ // setup the palette
+ xpm->add_color ('a', 0xFFFFFF); // white
+ xpm->add_color ('b', 0x000000); // black
+ xpm->add_color ('z', 0xFFCC00); // orange
+
+ // generate a nice BLUE->RED gradient
+ c = 'c';
+ z = 0x0000FF;
+ for (plm_long i=0; i<(graph_color_levels+1); i++)
+ {
+ xpm->add_color (c, z);
+
+ z -= 0x00000B; // BLUE--
+ z += 0x0B0000; // RED++
+
+ c = (char)((int)c + 1); // LETTER++
+ }
+
+ // Prime the XPM Canvas
+ xpm->prime ('a');
+ // ----------------------------------------------
+
+
+ printf("Drawing Histograms... ");
+
+
+ /* Generate Moving Histogram */
+ brush->set_type (XPM_BOX);
+ brush->set_color ('b');
+ brush->set_pos (graph_moving_x_pos, graph_moving_y_pos);
+ brush->set_width (graph_bar_width);
+ brush->set_height (0);
+
+ int tmp_h;
+ for(plm_long i=0; i<mi_hist->moving.bins; i++)
+ {
+ tmp_h = (int)(m_hist[i] * moving_scale);
+ brush->set_height (tmp_h);
+ brush->set_y (graph_moving_y_pos - tmp_h);
+ xpm->draw (brush);
+ brush->inc_x (graph_bar_spacing);
+ }
+
+
+ /* Generate Fixed Histogram */
+ brush->set_type (XPM_BOX);
+ brush->set_color ('b');
+ brush->set_pos (graph_fixed_x_pos, graph_fixed_y_pos);
+ brush->set_width (0);
+ brush->set_height (graph_bar_width);
+
+ for (plm_long i=0; i<mi_hist->fixed.bins; i++)
+ {
+ brush->set_width ((int)(f_hist[i] * fixed_scale));
+ xpm->draw (brush);
+ brush->inc_x ((-1)*graph_bar_spacing);
+ }
+
+
+ /* Generate Joint Histogram */
+ brush->set_type (XPM_BOX);
+ brush->set_color ('b');
+ brush->set_pos (graph_moving_x_pos, graph_fixed_y_pos);
+ brush->set_width (graph_bar_width);
+ brush->set_height (graph_bar_width);
+
+ z = 0;
+ for(plm_long j=0; j<mi_hist->fixed.bins; j++) {
+ for(plm_long i=0; i<mi_hist->moving.bins; i++) {
+ joint_color = (size_t)(j_hist[z++] * joint_scale);
+ if (joint_color > 0) {
+ // special handling for bin 0
+ if (joint_color > graph_color_levels) {
+ // printf ("Clamp @ P(%i,%i)\n", i, j);
+ // brush.color = (char)(graph_color_levels + 99);
+ brush->set_color ('z');
+ } else {
+ brush->set_color ((char)(joint_color + 99));
+ }
+ } else {
+ brush->set_color ('a');
+ }
+ xpm->draw (brush);
+ brush->inc_x (graph_bar_spacing);
+ }
+ // get ready to render new row
+ brush->set_x (graph_moving_x_pos);
+ brush->inc_y ((-1)*graph_bar_spacing);
+ }
+
+ /* Generate Joint Histogram Border */
+ brush->set_type (XPM_BOX); // top
+ brush->set_color ('b');
+ brush->set_pos (border_x_pos, border_y_pos);
+ brush->set_width (border_width);
+ brush->set_height (1);
+ xpm->draw (brush);
+
+ brush->set_width (1); // left
+ brush->set_height (border_height);
+ xpm->draw (brush);
+
+ brush->set_width (border_width); // bottom
+ brush->set_height (1);
+ brush->inc_y (border_height);
+ xpm->draw (brush);
+
+ brush->set_width (1); // right
+ brush->set_height (border_height);
+ brush->set_pos (border_width, border_y_pos);
+ xpm->draw (brush);
+
+ printf("done.\n");
+
+ // Write to file
+ xpm->write (filename);
+
+ delete xpm;
+ delete brush;
+}
diff --git a/src/plastimatch/register/joint_histogram.h b/src/plastimatch/register/joint_histogram.h
new file mode 100644
index 0000000..fef904c
--- /dev/null
+++ b/src/plastimatch/register/joint_histogram.h
@@ -0,0 +1,50 @@
+/* -----------------------------------------------------------------------
+ See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
+ ----------------------------------------------------------------------- */
+#ifndef _joint_histogram_h_
+#define _joint_histogram_h_
+
+#include "plmregister_config.h"
+#include <string>
+#include "histogram.h"
+#include "plm_int.h"
+
+class Volume;
+
+class PLMREGISTER_API Joint_histogram {
+public:
+ Joint_histogram ();
+ Joint_histogram (
+ Mi_hist_type type,
+ plm_long fixed_bins,
+ plm_long moving_bins);
+ ~Joint_histogram ();
+public:
+ void initialize (Volume *fixed, Volume *moving);
+ void reset_histograms ();
+ void dump_hist (int it, const std::string& prefix);
+
+ void add_pvi_8 (
+ const Volume *fixed,
+ const Volume *moving,
+ int fidx,
+ int mvf,
+ float li_1[3], /* Fraction of interpolant in lower index */
+ float li_2[3]); /* Fraction of interpolant in upper index */
+
+ float compute_score (int num_vox);
+
+public:
+ Histogram moving;
+ Histogram fixed;
+ Histogram joint;
+ double* m_hist;
+ double* f_hist;
+ double* j_hist;
+protected:
+ void allocate ();
+};
+
+void dump_xpm_hist (Joint_histogram* mi_hist, char* file_base, int iter);
+
+#endif
diff --git a/src/plastimatch/register/landmark_warp.cxx b/src/plastimatch/register/landmark_warp.cxx
index 23942b6..0edc8ef 100644
--- a/src/plastimatch/register/landmark_warp.cxx
+++ b/src/plastimatch/register/landmark_warp.cxx
@@ -129,7 +129,7 @@ landmark_convert_mm_to_voxel (
plm_long *dim,
const float *direction_cosines)
{
- for (int i = 0; i < landmarks_mm.get_count(); i++) {
+ for (size_t i = 0; i < landmarks_mm.get_count(); i++) {
for (int d = 0; d < 3; d++) {
landvox[i*3 + d] = ROUND_INT (
( landmarks_mm.point(i,d)
diff --git a/src/plastimatch/register/metric_parms.cxx b/src/plastimatch/register/metric_parms.cxx
new file mode 100644
index 0000000..f56c97c
--- /dev/null
+++ b/src/plastimatch/register/metric_parms.cxx
@@ -0,0 +1,54 @@
+/* -----------------------------------------------------------------------
+ See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
+ ----------------------------------------------------------------------- */
+#include "plmregister_config.h"
+#include <string>
+#include "logfile.h"
+#include "metric_parms.h"
+#include "string_util.h"
+
+Metric_parms::Metric_parms ()
+{
+ metric_type = SIMILARITY_METRIC_MSE;
+ metric_lambda = 1.0;
+}
+
+Plm_return_code
+Metric_parms::set_metric_type (const std::string& val)
+{
+ if (val == "dm" || val == "dmap") {
+ this->metric_type = SIMILARITY_METRIC_DMAP;
+ return PLM_SUCCESS;
+ }
+ else if (val == "gm") {
+ this->metric_type = SIMILARITY_METRIC_GM;
+ return PLM_SUCCESS;
+ }
+ else if (val == "mattes") {
+ this->metric_type = SIMILARITY_METRIC_MI_MATTES;
+ return PLM_SUCCESS;
+ }
+ else if (val == "mse" || val == "MSE") {
+ this->metric_type = SIMILARITY_METRIC_MSE;
+ return PLM_SUCCESS;
+ }
+ else if (val == "mi" || val == "MI") {
+#if PLM_CONFIG_LEGACY_MI_METRIC
+ this->metric_type = SIMILARITY_METRIC_MI_VW;
+#else
+ this->metric_type = SIMILARITY_METRIC_MI_MATTES;
+#endif
+ return PLM_SUCCESS;
+ }
+ else if (val == "mi_vw" || val == "viola-wells") {
+ this->metric_type = SIMILARITY_METRIC_MI_VW;
+ return PLM_SUCCESS;
+ }
+ else if (val == "nmi" || val == "NMI") {
+ this->metric_type = SIMILARITY_METRIC_NMI;
+ return PLM_SUCCESS;
+ }
+ else {
+ return PLM_ERROR;
+ }
+}
diff --git a/src/plastimatch/register/metric_parms.h b/src/plastimatch/register/metric_parms.h
new file mode 100644
index 0000000..fc4aceb
--- /dev/null
+++ b/src/plastimatch/register/metric_parms.h
@@ -0,0 +1,28 @@
+/* -----------------------------------------------------------------------
+ See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
+ ----------------------------------------------------------------------- */
+#ifndef _metric_parms_h_
+#define _metric_parms_h_
+
+#include "plmregister_config.h"
+#include <string>
+#include <vector>
+#include "plm_return_code.h"
+#include "similarity_metric_type.h"
+
+class PLMREGISTER_API Metric_parms {
+public:
+ Metric_parms ();
+public:
+ Similarity_metric_type metric_type;
+ float metric_lambda;
+
+ std::string fixed_fn;
+ std::string moving_fn;
+ std::string fixed_roi_fn;
+ std::string moving_roi_fn;
+public:
+ Plm_return_code set_metric_type (const std::string& val);
+};
+
+#endif
diff --git a/src/plastimatch/register/translation_mse.h b/src/plastimatch/register/metric_state.cxx
similarity index 51%
copy from src/plastimatch/register/translation_mse.h
copy to src/plastimatch/register/metric_state.cxx
index 82a3173..75e6356 100644
--- a/src/plastimatch/register/translation_mse.h
+++ b/src/plastimatch/register/metric_state.cxx
@@ -1,17 +1,19 @@
-/* -----------------------------------------------------------------------
- See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
- ----------------------------------------------------------------------- */
-#ifndef _translation_mse_h_
-#define _translation_mse_h_
-
-#include "plmregister_config.h"
-#include "volume.h"
-
-float
-translation_mse (
- const Stage_parms *stage,
- const Volume::Pointer& fixed,
- const Volume::Pointer& moving,
- const float dxyz[3]);
-
-#endif
+/* -----------------------------------------------------------------------
+ See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
+ ----------------------------------------------------------------------- */
+#include "plmregister_config.h"
+
+#include "joint_histogram.h"
+#include "metric_state.h"
+
+Metric_state::Metric_state ()
+{
+ metric_type = SIMILARITY_METRIC_MSE;
+ metric_lambda = 1.f;
+ mi_hist = 0;
+}
+
+Metric_state::~Metric_state ()
+{
+ delete mi_hist;
+}
diff --git a/src/plastimatch/register/metric_state.h b/src/plastimatch/register/metric_state.h
new file mode 100644
index 0000000..a926a72
--- /dev/null
+++ b/src/plastimatch/register/metric_state.h
@@ -0,0 +1,39 @@
+/* -----------------------------------------------------------------------
+ See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
+ ----------------------------------------------------------------------- */
+#ifndef _metric_state_h_
+#define _metric_state_h_
+
+#include "plmregister_config.h"
+#include "similarity_metric_type.h"
+#include "volume.h"
+
+class Joint_histogram;
+
+class PLMREGISTER_API Metric_state
+{
+public:
+ SMART_POINTER_SUPPORT (Metric_state);
+public:
+ Metric_state ();
+ ~Metric_state ();
+public:
+ Volume::Pointer fixed_ss;
+ Volume::Pointer moving_ss;
+ Volume::Pointer fixed_grad;
+ Volume::Pointer moving_grad;
+ Volume::Pointer fixed_roi;
+ Volume::Pointer moving_roi;
+
+ Similarity_metric_type metric_type;
+ float metric_lambda;
+
+ Joint_histogram *mi_hist;
+
+public:
+ const char *metric_string () {
+ return similarity_metric_type_string (metric_type);
+ }
+};
+
+#endif
diff --git a/src/plastimatch/register/process_parms.cxx b/src/plastimatch/register/process_parms.cxx
index 537ade2..b2e8231 100644
--- a/src/plastimatch/register/process_parms.cxx
+++ b/src/plastimatch/register/process_parms.cxx
@@ -99,16 +99,12 @@ Process_parms::execute_process (Registration_data::Pointer& regd) const
}
if (adjust_fixed) {
- regd->fixed_image->set_itk (
- itk_adjust (
- regd->fixed_image->itk_float(),
- parms));
+ Plm_image::Pointer& fixed = regd->get_fixed_image();
+ fixed->set_itk (itk_adjust (fixed->itk_float(), parms));
}
if (adjust_moving) {
- regd->moving_image->set_itk (
- itk_adjust (
- regd->moving_image->itk_float(),
- parms));
+ Plm_image::Pointer& moving = regd->get_moving_image();
+ moving->set_itk (itk_adjust (moving->itk_float(), parms));
}
}
}
diff --git a/src/plastimatch/register/rbf_gauss.cxx b/src/plastimatch/register/rbf_gauss.cxx
index 2a0920a..38b78bd 100644
--- a/src/plastimatch/register/rbf_gauss.cxx
+++ b/src/plastimatch/register/rbf_gauss.cxx
@@ -402,14 +402,10 @@ bspline_rbf_find_coeffs (
)
{
bspline_rbf_find_coeffs_reg (coeff, lw);
- //bspline_rbf_find_coeffs_noreg(vector_field, parms);
-
- int i;
- for (i=0; i < lw->m_fixed_landmarks.get_count(); i++) {
- printf("coeff %4d %.4f %.4f %.4f\n", i,
- coeff[3*i+0],
- coeff[3*i+1],
- coeff[3*i+2]);
+
+ for (size_t i = 0; i < lw->m_fixed_landmarks.get_count(); i++) {
+ printf("coeff %4d %.4f %.4f %.4f\n",
+ (int) i, coeff[3*i+0], coeff[3*i+1], coeff[3*i+2]);
}
#if defined (commentout)
@@ -537,7 +533,6 @@ rbf_gauss_update_vf_no_dircos (
}
}
-
void
rbf_gauss_warp (Landmark_warp *lw)
{
@@ -545,7 +540,6 @@ rbf_gauss_warp (Landmark_warp *lw)
float origin[3], spacing[3];
float direction_cosines[9];
plm_long dim[3];
- int i;
Volume::Pointer moving;
Volume *vf_out, *warped_out;
@@ -557,12 +551,13 @@ rbf_gauss_warp (Landmark_warp *lw)
rbf_cluster_find_adapt_radius( lw );
}
else {
- for(i = 0; i < lw->m_fixed_landmarks.get_count(); i++)
+ for (size_t i = 0; i < lw->m_fixed_landmarks.get_count(); i++)
lw->adapt_radius[i]=lw->rbf_radius;
}
- for (i = 0; i < lw->m_fixed_landmarks.get_count(); i++)
+ for (size_t i = 0; i < lw->m_fixed_landmarks.get_count(); i++) {
printf("%f\n", lw->adapt_radius[i]);
+ }
/* Solve for RBF weights */
coeff = (float*) malloc (
diff --git a/src/plastimatch/register/registration.cxx b/src/plastimatch/register/registration.cxx
index 0bf6744..3865669 100644
--- a/src/plastimatch/register/registration.cxx
+++ b/src/plastimatch/register/registration.cxx
@@ -73,13 +73,13 @@ Registration::~Registration ()
delete d_ptr;
}
-int
+Plm_return_code
Registration::set_command_file (const std::string& command_file)
{
return d_ptr->rparms->parse_command_file (command_file.c_str());
}
-int
+Plm_return_code
Registration::set_command_string (const std::string& command_string)
{
return d_ptr->rparms->set_command_string (command_string);
@@ -88,25 +88,25 @@ Registration::set_command_string (const std::string& command_string)
void
Registration::set_fixed_image (Plm_image::Pointer& fixed)
{
- d_ptr->rdata->fixed_image = fixed;
+ d_ptr->rdata->set_fixed_image (fixed);
}
void
Registration::set_moving_image (Plm_image::Pointer& moving)
{
- d_ptr->rdata->moving_image = moving;
+ d_ptr->rdata->set_moving_image (moving);
}
void
Registration::set_fixed_roi (Plm_image::Pointer& fixed_roi)
{
- d_ptr->rdata->fixed_roi = fixed_roi;
+ d_ptr->rdata->set_fixed_roi (fixed_roi);
}
void
Registration::set_moving_roi (Plm_image::Pointer& moving_roi)
{
- d_ptr->rdata->moving_roi = moving_roi;
+ d_ptr->rdata->set_moving_roi (moving_roi);
}
Registration_data::Pointer
@@ -131,10 +131,11 @@ set_fixed_image_region_global (Registration_data::Pointer& regd)
{
int use_magic_value = 1;
- regd->fixed_region_origin = regd->fixed_image->itk_float()->GetOrigin();
- regd->fixed_region_spacing = regd->fixed_image->itk_float()->GetSpacing();
+ Plm_image::Pointer fixed_image = regd->get_fixed_image();
+ regd->fixed_region_origin = fixed_image->itk_float()->GetOrigin();
+ regd->fixed_region_spacing = fixed_image->itk_float()->GetSpacing();
- if (regd->fixed_roi) {
+ if (regd->get_fixed_roi()) {
FloatImageType::RegionType::IndexType valid_index;
FloatImageType::RegionType::SizeType valid_size;
@@ -142,8 +143,8 @@ set_fixed_image_region_global (Registration_data::Pointer& regd)
typedef itk::ImageRegionConstIteratorWithIndex<
UCharImageType > IteratorType;
UCharImageType::RegionType region
- = regd->fixed_roi->itk_uchar()->GetLargestPossibleRegion();
- IteratorType it (regd->fixed_roi->itk_uchar(), region);
+ = regd->get_fixed_roi()->itk_uchar()->GetLargestPossibleRegion();
+ IteratorType it (regd->get_fixed_roi()->itk_uchar(), region);
int first = 1;
valid_index[0] = 0;
@@ -189,14 +190,15 @@ set_fixed_image_region_global (Registration_data::Pointer& regd)
valid_size[2] = 1;
/* Make sure the image is ITK float */
- FloatImageType::Pointer fixed_image = regd->fixed_image->itk_float();
+ Plm_image::Pointer fixed_image = regd->get_fixed_image();
+ FloatImageType::Pointer fixed = fixed_image->itk_float();
/* Search for bounding box of patient */
typedef itk::ImageRegionConstIteratorWithIndex <
FloatImageType > IteratorType;
FloatImageType::RegionType region
- = fixed_image->GetLargestPossibleRegion();
- IteratorType it (fixed_image, region);
+ = fixed->GetLargestPossibleRegion();
+ IteratorType it (fixed, region);
int first = 1;
for (it.GoToBegin(); !it.IsAtEnd(); ++it) {
@@ -230,7 +232,7 @@ set_fixed_image_region_global (Registration_data::Pointer& regd)
valid_size[i]++;
}
if (valid_size[i] + valid_index[i]
- < fixed_image->GetLargestPossibleRegion().GetSize()[i])
+ < fixed->GetLargestPossibleRegion().GetSize()[i])
{
valid_size[i]++;
}
@@ -239,7 +241,7 @@ set_fixed_image_region_global (Registration_data::Pointer& regd)
regd->fixed_region.SetSize(valid_size);
} else {
regd->fixed_region
- = regd->fixed_image->itk_float()->GetLargestPossibleRegion();
+ = fixed_image->itk_float()->GetLargestPossibleRegion();
}
}
@@ -258,6 +260,9 @@ save_output (
const std::string& valid_roi_out_fn
)
{
+ Plm_image::Pointer fixed_image = regd->get_fixed_image();
+ Plm_image::Pointer moving_image = regd->get_moving_image();
+
/* Handle null xf, make it zero translation */
if (xf_out->m_type == XFORM_NONE) {
xf_out->init_trn ();
@@ -269,7 +274,7 @@ save_output (
logfile_printf ("Writing transformation ...\n");
if (xf_out_itk && xf_out->m_type == XFORM_GPUIT_BSPLINE) {
Plm_image_header pih;
- pih.set_from_plm_image (regd->fixed_image);
+ pih.set_from_plm_image (fixed_image);
Xform::Pointer xf_tmp = xform_to_itk_bsp (xf_out, &pih, 0);
xf_tmp->save (*it);
} else {
@@ -294,10 +299,11 @@ save_output (
im_warped = Plm_image::New();
}
- pih.set_from_plm_image (regd->fixed_image);
+ pih.set_from_plm_image (fixed_image);
logfile_printf ("Warping...\n");
- plm_warp (im_warped, vfp, xf_out, &pih, regd->moving_image,
+ Plm_image::Pointer moving_image = regd->get_moving_image();
+ plm_warp (im_warped, vfp, xf_out, &pih, moving_image,
default_value, 0, 1);
if (img_out_fn[0]) {
@@ -325,7 +331,7 @@ save_output (
if (valid_roi_out_fn[0]) {
logfile_printf ("Warping valid ROI...\n");
Plm_image::Pointer valid_roi
- = Plm_image::clone (regd->moving_image);
+ = Plm_image::clone (moving_image);
#if defined (commentout)
plm_warp (im_warped, vfp, xf_out, &pih, regd->moving_image,
default_value, 0, 1);
@@ -336,7 +342,7 @@ save_output (
Xform::Pointer
Registration::do_registration_stage (
- Stage_parms* stage /* Input */
+ Stage_parms* stage
)
{
Registration_data::Pointer regd = d_ptr->rdata;
@@ -384,8 +390,7 @@ Registration::do_registration_stage (
if (stage->impl_type == IMPLEMENTATION_ITK) {
xf_out = do_itk_registration_stage (regd.get(), xf_in, stage);
} else {
- xf_out = do_gpuit_bspline_stage (regp.get(), regd.get(),
- xf_in, stage);
+ xf_out = do_gpuit_bspline_stage (regd.get(), xf_in, stage);
}
break;
case STAGE_TRANSFORM_VECTOR_FIELD:
@@ -418,23 +423,29 @@ set_automatic_parameters (
Registration_data::Pointer& regd,
Registration_parms::Pointer& regp)
{
+ Plm_image::Pointer fixed_image = regd->get_fixed_image();
+ Plm_image::Pointer moving_image = regd->get_moving_image();
std::list<Stage_parms*>& stages = regp->get_stages();
std::list<Stage_parms*>::iterator it;
for (it = stages.begin(); it != stages.end(); it++) {
Stage_parms* sp = *it;
if (sp->resample_type == RESAMPLE_AUTO) {
set_auto_resample (
- sp->resample_rate_fixed, regd->fixed_image.get());
+ sp->resample_rate_fixed, fixed_image.get());
set_auto_resample (
- sp->resample_rate_moving, regd->moving_image.get());
+ sp->resample_rate_moving, moving_image.get());
}
}
}
static void
-check_output_resolution (Xform::Pointer& xf_out, Registration_data::Pointer& regd)
+check_output_resolution (
+ Xform::Pointer& xf_out,
+ Registration_data::Pointer& regd)
{
- Volume *fixed = regd->fixed_image->get_vol ();
+ Plm_image::Pointer fixed_image = regd->get_fixed_image();
+ Plm_image::Pointer moving_image = regd->get_moving_image();
+ Volume *fixed = fixed_image->get_vol ();
int ss[3];
Plm_image_header pih;
float grid_spacing[3];
diff --git a/src/plastimatch/register/registration.h b/src/plastimatch/register/registration.h
index aca6409..725c330 100644
--- a/src/plastimatch/register/registration.h
+++ b/src/plastimatch/register/registration.h
@@ -19,8 +19,8 @@ public:
Registration ();
~Registration ();
public:
- int set_command_file (const std::string& command_file);
- int set_command_string (const std::string& command_string);
+ Plm_return_code set_command_file (const std::string& command_file);
+ Plm_return_code set_command_string (const std::string& command_string);
void set_fixed_image (Plm_image::Pointer& fixed);
void set_moving_image (Plm_image::Pointer& moving);
void set_fixed_roi (Plm_image::Pointer& fixed_roi);
diff --git a/src/plastimatch/register/registration_data.cxx b/src/plastimatch/register/registration_data.cxx
index d28b14b..2e146b4 100644
--- a/src/plastimatch/register/registration_data.cxx
+++ b/src/plastimatch/register/registration_data.cxx
@@ -3,19 +3,25 @@
----------------------------------------------------------------------- */
#include "plmregister_config.h"
+#include "distance_map.h"
#include "logfile.h"
#include "plm_image.h"
#include "plm_image_type.h"
#include "print_and_exit.h"
#include "registration_data.h"
#include "registration_parms.h"
+#include "registration_resample.h"
#include "shared_parms.h"
#include "stage_parms.h"
+#include "volume_grad.h"
class Registration_data_private
{
public:
Stage_parms auto_parms;
+ std::map <std::string, Registration_similarity_data::Pointer>
+ similarity_images;
+ std::list<std::string> similarity_indices;
public:
Registration_data_private () {
}
@@ -40,19 +46,6 @@ Registration_data::~Registration_data ()
void
Registration_data::load_global_input_files (Registration_parms::Pointer& regp)
{
- Plm_image_type image_type = PLM_IMG_TYPE_ITK_FLOAT;
-
- /* Load images */
- logfile_printf ("Loading fixed image: %s\n",
- regp->get_fixed_fn().c_str());
- this->fixed_image = Plm_image::New (new Plm_image (
- regp->get_fixed_fn(), image_type));
-
- logfile_printf ("Loading moving image: %s\n",
- regp->get_moving_fn().c_str());
- this->moving_image = Plm_image::New (new Plm_image (
- regp->get_moving_fn(), image_type));
-
this->load_shared_input_files (regp->get_shared_parms());
}
@@ -65,18 +58,44 @@ Registration_data::load_stage_input_files (const Stage_parms* stage)
void
Registration_data::load_shared_input_files (const Shared_parms* shared)
{
- /* load "global" rois */
- if (shared->fixed_roi_fn != "") {
- logfile_printf ("Loading fixed roi: %s\n",
- shared->fixed_roi_fn.c_str());
- this->fixed_roi = Plm_image::New (
- shared->fixed_roi_fn, PLM_IMG_TYPE_ITK_UCHAR);
- }
- if (shared->moving_roi_fn != "") {
- logfile_printf ("Loading moving roi: %s\n",
- shared->moving_roi_fn.c_str());
- this->moving_roi = Plm_image::New (
- shared->moving_roi_fn, PLM_IMG_TYPE_ITK_UCHAR);
+ std::map<std::string,Metric_parms>::const_iterator metric_it;
+ for (metric_it = shared->metric.begin();
+ metric_it != shared->metric.end(); ++metric_it)
+ {
+ const std::string& index = metric_it->first;
+ const Metric_parms& mp = metric_it->second;
+
+ /* Sanity check -- there should be at least a fixed and moving */
+ if (mp.fixed_fn == "") {
+ continue;
+ }
+ if (mp.moving_fn == "") {
+ continue;
+ }
+
+ /* Load images */
+ logfile_printf ("Loading fixed image [%s]: %s\n",
+ index.c_str(), mp.fixed_fn.c_str());
+ this->set_fixed_image (index,
+ Plm_image::New (mp.fixed_fn, PLM_IMG_TYPE_ITK_FLOAT));
+ logfile_printf ("Loading moving image [%s]: %s\n",
+ index.c_str(), mp.moving_fn.c_str());
+ this->set_moving_image (index,
+ Plm_image::New (mp.moving_fn, PLM_IMG_TYPE_ITK_FLOAT));
+
+ /* Load rois */
+ if (mp.fixed_roi_fn != "") {
+ logfile_printf ("Loading fixed roi [%s]: %s\n",
+ index.c_str(), mp.fixed_roi_fn.c_str());
+ this->set_fixed_roi (index,
+ Plm_image::New (mp.fixed_roi_fn, PLM_IMG_TYPE_ITK_UCHAR));
+ }
+ if (mp.moving_roi_fn != "") {
+ logfile_printf ("Loading moving roi [%s]: %s\n",
+ index.c_str(), mp.moving_roi_fn.c_str());
+ this->set_moving_roi (index,
+ Plm_image::New (mp.moving_roi_fn, PLM_IMG_TYPE_ITK_UCHAR));
+ }
}
/* load stiffness */
@@ -119,8 +138,221 @@ Registration_data::load_shared_input_files (const Shared_parms* shared)
}
}
+Registration_similarity_data::Pointer&
+Registration_data::get_similarity_images (
+ std::string index)
+{
+ if (index == "") {
+ index = DEFAULT_IMAGE_KEY;
+ }
+ if (!d_ptr->similarity_images[index]) {
+ d_ptr->similarity_images[index] = Registration_similarity_data::New();
+ }
+ return d_ptr->similarity_images[index];
+}
+
+void
+Registration_data::set_fixed_image (const Plm_image::Pointer& image)
+{
+ this->set_fixed_image (DEFAULT_IMAGE_KEY, image);
+}
+
+void
+Registration_data::set_fixed_image (
+ const std::string& index,
+ const Plm_image::Pointer& image)
+{
+ this->get_similarity_images(index)->fixed = image;
+}
+
+void
+Registration_data::set_moving_image (const Plm_image::Pointer& image)
+{
+ this->set_moving_image (DEFAULT_IMAGE_KEY, image);
+}
+
+void
+Registration_data::set_moving_image (
+ const std::string& index,
+ const Plm_image::Pointer& image)
+{
+ this->get_similarity_images(index)->moving = image;
+}
+
+void
+Registration_data::set_fixed_roi (const Plm_image::Pointer& image)
+{
+ this->set_fixed_roi (DEFAULT_IMAGE_KEY, image);
+}
+
+void
+Registration_data::set_fixed_roi (
+ const std::string& index,
+ const Plm_image::Pointer& image)
+{
+ this->get_similarity_images(index)->fixed_roi = image;
+}
+
+void
+Registration_data::set_moving_roi (const Plm_image::Pointer& image)
+{
+ this->set_moving_roi (DEFAULT_IMAGE_KEY, image);
+}
+
+void
+Registration_data::set_moving_roi (
+ const std::string& index,
+ const Plm_image::Pointer& image)
+{
+ this->get_similarity_images(index)->moving_roi = image;
+}
+
+Plm_image::Pointer&
+Registration_data::get_fixed_image ()
+{
+ return this->get_fixed_image(DEFAULT_IMAGE_KEY);
+}
+
+Plm_image::Pointer&
+Registration_data::get_fixed_image (
+ const std::string& index)
+{
+ return this->get_similarity_images(index)->fixed;
+}
+
+Plm_image::Pointer&
+Registration_data::get_moving_image ()
+{
+ return this->get_moving_image(DEFAULT_IMAGE_KEY);
+}
+
+Plm_image::Pointer&
+Registration_data::get_moving_image (
+ const std::string& index)
+{
+ return this->get_similarity_images(index)->moving;
+}
+
+Plm_image::Pointer&
+Registration_data::get_fixed_roi ()
+{
+ return this->get_fixed_roi(DEFAULT_IMAGE_KEY);
+}
+
+Plm_image::Pointer&
+Registration_data::get_fixed_roi (
+ const std::string& index)
+{
+ return this->get_similarity_images(index)->fixed_roi;
+}
+
+Plm_image::Pointer&
+Registration_data::get_moving_roi ()
+{
+ return this->get_moving_roi(DEFAULT_IMAGE_KEY);
+}
+
+Plm_image::Pointer&
+Registration_data::get_moving_roi (
+ const std::string& index)
+{
+ return this->get_similarity_images(index)->moving_roi;
+}
+
+const std::list<std::string>&
+Registration_data::get_similarity_indices ()
+{
+ d_ptr->similarity_indices.clear ();
+
+ std::map<std::string,
+ Registration_similarity_data::Pointer>::const_iterator it;
+ for (it = d_ptr->similarity_images.begin();
+ it != d_ptr->similarity_images.end(); ++it)
+ {
+ if (it->second->fixed && it->second->moving) {
+ if (it->first == DEFAULT_IMAGE_KEY) {
+ d_ptr->similarity_indices.push_front (it->first);
+ } else {
+ d_ptr->similarity_indices.push_back (it->first);
+ }
+ }
+ }
+ return d_ptr->similarity_indices;
+}
+
Stage_parms*
Registration_data::get_auto_parms ()
{
return &d_ptr->auto_parms;
}
+
+static Volume::Pointer
+make_dmap (const Volume::Pointer& image)
+{
+ Plm_image::Pointer pi = Plm_image::New (image);
+ Distance_map dm;
+
+ dm.set_input_image (pi);
+ dm.run ();
+
+ Plm_image im_out (dm.get_output_image());
+ return im_out.get_volume_float ();
+}
+
+void populate_similarity_list (
+ std::list<Metric_state::Pointer>& similarity_data,
+ Registration_data *regd,
+ const Stage_parms *stage
+)
+{
+ const Shared_parms *shared = stage->get_shared_parms();
+
+ /* Clear out the list */
+ similarity_data.clear ();
+
+ const std::list<std::string>& similarity_indices
+ = regd->get_similarity_indices ();
+ std::list<std::string>::const_iterator ind_it;
+ for (ind_it = similarity_indices.begin();
+ ind_it != similarity_indices.end(); ++ind_it)
+ {
+ Plm_image::Pointer fixed_image = regd->get_fixed_image (*ind_it);
+ Plm_image::Pointer moving_image = regd->get_moving_image (*ind_it);
+ Volume::Pointer& fixed = fixed_image->get_volume_float ();
+ Volume::Pointer& moving = moving_image->get_volume_float ();
+
+ Metric_state::Pointer ssi = Metric_state::New();
+
+ /* Subsample images */
+ ssi->fixed_ss = registration_resample_volume (
+ fixed, stage, stage->resample_rate_fixed);
+ ssi->moving_ss = registration_resample_volume (
+ moving, stage, stage->resample_rate_moving);
+
+ /* Metric */
+ const Metric_parms& metric_parms = shared->metric.find(*ind_it)->second;
+ ssi->metric_type = metric_parms.metric_type;
+ if (ssi->metric_type == SIMILARITY_METRIC_MI_VW) {
+ ssi->metric_type = SIMILARITY_METRIC_MI_MATTES;
+ }
+ ssi->metric_lambda = metric_parms.metric_lambda;
+
+ /* Gradient magnitude is MSE on gradient image */
+ if (ssi->metric_type == SIMILARITY_METRIC_GM) {
+ ssi->fixed_ss = volume_gradient_magnitude (ssi->fixed_ss);
+ ssi->moving_ss = volume_gradient_magnitude (ssi->moving_ss);
+ }
+
+ /* Distance map is MSE on distance map images */
+ if (ssi->metric_type == SIMILARITY_METRIC_DMAP) {
+ ssi->fixed_ss = make_dmap (ssi->fixed_ss);
+ ssi->moving_ss = make_dmap (ssi->moving_ss);
+ }
+
+ /* Make spatial gradient image */
+ ssi->moving_grad = volume_gradient (ssi->moving_ss);
+
+ /* Append to list */
+ similarity_data.push_back (ssi);
+ }
+}
diff --git a/src/plastimatch/register/registration_data.h b/src/plastimatch/register/registration_data.h
index 9b3ee89..491c2a0 100644
--- a/src/plastimatch/register/registration_data.h
+++ b/src/plastimatch/register/registration_data.h
@@ -6,9 +6,11 @@
#include "plmregister_config.h"
#include "itk_image_type.h"
+#include "metric_state.h"
#include "plm_image.h"
#include "pointset.h"
#include "registration_parms.h"
+#include "registration_similarity_data.h"
#include "smart_pointer.h"
class Plm_image;
@@ -16,16 +18,21 @@ class Registration_data_private;
class Shared_parms;
class Stage_parms;
+/*! \brief
+ * The Registration_data class holds global data shared across multiple
+ * registration stages. These data include images, landmarks,
+ * ROIs, and automatic parameters.
+ */
class PLMREGISTER_API Registration_data {
public:
SMART_POINTER_SUPPORT (Registration_data);
Registration_data_private *d_ptr;
public:
- /* Input images */
- Plm_image::Pointer fixed_image;
- Plm_image::Pointer moving_image;
- Plm_image::Pointer fixed_roi;
- Plm_image::Pointer moving_roi;
+ Registration_data ();
+ ~Registration_data ();
+
+public:
+ /* Regularization stiffness image */
Plm_image::Pointer fixed_stiffness;
/* Input landmarks */
@@ -38,13 +45,47 @@ public:
FloatImageType::SpacingType fixed_region_spacing;
public:
- Registration_data ();
- ~Registration_data ();
void load_global_input_files (Registration_parms::Pointer& regp);
void load_stage_input_files (const Stage_parms* regp);
void load_shared_input_files (const Shared_parms* shared);
+ Registration_similarity_data::Pointer&
+ get_similarity_images (std::string index);
+
+ void set_fixed_image (const Plm_image::Pointer& image);
+ void set_fixed_image (const std::string& index,
+ const Plm_image::Pointer& image);
+ void set_moving_image (const Plm_image::Pointer& image);
+ void set_moving_image (const std::string& index,
+ const Plm_image::Pointer& image);
+ void set_fixed_roi (const Plm_image::Pointer& image);
+ void set_fixed_roi (const std::string& index,
+ const Plm_image::Pointer& image);
+ void set_moving_roi (const Plm_image::Pointer& image);
+ void set_moving_roi (const std::string& index,
+ const Plm_image::Pointer& image);
+ Plm_image::Pointer& get_fixed_image ();
+ Plm_image::Pointer& get_fixed_image (const std::string& index);
+ Plm_image::Pointer& get_moving_image ();
+ Plm_image::Pointer& get_moving_image (const std::string& index);
+ Plm_image::Pointer& get_fixed_roi ();
+ Plm_image::Pointer& get_fixed_roi (const std::string& index);
+ Plm_image::Pointer& get_moving_roi ();
+ Plm_image::Pointer& get_moving_roi (const std::string& index);
+
+ /*! \brief Get list of indices which have both a fixed and moving image.
+ The default image (index "0") will be the first index in the list.
+ The remaining indices will be sorted in order they appear
+ in the command file. */
+ const std::list<std::string>& get_similarity_indices ();
+
Stage_parms* get_auto_parms ();
};
+void populate_similarity_list (
+ std::list<Metric_state::Pointer>& similarity_data,
+ Registration_data *regd,
+ const Stage_parms *stage
+);
+
#endif
diff --git a/src/plastimatch/register/registration_metric_type.h b/src/plastimatch/register/registration_metric_type.h
deleted file mode 100755
index 90ae189..0000000
--- a/src/plastimatch/register/registration_metric_type.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* -----------------------------------------------------------------------
- See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
- ----------------------------------------------------------------------- */
-#ifndef _registration_metric_type_h_
-#define _registration_metric_type_h_
-
-enum Registration_metric_type {
- REGISTRATION_METRIC_NONE,
- REGISTRATION_METRIC_GM,
- REGISTRATION_METRIC_MI_MATTES,
- REGISTRATION_METRIC_MI_VW,
- REGISTRATION_METRIC_MSE,
- REGISTRATION_METRIC_NMI
-};
-
-const char* registration_metric_type_string (Registration_metric_type);
-
-#endif
diff --git a/src/plastimatch/register/registration_parms.cxx b/src/plastimatch/register/registration_parms.cxx
index 62b974b..df210ef 100644
--- a/src/plastimatch/register/registration_parms.cxx
+++ b/src/plastimatch/register/registration_parms.cxx
@@ -10,13 +10,8 @@
#include <stdio.h>
#include <string.h>
#include <time.h>
-#if defined (_WIN32)
-// win32 directory stuff
-#else
-#include <sys/types.h>
-#include <dirent.h>
-#endif
+#include "groupwise_parms.h"
#include "logfile.h"
#include "parameter_parser.h"
#include "plm_return_code.h"
@@ -28,22 +23,19 @@
class Registration_parms_private
{
public:
- std::string moving_fn;
- std::string fixed_fn;
std::list<Stage_parms*> stages;
Shared_parms *shared;
-
- /* GCS FIX: These were disabled, and are needing some re-engineering */
- std::list< std::string > moving_jobs;
- std::list< std::string > fixed_jobs;
+ Groupwise_parms *gw_parms;
public:
Registration_parms_private () {
shared = new Shared_parms;
+ gw_parms = 0;
}
~Registration_parms_private () {
delete_all_stages ();
delete shared;
+ delete gw_parms;
}
void delete_all_stages () {
std::list<Stage_parms*>::iterator it;
@@ -62,6 +54,8 @@ public:
Registration_parms_parser (Registration_parms *rp)
{
this->rp = rp;
+ this->enable_key_regularization (true);
+ this->set_default_index (DEFAULT_IMAGE_KEY);
}
public:
virtual Plm_return_code begin_section (
@@ -94,9 +88,10 @@ public:
virtual Plm_return_code set_key_value (
const std::string& section,
const std::string& key,
+ const std::string& index,
const std::string& val)
{
- return this->rp->set_key_value (section, key, val);
+ return this->rp->set_key_value (section, key, index, val);
}
};
@@ -110,8 +105,6 @@ Registration_parms::Registration_parms()
init_type = STAGE_TRANSFORM_NONE;
default_value = 0.0;
num_stages = 0;
- job_idx = 0;
- num_jobs = 1;
}
Registration_parms::~Registration_parms()
@@ -119,35 +112,11 @@ Registration_parms::~Registration_parms()
delete d_ptr;
}
-#if defined (GCS_FIXME) // Delete this, replace with compose_filename
-// JAS 2012.02.13 -- TODO: Move somewhere more appropriate
-static void
-check_trailing_slash (char* s)
-{
- int i=0;
- while (s[i++] != '\0');
-
- if (s[i-2] != '/') {
- strcat (s, "/");
- }
-}
-#endif
-
-
-#if defined (GCS_FIXME) // Delete this, replace with Dir_list
-int
-populate_jobs ()
-{
- /* This function should read through the directory,
- and identify the input files for each registration role
- (fixed, moving, etc.) */
-}
-#endif
-
Plm_return_code
Registration_parms::set_key_value (
const std::string& section,
- const std::string& key,
+ const std::string& key,
+ const std::string& index,
const std::string& val)
{
int rc;
@@ -178,39 +147,7 @@ Registration_parms::set_key_value (
}
/* The following keywords are only allowed globally */
- if (key == "fixed") {
- if (!section_global) goto key_only_allowed_in_section_global;
- d_ptr->fixed_fn = val;
- }
- else if (key == "moving") {
- if (!section_global) goto key_only_allowed_in_section_global;
- d_ptr->moving_fn = val;
- }
-#if defined (GCS_FIXME) // stubbed out until above is fixed
- else if (key == "fixed_dir") {
- if (!section_global) goto key_only_allowed_in_section_global;
- this->fixed_dir = val;
- check_trailing_slash (this->fixed_dir);
- this->num_jobs = populate_jobs (this->fixed_jobs, this->fixed_dir);
- }
- else if (key == "moving_dir") {
- if (!section_global) goto key_only_allowed_in_section_global;
- this->moving_dir = val;
- check_trailing_slash (this->moving_dir);
- this->num_jobs = populate_jobs (this->moving_jobs, this->moving_dir);
- }
- else if (key == "img_out_dir") {
- if (!section_global) goto key_only_allowed_in_section_global;
- this->img_out_dir = val;
- check_trailing_slash (this->img_out_dir);
- }
- else if (key == "vf_out_dir") {
- if (!section_global) goto key_only_allowed_in_section_global;
- this->vf_out_dir = val;
- check_trailing_slash (this->vf_out_dir);
- }
-#endif
- else if (key == "xf_in"
+ if (key == "xf_in"
|| key == "xform_in"
|| key == "vf_in")
{
@@ -221,8 +158,20 @@ Registration_parms::set_key_value (
if (!section_global) goto key_only_allowed_in_section_global;
this->log_fn = val;
}
+ else if (key == "group_dir") {
+ if (!section_global) goto key_only_allowed_in_section_global;
+ this->group_dir = val;
+ }
/* The following keywords are allowed either globally or in stages */
+ else if (key == "fixed") {
+ if (section_process) goto key_not_allowed_in_section_process;
+ shared->metric[index].fixed_fn = val;
+ }
+ else if (key == "moving") {
+ if (section_process) goto key_not_allowed_in_section_process;
+ shared->metric[index].moving_fn = val;
+ }
else if (key == "background_val"
|| key == "default_value")
{
@@ -240,11 +189,11 @@ Registration_parms::set_key_value (
}
else if (key == "fixed_mask" || key == "fixed_roi") {
if (section_process) goto key_not_allowed_in_section_process;
- shared->fixed_roi_fn = val;
+ shared->metric[index].fixed_roi_fn = val;
}
else if (key == "moving_mask" || key == "moving_roi") {
if (section_process) goto key_not_allowed_in_section_process;
- shared->moving_roi_fn = val;
+ shared->metric[index].moving_roi_fn = val;
}
else if (key == "fixed_roi_enable") {
if (section_process) goto key_not_allowed_in_section_process;
@@ -531,47 +480,17 @@ Registration_parms::set_key_value (
}
else if (key == "metric" || key == "smetric") {
if (!section_stage) goto key_only_allowed_in_section_stage;
- std::vector<std::string> metric_vec = string_split (val, ',');
- if (metric_vec.size() == 0) {
- goto error_exit;
- }
- stage->metric_type.clear();
- for (int i = 0; i < metric_vec.size(); i++) {
- if (metric_vec[i] == "gm") {
- stage->metric_type.push_back (REGISTRATION_METRIC_GM);
- }
- else if (metric_vec[i] == "mattes") {
- stage->metric_type.push_back (REGISTRATION_METRIC_MI_MATTES);
- }
- else if (metric_vec[i] == "mse" || metric_vec[i] == "MSE") {
- stage->metric_type.push_back (REGISTRATION_METRIC_MSE);
- }
- else if (metric_vec[i] == "mi" || metric_vec[i] == "MI") {
-#if PLM_CONFIG_LEGACY_MI_METRIC
- stage->metric_type.push_back (REGISTRATION_METRIC_MI_VW);
-#else
- stage->metric_type.push_back (REGISTRATION_METRIC_MI_MATTES);
-#endif
- }
- else if (metric_vec[i] == "mi_vw"
- || metric_vec[i] == "viola-wells")
- {
- stage->metric_type.push_back (REGISTRATION_METRIC_MI_VW);
- }
- else if (metric_vec[i] == "nmi" || metric_vec[i] == "NMI") {
- stage->metric_type.push_back (REGISTRATION_METRIC_NMI);
- }
- else {
- goto error_exit;
- }
+ if (shared->metric[index].set_metric_type (val) != PLM_SUCCESS) {
+ goto error_exit;
}
}
else if (key == "metric_lambda" || key == "smetric_lambda") {
if (!section_stage) goto key_only_allowed_in_section_stage;
- stage->metric_lambda = parse_float_string (val);
- if (stage->metric_lambda.size() == 0) {
+ float f;
+ if (sscanf (val.c_str(), "%f", &f) != 1) {
goto error_exit;
}
+ shared->metric[index].metric_lambda = f;
}
else if (key == "histogram_type") {
if (!section_stage) goto key_only_allowed_in_section_stage;
@@ -741,28 +660,28 @@ Registration_parms::set_key_value (
}
}
else if (key == "mattes_fixed_minVal"
- ||key == "mi_fixed_minVal") {
+ || key == "mi_fixed_minVal") {
if (!section_stage) goto key_only_allowed_in_section_stage;
if (sscanf (val.c_str(), "%g", &stage->mi_fixed_image_minVal) != 1) {
goto error_exit;
}
}
else if (key == "mattes_fixed_maxVal"
- ||key == "mi_fixed_maxVal") {
+ || key == "mi_fixed_maxVal") {
if (!section_stage) goto key_only_allowed_in_section_stage;
if (sscanf (val.c_str(), "%g", &stage->mi_fixed_image_maxVal) != 1) {
goto error_exit;
}
}
else if (key == "mattes_moving_minVal"
- ||key == "mi_moving_minVal") {
+ || key == "mi_moving_minVal") {
if (!section_stage) goto key_only_allowed_in_section_stage;
if (sscanf (val.c_str(), "%g", &stage->mi_moving_image_minVal) != 1) {
goto error_exit;
}
}
else if (key == "mattes_moving_maxVal"
- ||key == "mi_moving_maxVal") {
+ || key == "mi_moving_maxVal") {
if (!section_stage) goto key_only_allowed_in_section_stage;
if (sscanf (val.c_str(), "%g", &stage->mi_moving_image_maxVal) != 1) {
goto error_exit;
@@ -1083,7 +1002,7 @@ error_exit:
return PLM_ERROR;
}
-int
+Plm_return_code
Registration_parms::set_command_string (
const std::string& command_string
)
@@ -1093,7 +1012,7 @@ Registration_parms::set_command_string (
return rpp.parse_config_string (command_string);
}
-int
+Plm_return_code
Registration_parms::parse_command_file (const char* options_fn)
{
/* Read file into string */
@@ -1105,83 +1024,6 @@ Registration_parms::parse_command_file (const char* options_fn)
return this->set_command_string (buffer.str());
}
-#if defined (GCS_FIX) // Needs re-engineering
-/* JAS 2012.03.13
- * This is a temp solution */
-/* GCS 2012-12-28: Nb. regp->job_idx must be set prior to calling
- this function */
-void
-Registration_parms::set_job_paths (void)
-{
- /* Setup input paths */
- if (*(this->fixed_dir)) {
- d_ptr->fixed_fn = string_format (
- "%s%s", this->fixed_dir, this->fixed_jobs[this->job_idx]);
- }
- if (*(this->moving_dir)) {
- d_ptr->moving_fn = string_format (
- "%s%s", this->moving_dir, this->moving_jobs[this->job_idx]);
- }
-
- /* Setup output paths */
- /* NOTE: For now, output files inherit moving image names */
- if (*(this->img_out_dir)) {
- if (!strcmp (this->img_out_dir, this->moving_dir)) {
- strcpy (this->img_out_fn, this->img_out_dir);
- strcat (this->img_out_fn, "warp/");
- strcat (this->img_out_fn, this->moving_jobs[this->job_idx]);
- } else {
- strcpy (this->img_out_fn, this->img_out_dir);
- strcat (this->img_out_fn, this->moving_jobs[this->job_idx]);
- }
- /* If not dicom, we give a default name */
- if (this->img_out_fmt != IMG_OUT_FMT_DICOM) {
- std::string fn = string_format ("%s.mha", this->img_out_fn);
- strcpy (this->img_out_fn, fn.c_str());
- }
- } else {
- /* Output directory not specifed but img_out was... smart fallback*/
- if (*(this->img_out_fn)) {
- strcpy (this->img_out_fn, this->moving_dir);
- strcat (this->img_out_fn, "warp/");
- strcat (this->img_out_fn, this->moving_jobs[this->job_idx]);
- }
- }
- if (*(this->vf_out_dir)) {
- if (!strcmp (this->vf_out_dir, this->moving_dir)) {
- strcpy (this->vf_out_fn, this->img_out_dir);
- strcat (this->vf_out_fn, "vf/");
- strcat (this->vf_out_fn, this->moving_jobs[this->job_idx]);
- } else {
- strcpy (this->vf_out_fn, this->vf_out_dir);
- strcat (this->vf_out_fn, this->moving_jobs[this->job_idx]);
- }
- /* Give a default name */
- std::string fn = string_format ("%s_vf.mha", this->vf_out_fn);
- strcpy (this->vf_out_fn, fn.c_str());
- } else {
- /* Output directory not specifed but vf_out was... smart fallback*/
- if (*(this->vf_out_fn)) {
- strcpy (this->vf_out_fn, this->moving_dir);
- strcat (this->vf_out_fn, "vf/");
- strcat (this->vf_out_fn, this->moving_jobs[this->job_idx]);
- }
- }
-}
-#endif
-
-const std::string&
-Registration_parms::get_fixed_fn ()
-{
- return d_ptr->fixed_fn;
-}
-
-const std::string&
-Registration_parms::get_moving_fn ()
-{
- return d_ptr->moving_fn;
-}
-
Shared_parms*
Registration_parms::get_shared_parms ()
{
diff --git a/src/plastimatch/register/registration_parms.h b/src/plastimatch/register/registration_parms.h
index 28e2d03..1438944 100644
--- a/src/plastimatch/register/registration_parms.h
+++ b/src/plastimatch/register/registration_parms.h
@@ -15,11 +15,14 @@
#include "smart_pointer.h"
#include "threading.h"
+class Groupwise_parms;
class Plm_image;
class Registration_parms_private;
class Shared_parms;
class Stage_parms;
+#define DEFAULT_IMAGE_KEY "0"
+
class PLMREGISTER_API Registration_parms {
public:
SMART_POINTER_SUPPORT (Registration_parms);
@@ -43,28 +46,29 @@ public:
std::string fixed_dir;
std::string img_out_dir;
std::string vf_out_dir;
- int job_idx;
- int num_jobs;
+
+ /* for groupwise registration */
+ std::string group_dir;
public:
Registration_parms();
~Registration_parms();
public:
- int set_command_string (const std::string& command_string);
+ Plm_return_code set_command_string (const std::string& command_string);
Plm_return_code set_key_value (
const std::string& section,
const std::string& key,
+ const std::string& index,
const std::string& val);
- int parse_command_file (const char* options_fn);
+ Plm_return_code parse_command_file (const char* options_fn);
void set_job_paths (void);
public:
- const std::string& get_fixed_fn ();
- const std::string& get_moving_fn ();
Shared_parms* get_shared_parms ();
void delete_all_stages ();
std::list<Stage_parms*>& get_stages ();
Stage_parms* append_stage ();
Stage_parms* append_process_stage ();
+ Groupwise_parms* get_groupwise_parms ();
};
#endif
diff --git a/src/plastimatch/register/registration_resample.cxx b/src/plastimatch/register/registration_resample.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/register/registration_resample.h b/src/plastimatch/register/registration_resample.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/register/registration_similarity_data.h b/src/plastimatch/register/registration_similarity_data.h
new file mode 100644
index 0000000..c3fae72
--- /dev/null
+++ b/src/plastimatch/register/registration_similarity_data.h
@@ -0,0 +1,24 @@
+/* -----------------------------------------------------------------------
+ See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
+ ----------------------------------------------------------------------- */
+#ifndef _registration_similarity_data_h_
+#define _registration_similarity_data_h_
+
+#include "plmregister_config.h"
+
+/*! \brief
+ * The Registration_similarity_data class holds original or processed
+ * images used for similarity measure calculations over multiple stages.
+ */
+class PLMREGISTER_API Registration_similarity_data
+{
+public:
+ SMART_POINTER_SUPPORT (Registration_similarity_data);
+public:
+ Plm_image::Pointer fixed;
+ Plm_image::Pointer moving;
+ Plm_image::Pointer fixed_roi;
+ Plm_image::Pointer moving_roi;
+};
+
+#endif
diff --git a/src/plastimatch/register/registration_util.cxx b/src/plastimatch/register/registration_util.cxx
new file mode 100644
index 0000000..57685da
--- /dev/null
+++ b/src/plastimatch/register/registration_util.cxx
@@ -0,0 +1,44 @@
+/* -----------------------------------------------------------------------
+ See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
+ ----------------------------------------------------------------------- */
+#include "plmregister_config.h"
+#include "itkImageRegionConstIteratorWithIndex.h"
+
+#include "registration_util.h"
+#include "shared_parms.h"
+
+plm_long
+count_fixed_voxels (
+ Registration_data *regd,
+ Stage_parms* stage,
+ FloatImageType::Pointer& fixed_ss)
+{
+ // Do simple calculation if there is no ROI
+ const Shared_parms *shared = stage->get_shared_parms();
+ if (!shared->fixed_roi_enable || !regd->get_fixed_roi()) {
+ plm_long dim[3];
+ get_image_header (dim, 0, 0, fixed_ss);
+ return dim[0] * dim[1] * dim[2];
+ }
+
+ // Else, iterate through image to find voxels where ROI not zero
+ Plm_image::Pointer& fixed_roi = regd->get_fixed_roi ();
+ const UCharImageType::Pointer itk_fixed_roi = fixed_roi->itk_uchar ();
+ typedef itk::ImageRegionConstIteratorWithIndex < FloatImageType
+ > IteratorType;
+ FloatImageType::RegionType region = fixed_ss->GetLargestPossibleRegion();
+ IteratorType it (fixed_ss, region);
+ plm_long num_voxels = 0;
+ for (it.GoToBegin(); !it.IsAtEnd(); ++it) {
+ FloatImageType::PointType phys_loc;
+ fixed_ss->TransformIndexToPhysicalPoint (it.GetIndex(), phys_loc);
+ UCharImageType::IndexType roi_idx;
+ bool is_inside = itk_fixed_roi->TransformPhysicalPointToIndex (
+ phys_loc, roi_idx);
+ if (is_inside && itk_fixed_roi->GetPixel (roi_idx)) {
+ num_voxels ++;
+ }
+ }
+ return num_voxels;
+}
+
diff --git a/src/plastimatch/register/registration_resample.h b/src/plastimatch/register/registration_util.h
old mode 100755
new mode 100644
similarity index 55%
copy from src/plastimatch/register/registration_resample.h
copy to src/plastimatch/register/registration_util.h
index 111ffd2..3ad90bb
--- a/src/plastimatch/register/registration_resample.h
+++ b/src/plastimatch/register/registration_util.h
@@ -1,18 +1,17 @@
/* -----------------------------------------------------------------------
See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
----------------------------------------------------------------------- */
-#ifndef _registration_resample_h_
-#define _registration_resample_h_
+#ifndef _registration_util_h_
+#define _registration_util_h_
#include "plmregister_config.h"
+#include "itk_image_type.h"
+#include "registration_data.h"
#include "stage_parms.h"
-#include "volume.h"
-Volume::Pointer
-registration_resample_volume (
- const Volume::Pointer& vol,
- const Stage_parms* stage,
- const float resample_rate[3]
-);
+plm_long
+count_fixed_voxels (Registration_data *regd,
+ Stage_parms* stage,
+ FloatImageType::Pointer& fixed_ss);
#endif
diff --git a/src/plastimatch/register/shared_parms.cxx b/src/plastimatch/register/shared_parms.cxx
old mode 100755
new mode 100644
index f861358..947bb8e
--- a/src/plastimatch/register/shared_parms.cxx
+++ b/src/plastimatch/register/shared_parms.cxx
@@ -3,10 +3,13 @@
----------------------------------------------------------------------- */
#include "plmregister_config.h"
+#include "logfile.h"
+#include "registration_parms.h"
#include "shared_parms.h"
Shared_parms::Shared_parms ()
{
+ this->metric[DEFAULT_IMAGE_KEY] = Metric_parms ();
this->fixed_roi_enable = true;
this->moving_roi_enable = true;
this->fixed_stiffness_enable = true;
@@ -18,6 +21,7 @@ Shared_parms::Shared_parms ()
Shared_parms::Shared_parms (const Shared_parms& s)
{
+ this->metric = s.metric;
this->fixed_roi_enable = s.fixed_roi_enable;
this->moving_roi_enable = s.moving_roi_enable;
this->fixed_stiffness_enable = s.fixed_stiffness_enable;
@@ -33,9 +37,22 @@ Shared_parms::~Shared_parms ()
void
Shared_parms::copy (const Shared_parms *s)
{
+ this->metric = s->metric;
this->fixed_roi_enable = s->fixed_roi_enable;
this->moving_roi_enable = s->moving_roi_enable;
+ this->fixed_stiffness_enable = s->fixed_stiffness_enable;
this->legacy_subsampling = s->legacy_subsampling;
/* filenames do not propagate when copied */
}
+
+void
+Shared_parms::log ()
+{
+ lprintf ("LOG Shared parms\n");
+ std::map<std::string, Metric_parms>::iterator it;
+ for (it = this->metric.begin(); it != this->metric.end(); ++it) {
+ lprintf ("Shared metric | %s | %d\n", it->first.c_str(),
+ it->second.metric_type);
+ }
+}
diff --git a/src/plastimatch/register/shared_parms.h b/src/plastimatch/register/shared_parms.h
old mode 100755
new mode 100644
index b6a2d31..711c14a
--- a/src/plastimatch/register/shared_parms.h
+++ b/src/plastimatch/register/shared_parms.h
@@ -5,7 +5,9 @@
#define _shared_parms_h_
#include "plmregister_config.h"
+#include <map>
#include <string>
+#include "metric_parms.h"
class PLMREGISTER_API Shared_parms {
public:
@@ -14,11 +16,12 @@ public:
~Shared_parms ();
public:
+ /* Similarity parms */
+ std::map<std::string, Metric_parms> metric;
+
/* ROI */
bool fixed_roi_enable;
bool moving_roi_enable;
- std::string fixed_roi_fn;
- std::string moving_roi_fn;
std::string valid_roi_out_fn;
/* Stiffness map */
@@ -37,6 +40,7 @@ public:
public:
void copy (const Shared_parms *s);
+ void log ();
};
#endif
diff --git a/src/plastimatch/register/registration_metric_type.cxx b/src/plastimatch/register/similarity_metric_type.cxx
similarity index 59%
rename from src/plastimatch/register/registration_metric_type.cxx
rename to src/plastimatch/register/similarity_metric_type.cxx
index 432da22..a511780 100644
--- a/src/plastimatch/register/registration_metric_type.cxx
+++ b/src/plastimatch/register/similarity_metric_type.cxx
@@ -4,23 +4,25 @@
#include "plmbase_config.h"
#include <stdio.h>
#include <string.h>
-#include "registration_metric_type.h"
+#include "similarity_metric_type.h"
const char*
-registration_metric_type_string (Registration_metric_type type)
+similarity_metric_type_string (Similarity_metric_type type)
{
switch (type) {
- case REGISTRATION_METRIC_NONE:
+ case SIMILARITY_METRIC_NONE:
return "none";
- case REGISTRATION_METRIC_GM:
+ case SIMILARITY_METRIC_DMAP:
+ return "DMAP";
+ case SIMILARITY_METRIC_GM:
return "GM";
- case REGISTRATION_METRIC_MI_MATTES:
+ case SIMILARITY_METRIC_MI_MATTES:
return "MI";
- case REGISTRATION_METRIC_MI_VW:
+ case SIMILARITY_METRIC_MI_VW:
return "MIVW";
- case REGISTRATION_METRIC_MSE:
+ case SIMILARITY_METRIC_MSE:
return "MSE";
- case REGISTRATION_METRIC_NMI:
+ case SIMILARITY_METRIC_NMI:
return "NMI";
default:
return "(unkn)";
diff --git a/src/plastimatch/register/similarity_metric_type.h b/src/plastimatch/register/similarity_metric_type.h
new file mode 100644
index 0000000..a54a6fa
--- /dev/null
+++ b/src/plastimatch/register/similarity_metric_type.h
@@ -0,0 +1,19 @@
+/* -----------------------------------------------------------------------
+ See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
+ ----------------------------------------------------------------------- */
+#ifndef _similarity_metric_type_h_
+#define _similarity_metric_type_h_
+
+enum Similarity_metric_type {
+ SIMILARITY_METRIC_NONE,
+ SIMILARITY_METRIC_DMAP,
+ SIMILARITY_METRIC_GM,
+ SIMILARITY_METRIC_MI_MATTES,
+ SIMILARITY_METRIC_MI_VW,
+ SIMILARITY_METRIC_MSE,
+ SIMILARITY_METRIC_NMI
+};
+
+const char* similarity_metric_type_string (Similarity_metric_type);
+
+#endif
diff --git a/src/plastimatch/register/stage_parms.cxx b/src/plastimatch/register/stage_parms.cxx
index 68e5a29..3beec6c 100644
--- a/src/plastimatch/register/stage_parms.cxx
+++ b/src/plastimatch/register/stage_parms.cxx
@@ -50,8 +50,6 @@ Stage_parms::Stage_parms ()
threading_type = THREADING_CPU_OPENMP;
gpuid = 0;
/* Similarity metric */
- metric_type.push_back (REGISTRATION_METRIC_MSE);
- metric_lambda.push_back (1.0);
regularization_type = REGULARIZATION_BSPLINE_ANALYTIC;
demons_gradient_type = SYMMETRIC;
regularization_lambda = 0.0f;
@@ -172,8 +170,6 @@ Stage_parms::Stage_parms (const Stage_parms& s)
threading_type = s.threading_type;
gpuid = s.gpuid;
/* Similarity metric */
- metric_type = s.metric_type;
- metric_lambda = s.metric_lambda;
regularization_type = s.regularization_type;
regularization_lambda = s.regularization_lambda;
/* Image resample */
diff --git a/src/plastimatch/register/stage_parms.h b/src/plastimatch/register/stage_parms.h
index 80be1ec..3590be2 100644
--- a/src/plastimatch/register/stage_parms.h
+++ b/src/plastimatch/register/stage_parms.h
@@ -10,12 +10,12 @@
#include <ctype.h>
#include <stdlib.h>
-#include "bspline.h" /* for enums */
-#include "bspline_mi_hist.h" /* for enums */
+#include "bspline.h"
+#include "joint_histogram.h"
#include "plm_image_type.h"
#include "plm_return_code.h"
#include "process_parms.h"
-#include "registration_metric_type.h"
+#include "similarity_metric_type.h"
#include "threading.h"
enum Stage_transform_type {
@@ -127,9 +127,6 @@ public:
char alg_flavor;
Threading threading_type;
int gpuid; /* Sets GPU to use for multi-gpu machines */
- /* Similarity metric */
- std::vector<Registration_metric_type> metric_type;
- std::vector<float> metric_lambda;
/* Regularization */
Regularization_type regularization_type;
float regularization_lambda;
diff --git a/src/plastimatch/register/translation_grid_search.cxx b/src/plastimatch/register/translation_grid_search.cxx
index 536411c..cc0597b 100644
--- a/src/plastimatch/register/translation_grid_search.cxx
+++ b/src/plastimatch/register/translation_grid_search.cxx
@@ -9,12 +9,14 @@
#include "interpolate.h"
#include "interpolate_macros.h"
#include "logfile.h"
+#include "metric_parms.h"
#include "mha_io.h"
#include "plm_image.h"
#include "plm_image_header.h"
#include "print_and_exit.h"
#include "registration_data.h"
#include "registration_resample.h"
+#include "shared_parms.h"
#include "stage_parms.h"
#include "string_util.h"
#include "translation_grid_search.h"
@@ -26,16 +28,31 @@
#include "volume_resample.h"
#include "xform.h"
-static void
-translation_grid_search (
- Xform::Pointer& xf_out,
- const Stage_parms* stage,
- Stage_parms* auto_parms,
+class Translation_grid_search
+{
+public:
+ std::list<Metric_state::Pointer> similarity_data;
+
float (*translation_score) (
const Stage_parms *stage, const Volume::Pointer& fixed,
- const Volume::Pointer& moving, const float dxyz[3]),
- const Volume::Pointer& fixed,
- const Volume::Pointer& moving)
+ const Volume::Pointer& moving, const float dxyz[3]);
+ float best_score;
+ float best_translation[3];
+public:
+ void do_search (
+ Xform::Pointer& xf_out,
+ const Stage_parms* stage,
+ Stage_parms* auto_parms);
+ void do_score (
+ const Stage_parms* stage,
+ const float dxyz[3]);
+};
+
+void
+Translation_grid_search::do_search (
+ Xform::Pointer& xf_out,
+ const Stage_parms* stage,
+ Stage_parms* auto_parms)
{
/* GCS FIX: region of interest is not used */
@@ -43,6 +60,9 @@ translation_grid_search (
For these cases, we need to use bounding box to compute
search extent. */
+ Volume::Pointer& fixed = this->similarity_data.front()->fixed_ss;
+ Volume::Pointer& moving = this->similarity_data.front()->moving_ss;
+
/* Compute maximum search extent */
lprintf ("Computing grid search extent.\n");
float search_min[3];
@@ -78,15 +98,11 @@ translation_grid_search (
/* Get default value */
TranslationTransformType::Pointer old_trn = xf_out->get_trn ();
- float best_translation[3] = { 0.f, 0.f, 0.f };
- best_translation[0] = old_trn->GetParameters()[0];
- best_translation[1] = old_trn->GetParameters()[1];
- best_translation[2] = old_trn->GetParameters()[2];
- float best_score = translation_score (
- stage, fixed, moving, best_translation);
- lprintf ("[%g %g %g] %g *\n",
- best_translation[0], best_translation[1], best_translation[2],
- best_score);
+ this->best_translation[0] = old_trn->GetParameters()[0];
+ this->best_translation[1] = old_trn->GetParameters()[1];
+ this->best_translation[2] = old_trn->GetParameters()[2];
+ this->best_score = FLT_MAX;
+ this->do_score (stage, this->best_translation);
/* Compute search range */
int num_steps[3] = { 0, 0, 0 };
@@ -130,7 +146,7 @@ translation_grid_search (
} else {
search_step[d] = stage->gridsearch_step_size[d];
}
- search_min[d] = best_translation[d] - 1.5 * search_step[d];
+ search_min[d] = this->best_translation[d] - 1.5 * search_step[d];
}
}
@@ -148,27 +164,16 @@ translation_grid_search (
search_min[0] + i * search_step[0],
search_min[1] + j * search_step[1],
search_min[2] + k * search_step[2] };
- float score = translation_score (stage,
- fixed, moving, translation);
- lprintf ("[%g %g %g] %g",
- translation[0], translation[1], translation[2], score);
- if (score < best_score) {
- best_score = score;
- best_translation[0] = translation[0];
- best_translation[1] = translation[1];
- best_translation[2] = translation[2];
- lprintf (" *");
- }
- lprintf ("\n");
+ this->do_score (stage, translation);
}
}
}
/* Find the best translation */
TranslationTransformType::ParametersType xfp(3);
- xfp[0] = best_translation[0];
- xfp[1] = best_translation[1];
- xfp[2] = best_translation[2];
+ xfp[0] = this->best_translation[0];
+ xfp[1] = this->best_translation[1];
+ xfp[2] = this->best_translation[2];
/* Fixate translation into xform */
TranslationTransformType::Pointer new_trn = TranslationTransformType::New();
@@ -176,6 +181,51 @@ translation_grid_search (
xf_out->set_trn (new_trn);
}
+void
+Translation_grid_search::do_score (
+ const Stage_parms* stage,
+ const float dxyz[3])
+{
+ lprintf ("[%g %g %g]",
+ dxyz[0], dxyz[1], dxyz[2]);
+
+ std::list<Metric_state::Pointer>::iterator it;
+ float acc_score = 0.f;
+ for (it = this->similarity_data.begin();
+ it != this->similarity_data.end(); ++it)
+ {
+ const Metric_state::Pointer& ssi = *it;
+ float score = 0.f;
+ switch (ssi->metric_type) {
+ case SIMILARITY_METRIC_MSE:
+ case SIMILARITY_METRIC_GM:
+ score = translation_mse (stage, ssi, dxyz);
+ break;
+ case SIMILARITY_METRIC_MI_MATTES:
+ case SIMILARITY_METRIC_MI_VW:
+ score = translation_mi (stage, ssi, dxyz);
+ break;
+ default:
+ print_and_exit ("Metric %d not implemented with grid search\n");
+ break;
+ }
+ lprintf (" %g", score);
+ acc_score += score;
+ }
+
+ if (this->similarity_data.size() > 1) {
+ lprintf (" | %g", acc_score);
+ }
+ if (acc_score < this->best_score) {
+ this->best_score = acc_score;
+ this->best_translation[0] = dxyz[0];
+ this->best_translation[1] = dxyz[1];
+ this->best_translation[2] = dxyz[2];
+ lprintf (" *");
+ }
+ lprintf ("\n");
+}
+
Xform::Pointer
translation_grid_search_stage (
Registration_data* regd,
@@ -185,72 +235,16 @@ translation_grid_search_stage (
Xform::Pointer xf_out = Xform::New ();
Plm_image_header pih;
- Volume::Pointer& fixed = regd->fixed_image->get_volume_float ();
- Volume::Pointer& moving = regd->moving_image->get_volume_float ();
- Volume::Pointer moving_ss;
- Volume::Pointer fixed_ss;
+ Translation_grid_search tgsd;
- fixed->convert (PT_FLOAT); /* Maybe not necessary? */
- moving->convert (PT_FLOAT); /* Maybe not necessary? */
+ /* Copy similarity images and parms */
+ populate_similarity_list (tgsd.similarity_data, regd, stage);
-#if defined (commentout)
- lprintf ("SUBSAMPLE: (%g %g %g), (%g %g %g)\n",
- stage->resample_rate_fixed[0], stage->resample_rate_fixed[1],
- stage->resample_rate_fixed[2], stage->resample_rate_moving[0],
- stage->resample_rate_moving[1], stage->resample_rate_moving[2]
- );
- moving_ss = volume_subsample_vox_legacy (
- moving, stage->resample_rate_moving);
- fixed_ss = volume_subsample_vox_legacy (
- fixed, stage->resample_rate_fixed);
-#endif
- moving_ss = registration_resample_volume (
- moving, stage, stage->resample_rate_moving);
- fixed_ss = registration_resample_volume (
- fixed, stage, stage->resample_rate_fixed);
-
- if (stage->metric_type[0] == REGISTRATION_METRIC_GM) {
- fixed_ss = volume_gradient_magnitude (fixed_ss);
- moving_ss = volume_gradient_magnitude (moving_ss);
- }
-
- if (stage->debug_dir != "") {
- std::string fn;
- fn = string_format ("%s/%02d_fixed_ss.mha",
- stage->debug_dir.c_str(), stage->stage_no);
- write_mha (fn.c_str(), fixed_ss.get());
- fn = string_format ("%s/%02d_moving_ss.mha",
- stage->debug_dir.c_str(), stage->stage_no);
- write_mha (fn.c_str(), moving_ss.get());
- }
-
/* Transform input xform to itk translation */
xform_to_trn (xf_out.get(), xf_in.get(), &pih);
- /* Choose the correct score function */
- float (*translation_score) (
- const Stage_parms *stage, const Volume::Pointer& fixed,
- const Volume::Pointer& moving, const float dxyz[3])
- = &translation_mse;
- switch (stage->metric_type[0]) {
- case REGISTRATION_METRIC_MSE:
- case REGISTRATION_METRIC_GM:
- translation_score = &translation_mse;
- break;
- case REGISTRATION_METRIC_MI_MATTES:
- case REGISTRATION_METRIC_MI_VW:
- translation_score = &translation_mi;
- break;
- default:
- print_and_exit ("Metric %d not implemented with grid search\n");
- break;
- }
-
/* Run the translation optimizer */
- translation_grid_search (xf_out, stage,
- regd->get_auto_parms (),
- translation_score,
- fixed_ss, moving_ss);
+ tgsd.do_search (xf_out, stage, regd->get_auto_parms ());
return xf_out;
}
diff --git a/src/plastimatch/register/translation_mi.cxx b/src/plastimatch/register/translation_mi.cxx
index 9c6ee26..9061466 100644
--- a/src/plastimatch/register/translation_mi.cxx
+++ b/src/plastimatch/register/translation_mi.cxx
@@ -22,24 +22,18 @@
float
translation_mi (
const Stage_parms *stage,
- const Volume::Pointer& fixed,
- const Volume::Pointer& moving,
+ const Metric_state::Pointer& ssi,
const float dxyz[3])
{
- Bspline_mi_hist_set *mi_hist = new Bspline_mi_hist_set (
+ Volume *fixed = ssi->fixed_ss.get();
+ Volume *moving = ssi->moving_ss.get();
+ Joint_histogram *mi_hist = new Joint_histogram (
stage->mi_hist_type,
stage->mi_hist_fixed_bins,
stage->mi_hist_moving_bins);
- mi_hist->initialize (fixed.get(), moving.get());
+ mi_hist->initialize (fixed, moving);
mi_hist->reset_histograms ();
- float mse_score = 0.0f;
- double* f_hist = mi_hist->f_hist;
- double* m_hist = mi_hist->m_hist;
- double* j_hist = mi_hist->j_hist;
- double mhis = 0.0f; /* Moving histogram incomplete sum */
- double jhis = 0.0f; /* Joint histogram incomplete sum */
-
plm_long fijk[3], fidx; /* Indices within fixed image (vox) */
float fxyz[3]; /* Position within fixed image (mm) */
float mijk[3]; /* Indices within moving image (vox) */
@@ -67,7 +61,7 @@ translation_mi (
if (!moving->is_inside (mijk)) continue;
/* Get tri-linear interpolation fractions */
- li_clamp_3d (mijk, mijk_f, mijk_r, li_1, li_2, moving.get());
+ li_clamp_3d (mijk, mijk_f, mijk_r, li_1, li_2, moving);
/* Find the fixed image linear index */
fidx = volume_index (fixed->dim, fijk);
@@ -78,8 +72,7 @@ translation_mi (
midx_f = volume_index (moving->dim, mijk_f);
/* Add to histogram */
- mi_hist->add_pvi_8 (
- fixed.get(), moving.get(), fidx, midx_f, li_1, li_2);
+ mi_hist->add_pvi_8 (fixed, moving, fidx, midx_f, li_1, li_2);
num_vox++;
}
diff --git a/src/plastimatch/register/translation_mi.h b/src/plastimatch/register/translation_mi.h
index 53c29f8..0d9bad8 100644
--- a/src/plastimatch/register/translation_mi.h
+++ b/src/plastimatch/register/translation_mi.h
@@ -12,8 +12,7 @@ class Stage_parms;
float
translation_mi (
const Stage_parms *stage,
- const Volume::Pointer& fixed,
- const Volume::Pointer& moving,
+ const Metric_state::Pointer& ssi,
const float dxyz[3]);
#endif
diff --git a/src/plastimatch/register/translation_mse.cxx b/src/plastimatch/register/translation_mse.cxx
index 8cce5cb..dfcd4ad 100644
--- a/src/plastimatch/register/translation_mse.cxx
+++ b/src/plastimatch/register/translation_mse.cxx
@@ -22,8 +22,7 @@
float
translation_mse (
const Stage_parms *stage,
- const Volume::Pointer& fixed,
- const Volume::Pointer& moving,
+ const Metric_state::Pointer& ssi,
const float dxyz[3])
{
plm_long fijk[3], fv; /* Indices within fixed image (vox) */
@@ -37,7 +36,8 @@ translation_mse (
plm_long mijk_r[3]; /* Round */
float m_val;
- Volume *mvol = moving.get();
+ Volume *fixed = ssi->fixed_ss.get();
+ Volume *moving = ssi->moving_ss.get();
float* f_img = (float*) fixed->img;
float* m_img = (float*) moving->img;
@@ -59,7 +59,7 @@ translation_mse (
if (!moving->is_inside (mijk)) continue;
/* Compute interpolation fractions */
- li_clamp_3d (mijk, mijk_f, mijk_r, li_1, li_2, mvol);
+ li_clamp_3d (mijk, mijk_f, mijk_r, li_1, li_2, moving);
/* Find linear index of "corner voxel" in moving image */
mvf = volume_index (moving->dim, mijk_f);
diff --git a/src/plastimatch/register/translation_mse.h b/src/plastimatch/register/translation_mse.h
index 82a3173..6ac8025 100644
--- a/src/plastimatch/register/translation_mse.h
+++ b/src/plastimatch/register/translation_mse.h
@@ -10,8 +10,7 @@
float
translation_mse (
const Stage_parms *stage,
- const Volume::Pointer& fixed,
- const Volume::Pointer& moving,
+ const Metric_state::Pointer& ssi,
const float dxyz[3]);
#endif
diff --git a/src/plastimatch/segment/autolabel_parms.cxx b/src/plastimatch/segment/autolabel_parms.cxx
index a6c7779..0c76907 100644
--- a/src/plastimatch/segment/autolabel_parms.cxx
+++ b/src/plastimatch/segment/autolabel_parms.cxx
@@ -71,9 +71,10 @@ public:
virtual Plm_return_code set_key_value (
const std::string& section,
const std::string& key,
+ const std::string& index,
const std::string& val)
{
- return this->mp->set_key_value (section, key, val);
+ return this->mp->set_key_value (section, key, index, val);
}
};
@@ -110,6 +111,7 @@ Plm_return_code
Autolabel_parms::set_key_value (
const std::string& section,
const std::string& key,
+ const std::string& index,
const std::string& val
)
{
diff --git a/src/plastimatch/segment/autolabel_parms.h b/src/plastimatch/segment/autolabel_parms.h
index 7629f93..aca33cf 100644
--- a/src/plastimatch/segment/autolabel_parms.h
+++ b/src/plastimatch/segment/autolabel_parms.h
@@ -27,6 +27,7 @@ public:
Plm_return_code set_key_value (
const std::string& section,
const std::string& key,
+ const std::string& index,
const std::string& val);
public:
diff --git a/src/plastimatch/segment/mabs.cxx b/src/plastimatch/segment/mabs.cxx
old mode 100755
new mode 100644
index 96e1d45..8624979
--- a/src/plastimatch/segment/mabs.cxx
+++ b/src/plastimatch/segment/mabs.cxx
@@ -576,7 +576,7 @@ Mabs::run_registration_loop ()
std::string command_string_plus_cog = "[STAGE]\nxform=align_center_of_gravity\n";
command_string_plus_cog.append(command_string);
int rc_cog = reg.set_command_string (command_string_plus_cog);
- if (rc != PLM_SUCCESS) {
+ if (rc_cog != PLM_SUCCESS) {
lprintf ("Skipping centers of gravity prealignment addition to command file \"%s\" \n", command_file.c_str());
continue;
}
@@ -621,11 +621,11 @@ Mabs::run_registration_loop ()
/* Warp the output image */
lprintf ("Warp output image...\n");
- Plm_image_header fixed_pih (regd->fixed_image);
+ Plm_image_header fixed_pih (fixed_image);
Plm_image::Pointer warped_image = Plm_image::New();
timer.start();
plm_warp (warped_image, 0, xf_out, &fixed_pih,
- regd->moving_image,
+ moving_image,
regp->default_value, 0, 1);
d_ptr->time_warp_img += timer.report();
@@ -933,7 +933,7 @@ Mabs::atlas_selection ()
std::string command_string_plus_cog = "[STAGE]\nxform=align_center_of_gravity\n";
command_string_plus_cog.append(command_string);
int rc_cog = reg.set_command_string (command_string_plus_cog);
- if (rc != PLM_SUCCESS) {
+ if (rc_cog != PLM_SUCCESS) {
lprintf ("Skipping centers of gravity prealignment addition to command file \"%s\" \n", d_ptr->parms->prealign_registration_config.c_str());
}
@@ -961,11 +961,11 @@ Mabs::atlas_selection ()
/* Warp the image */
lprintf ("Prealign input image...\n");
- Plm_image_header fixed_pih (regd->fixed_image);
+ Plm_image_header fixed_pih (fixed_image);
Plm_image::Pointer warped_image = Plm_image::New();
timer.start();
plm_warp (warped_image, 0, xf_out, &fixed_pih,
- regd->moving_image,
+ moving_image,
regp->default_value, 0, 1);
d_ptr->time_warp_img += timer.report();
diff --git a/src/plastimatch/segment/mabs.h b/src/plastimatch/segment/mabs.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/segment/mabs_atlas_selection.cxx b/src/plastimatch/segment/mabs_atlas_selection.cxx
index a35765c..35d2f9a 100644
--- a/src/plastimatch/segment/mabs_atlas_selection.cxx
+++ b/src/plastimatch/segment/mabs_atlas_selection.cxx
@@ -248,7 +248,7 @@ Mabs_atlas_selection::compute_similarity_value_post()
Xform::Pointer xf = reg.do_registration_pure ();
Plm_image::Pointer deformed_atlas = Plm_image::New ();
- Plm_image_header fixed_pih (regd->fixed_image);
+ Plm_image_header fixed_pih (this->subject);
plm_warp (deformed_atlas, 0, xf, &fixed_pih,
this->atlas, regp->default_value, 0, 1);
@@ -289,7 +289,7 @@ Mabs_atlas_selection::compute_similarity_value_ratio()
Xform::Pointer xf = reg.do_registration_pure ();
Plm_image::Pointer deformed_atlas = Plm_image::New ();
- Plm_image_header fixed_pih (regd->fixed_image);
+ Plm_image_header fixed_pih (this->subject);
plm_warp (deformed_atlas, 0, xf, &fixed_pih,
this->atlas, regp->default_value, 0, 1);
diff --git a/src/plastimatch/segment/mabs_parms.cxx b/src/plastimatch/segment/mabs_parms.cxx
index dead18e..4482fa1 100644
--- a/src/plastimatch/segment/mabs_parms.cxx
+++ b/src/plastimatch/segment/mabs_parms.cxx
@@ -83,6 +83,7 @@ public:
virtual Plm_return_code set_key_value (
const std::string& section,
const std::string& key,
+ const std::string& index,
const std::string& val);
};
@@ -90,6 +91,7 @@ Plm_return_code
Mabs_parms_parser::set_key_value (
const std::string& section,
const std::string& key,
+ const std::string& index,
const std::string& val)
{
/* [CONVERT] */
diff --git a/src/plastimatch/segment/mabs_stats.cxx b/src/plastimatch/segment/mabs_stats.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/segment/mabs_stats.h b/src/plastimatch/segment/mabs_stats.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/standalone/CMakeLists.txt b/src/plastimatch/standalone/CMakeLists.txt
index d7cfd94..901388b 100644
--- a/src/plastimatch/standalone/CMakeLists.txt
+++ b/src/plastimatch/standalone/CMakeLists.txt
@@ -83,9 +83,6 @@ set (OPENCL_PROBE_SRC
if (OPENCL_FOUND)
plm_add_opencl_file (OPENCL_PROBE_SRC opencl_probe.cl)
endif ()
-set (PROTON_DOSE_SRC
- proton_dose_main.cxx
- )
set (RAW_TO_MHA_SRC
raw_to_mha.c
)
@@ -351,9 +348,6 @@ plm_add_executable (hnd_to_pfm "${HND_TO_PFM_SRC}"
plm_add_executable (mha_to_raw "${MHA_TO_RAW_SRC}"
"" ""
${BUILD_IF_NOT_SLICER_EXT} ${INSTALL_NEVER})
-plm_add_executable (proton_dose "${PROTON_DOSE_SRC}"
- "${PLASTIMATCH_LIBS}" "${PLASTIMATCH_LDFLAGS}"
- ${BUILD_IF_NOT_SLICER_EXT} ${INSTALL_NEVER})
plm_add_executable (raw_to_mha "${RAW_TO_MHA_SRC}"
"" ""
${BUILD_IF_NOT_SLICER_EXT} ${INSTALL_NEVER})
diff --git a/src/plastimatch/standalone/YKThreadRegi.cpp b/src/plastimatch/standalone/YKThreadRegi.cpp
index 70001b3..cfe8123 100644
--- a/src/plastimatch/standalone/YKThreadRegi.cpp
+++ b/src/plastimatch/standalone/YKThreadRegi.cpp
@@ -53,10 +53,6 @@ void YKThreadRegi::run()//called by thread.start()
strPath.c_str());
}
- std::string strFixed = reg.get_registration_parms()->get_fixed_fn(); // return d_ptr->rparms;
- std::string strMoving = reg.get_registration_parms()->get_moving_fn();
-
-
QTime time;
time.start();
try {
diff --git a/src/plastimatch/standalone/bspline_main.cxx b/src/plastimatch/standalone/bspline_main.cxx
index d1c9a77..f2a3962 100644
--- a/src/plastimatch/standalone/bspline_main.cxx
+++ b/src/plastimatch/standalone/bspline_main.cxx
@@ -49,22 +49,6 @@ main (int argc, char* argv[])
}
#endif
- fixed = read_mha (options.fixed_fn);
- if (!fixed) exit (-1);
- moving = read_mha (options.moving_fn);
- if (!moving) exit (-1);
-
- parms->fixed = fixed;
- parms->moving = moving;
-
- volume_convert_to_float (moving);
- volume_convert_to_float (fixed);
-
- printf ("Making gradient\n");
- moving_grad = volume_make_gradient (moving);
-
- parms->moving_grad = moving_grad;
-
#if defined (commentout)
/* Load and adjust landmarks */
if (options.fixed_landmarks && options.moving_landmarks) {
@@ -77,6 +61,12 @@ main (int argc, char* argv[])
/* Debug */
//write_mha ("moving_grad.mha", moving_grad);
+ /* Load images */
+ fixed = read_mha (options.fixed_fn);
+ if (!fixed) exit (-1);
+ moving = read_mha (options.moving_fn);
+ if (!moving) exit (-1);
+
/* Allocate memory and build lookup tables */
printf ("Allocating lookup tables\n");
memset (roi_offset, 0, 3*sizeof(plm_long));
@@ -99,9 +89,31 @@ main (int argc, char* argv[])
);
}
+ /* Initialize Bspline_optimize data structure */
+ Bspline_optimize bod;
+ Bspline_state *bst = bod.get_bspline_state();
+
+ /* Set up Metric_state */
+ Metric_state::Pointer ms = Metric_state::New ();
+ ms->metric_type = options.metric_type;
+ printf ("Metric type %d\n", ms->metric_type);
+ ms->metric_lambda = 1.f;
+ ms->fixed_ss.reset (fixed);
+ ms->moving_ss.reset (moving);
+ bst->similarity_data.push_back (ms);
+
+ volume_convert_to_float (moving);
+ volume_convert_to_float (fixed);
+
+ printf ("Making gradient\n");
+ moving_grad = volume_make_gradient (ms->moving_ss.get());
+ ms->moving_grad.reset (moving_grad);
+
/* Run the optimization */
printf ("Running optimization.\n");
- bspline_optimize (bxf, parms);
+ bod.set_bspline_parms (parms);
+ bod.set_bspline_xform (bxf);
+ bod.optimize ();
printf ("Done running optimization.\n");
/* Save output transform */
@@ -157,9 +169,6 @@ main (int argc, char* argv[])
/* Free memory */
printf ("Done warping images.\n");
delete bxf;
- delete fixed;
- delete moving;
- delete moving_grad;
delete moving_warped;
delete vector_field;
diff --git a/src/plastimatch/standalone/bspline_opts.cxx b/src/plastimatch/standalone/bspline_opts.cxx
index c5e3d7b..e7b5711 100644
--- a/src/plastimatch/standalone/bspline_opts.cxx
+++ b/src/plastimatch/standalone/bspline_opts.cxx
@@ -175,13 +175,12 @@ bspline_opts_parse_args (Bspline_options* options, int argc, char* argv[])
}
i++;
if (!strcmp(argv[i], "mse")) {
- parms->metric_type[0] = REGISTRATION_METRIC_MSE;
+ options->metric_type = SIMILARITY_METRIC_MSE;
} else if (!strcmp(argv[i], "mi")) {
- parms->metric_type[0] = REGISTRATION_METRIC_MI_MATTES;
+ options->metric_type = SIMILARITY_METRIC_MI_MATTES;
} else {
print_usage ();
}
- parms->metric_lambda[0] = 1.;
}
else if (!strcmp (argv[i], "-s")) {
if (i == (argc-1) || argv[i+1][0] == '-') {
diff --git a/src/plastimatch/standalone/bspline_opts.h b/src/plastimatch/standalone/bspline_opts.h
index d99725c..1a70981 100644
--- a/src/plastimatch/standalone/bspline_opts.h
+++ b/src/plastimatch/standalone/bspline_opts.h
@@ -6,6 +6,7 @@
#include "bspline.h"
#include "bspline_parms.h"
+#include "similarity_metric_type.h"
class Bspline_options
{
@@ -20,6 +21,7 @@ public:
char* moving_landmarks;
char* warped_landmarks;
char* method;
+ Similarity_metric_type metric_type;
float landmark_stiffness;
float young_modulus;
plm_long vox_per_rgn[3];
@@ -36,6 +38,7 @@ public:
moving_landmarks = 0;
warped_landmarks = 0;
method = 0;
+ metric_type = SIMILARITY_METRIC_MSE;
landmark_stiffness = 0;
young_modulus = 0;
for (int d = 0; d < 3; d++) {
diff --git a/src/plastimatch/standalone/check_grad.cxx b/src/plastimatch/standalone/check_grad.cxx
index e7580d2..faa6943 100644
--- a/src/plastimatch/standalone/check_grad.cxx
+++ b/src/plastimatch/standalone/check_grad.cxx
@@ -19,7 +19,7 @@
#include "plm_clp.h"
#include "plm_image.h"
#include "print_and_exit.h"
-#include "registration_metric_type.h"
+#include "similarity_metric_type.h"
#include "volume.h"
#include "volume_grad.h"
@@ -53,7 +53,7 @@ public:
char bsp_implementation;
BsplineThreading bsp_threading;
- Registration_metric_type bsp_metric;
+ Similarity_metric_type bsp_metric;
public:
Check_grad_opts () {
@@ -74,7 +74,7 @@ public:
debug_dir = "";
bsp_implementation = '\0';
bsp_threading = BTHR_CPU;
- bsp_metric = REGISTRATION_METRIC_MSE;
+ bsp_metric = SIMILARITY_METRIC_MSE;
}
};
@@ -93,19 +93,22 @@ check_gradient (
Bspline_optimize bod;
Bspline_xform *bxf;
Bspline_parms *parms = new Bspline_parms;
+ Bspline_state *bst = bod.get_bspline_state ();
/* Fixate images into bspline parms */
- parms->fixed = fixed;
- parms->moving = moving;
- parms->moving_grad = moving_grad;
+ Metric_state::Pointer sim = Metric_state::New();
+ bst->similarity_data.push_back (sim);
parms->implementation = options->bsp_implementation;
- parms->metric_type[0] = options->bsp_metric;
+ sim->fixed_ss.reset (fixed);
+ sim->moving_ss.reset (moving);
+ sim->moving_grad.reset (moving_grad);
+ sim->metric_type = options->bsp_metric;
/* Maybe we got a roi too */
Plm_image::Pointer pli_fixed_roi;
if (options->fixed_roi_fn != "") {
pli_fixed_roi = Plm_image::New (options->fixed_roi_fn);
- parms->fixed_roi = pli_fixed_roi->get_volume_uchar().get();
+ sim->fixed_roi = pli_fixed_roi->get_volume_uchar();
}
/* Set extra debug stuff, if desired */
@@ -140,8 +143,8 @@ check_gradient (
}
}
}
- bod.initialize (bxf, parms);
- Bspline_state *bst = bod.get_bspline_state ();
+ bod.set_bspline_xform (bxf);
+ bod.set_bspline_parms (parms);
/* Create scratch variables */
x = (float*) malloc (sizeof(float) * bxf->num_coeff);
@@ -153,9 +156,7 @@ check_gradient (
x[i] = bxf->coeff[i];
}
- if (parms->metric_type[0] == REGISTRATION_METRIC_MI_MATTES) {
- bst->mi_hist->initialize (parms->fixed, parms->moving);
- }
+ bst->initialize_mi_histograms ();
/* Get score and gradient */
bspline_score (&bod);
@@ -167,7 +168,7 @@ check_gradient (
for (i = 0; i < bxf->num_coeff; i++) {
grad[i] = bst->ssd.total_grad[i];
}
- score = bst->ssd.score;
+ score = bst->ssd.total_score;
/* If a search dir was specified, use that instead of the gradient */
if (options->input_search_dir_fn != "") {
@@ -213,7 +214,7 @@ check_gradient (
}
/* Compute difference between grad and grad_fd */
- fprintf (fp, "%4d,%12.12f\n", i, bst->ssd.score);
+ fprintf (fp, "%4d,%12.12f\n", i, bst->ssd.total_score);
// JAS 04.19.2010
// This loop could take a while to exit. This will
@@ -246,7 +247,7 @@ check_gradient (
}
/* Stash score difference in grad_fd */
- grad_fd[i] = (bst->ssd.score - score) / options->step_size;
+ grad_fd[i] = (bst->ssd.total_score - score) / options->step_size;
/* Compute difference between grad and grad_fd */
fprintf (fp, "%12.12f,%12.12f\n", grad[i], grad_fd[i]);
@@ -360,9 +361,9 @@ parse_fn (
}
val = parser->get_string("metric").c_str();
if (val == "mse") {
- parms->bsp_metric = REGISTRATION_METRIC_MSE;
+ parms->bsp_metric = SIMILARITY_METRIC_MSE;
} else if (val == "mi") {
- parms->bsp_metric = REGISTRATION_METRIC_MI_MATTES;
+ parms->bsp_metric = SIMILARITY_METRIC_MI_MATTES;
} else {
throw (dlib::error ("Error parsing --metric, unknown option."));
}
diff --git a/src/plastimatch/standalone/dlib_train.cxx b/src/plastimatch/standalone/dlib_train.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/standalone/drr_main.cxx b/src/plastimatch/standalone/drr_main.cxx
old mode 100644
new mode 100755
index 35d44e5..699ee78
--- a/src/plastimatch/standalone/drr_main.cxx
+++ b/src/plastimatch/standalone/drr_main.cxx
@@ -119,8 +119,8 @@ create_matrix_and_drr (
options->image_center[1] };
/* Set image resolution */
- int ires[2] = { options->image_resolution[0],
- options->image_resolution[1] };
+ plm_long ires[2] = { options->image_resolution[0],
+ options->image_resolution[1] };
/* Set physical size of imager in mm */
float isize[2];
@@ -133,7 +133,7 @@ create_matrix_and_drr (
/* Create projection matrix */
sprintf (mat_fn, "%s%04d.txt", options->output_prefix, a);
- pmat->set (cam, tgt, vup, sid, ic, ps, ires);
+ pmat->set (cam, tgt, vup, sid, ic, ps);
if (options->output_format == OUTPUT_FORMAT_PFM) {
sprintf (img_fn, "%s%04d.pfm", options->output_prefix, a);
diff --git a/src/plastimatch/standalone/gamma_gui.cpp b/src/plastimatch/standalone/gamma_gui.cpp
index ee54236..6533d5b 100644
--- a/src/plastimatch/standalone/gamma_gui.cpp
+++ b/src/plastimatch/standalone/gamma_gui.cpp
@@ -3354,3 +3354,320 @@ QString gamma_gui::ConvertMGHProtonDoseToMha(QString& strPathBinary, VEC3D& fDim
return strResult;
}
+
+void gamma_gui::SLTM_ConvertIBAOPG_Files()
+{
+ QStringList files = QFileDialog::getOpenFileNames(this, "Select one or more files to open",
+ m_strPathInputDir, "IBA OPG files (*.opg)");
+
+ int cnt = files.size();
+ if (cnt <= 0)
+ return;
+
+ QString strPathOPG;
+ QString strPathMHA;
+ int filePathLen;
+ for (int i = 0; i < cnt; i++)
+ {
+ strPathOPG = files.at(i);
+ filePathLen = strPathOPG.length();
+ //replace extention
+ strPathMHA = strPathOPG.left(filePathLen - 4);
+ strPathMHA = strPathMHA + ".mha";
+ ConvertOPG2FloatMHA(strPathOPG, strPathMHA);
+ }
+}
+
+
+//From IBA generic Txt (OPG) to float mha
+bool gamma_gui::ConvertOPG2FloatMHA(QString& strFilePathOPG, QString& strFilePathMHA)
+{
+ //FloatImage2DType::Pointer spFloatDose;
+
+
+ //Data Type: Abs. Dose
+ //Data Factor : 1.814
+ //Data Unit : Should be mGy
+ // Length unit: should be cm
+ //No.of Columns : 32
+ // No.of Rows : 32
+ //Number of Bodies: 1
+ //Operators Note : Corr. : Unif.Calib., Bkgnd, Calib Output, Temp., Press.,
+
+ bool bAbsDose = false;
+ double fDataFactor = 0.0;
+ QString strDataUnit;
+ QString strLengthUnit;
+ int iColumns = 0;
+ int iRows = 0;
+ int iBody = 0;
+ QString strNote;
+
+ double fPlanePos = 0.0;
+
+ ifstream fin;
+ fin.open(strFilePathOPG.toLocal8Bit().constData());
+
+ if (fin.fail())
+ {
+ cout << "Error occurred in file reading!" << endl;
+ return false;
+ }
+ char str[MAX_LINE_LENGTH];
+
+ vector<double> vXVal;
+ vector<double> vYVal;
+ float* pFloatImg = NULL;
+ int imgSize = 0;
+
+ while (!fin.eof())
+ {
+ memset(str, 0, MAX_LINE_LENGTH);
+ fin.getline(str, MAX_LINE_LENGTH);
+ QString tmpStr = QString(str);
+ QString trimmed;
+ QStringList strListLine;
+ QString strHeader;
+ QString strData;
+
+ if (tmpStr.contains("<asciiheader>")) //go into subloop
+ {
+ while (!fin.eof())
+ {
+ strHeader = "";
+ strData = "";
+
+ memset(str, 0, MAX_LINE_LENGTH);
+ fin.getline(str, MAX_LINE_LENGTH);
+ tmpStr = QString(str);
+
+ strListLine = tmpStr.split(" ");// at least two consec. spaces
+
+ if (strListLine.count() >= 2)
+ {
+ strHeader = strListLine.at(0);
+ strData = tmpStr.right(tmpStr.length() - strHeader.length());
+ strData = strData.trimmed();
+ }
+
+ //trimmed = tmpStr.trimmed(); //if any blank line found
+ //if (trimmed.length() < 1)
+ // break;
+
+ if (strHeader.contains("Data Type:") && strData.length() > 0) //go into subloop
+ {
+ if (strData.contains("Abs. Dose"))
+ bAbsDose = true;
+ else
+ bAbsDose = false;
+ }
+ else if (strHeader.contains("Data Factor:") && strData.length() > 0) //go into subloop
+ {
+ fDataFactor = strData.toDouble();
+ }
+ else if (strHeader.contains("Data Unit:") && strData.length() > 0) //go into subloop
+ {
+ strDataUnit = strData;
+ if (!strDataUnit.contains("mGy"))
+ {
+ cout << "Error! unit should be mGy. Current = " << strDataUnit.toLocal8Bit().constData() << endl;
+ }
+ }
+ else if (strHeader.contains("Length Unit:") && strData.length() > 0) //go into subloop
+ {
+ strLengthUnit = strData;
+
+ if (!strLengthUnit.contains("cm"))
+ {
+ cout << "Error! unit should be cm. Current = " << strLengthUnit.toLocal8Bit().constData() << endl;
+ }
+ }
+ else if (strHeader.contains("No. of Columns:") && strData.length() > 0) //go into subloop
+ {
+ iColumns = strData.toInt();
+ }
+ else if (strHeader.contains("No. of Rows:") && strData.length() > 0) //go into subloop
+ {
+ iRows = strData.toInt();
+ }
+ else if (strHeader.contains("Number of Bodies:") && strData.length() > 0) //go into subloop
+ {
+ iBody = strData.toInt();
+ }
+ else if (strHeader.contains("Operators Note:") && strData.length() > 0) //go into subloop
+ {
+ strNote = strData;
+ }
+ //else if (strHeader.contains("</asciiheader>")) //go into subloop
+ else if (tmpStr.contains("</asciiheader>")) //go into subloop
+ {
+ break;
+ }
+ }// end of while
+ }//end of if tmpStr.contains("<asciiheader>"
+
+ if (tmpStr.contains("<asciibody>")) //go into subloop
+ {
+ imgSize = iColumns*iRows;
+
+ if (imgSize > 1)
+ pFloatImg = new float[imgSize];
+
+ while (!fin.eof())
+ {
+ memset(str, 0, MAX_LINE_LENGTH);
+ fin.getline(str, MAX_LINE_LENGTH);
+ tmpStr = QString(str);
+
+ if (tmpStr.contains("X[cm]"))
+ {
+ strListLine = tmpStr.split(" ");
+ int iCntItem = strListLine.count();
+ vXVal.clear();
+
+ QStringList strListValidX;
+ QString strTestX;
+
+ for (int i = 1; i<iCntItem; i++)
+ {
+ strTestX = strListLine.at(i);
+ cout << strTestX.toLocal8Bit().constData() << endl;
+
+ strTestX = strTestX.trimmed();
+ if (strTestX.length() > 0)
+ {
+ strListValidX.push_back(strTestX);
+ }
+ }
+
+ int iValidXCnt = strListValidX.count();
+
+ cout << "Valid only" << endl;
+ for (int i = 0; i < iValidXCnt; i++)
+ {
+ vXVal.push_back(strListValidX.at(i).toDouble());
+ cout << strListValidX.at(i).toDouble() << endl;
+ }
+
+ /*if ((int)(vXVal.size()) != iColumns)
+ {
+ cout << "Error! X[cm] data count = " << vXVal.size() << ", X header info = " << iColumns << endl;
+ return false;
+ } */
+ }
+ else if (tmpStr.contains("Y[cm]"))
+ {
+ vYVal.clear();
+ int iYLineCnt = 0;
+
+ while (!fin.eof())
+ {
+ memset(str, 0, MAX_LINE_LENGTH);
+ fin.getline(str, MAX_LINE_LENGTH);
+ tmpStr = QString(str);
+
+ if (tmpStr.contains("</asciibody>"))
+ break;
+
+ strListLine = tmpStr.split("\t");// at least two consec. spaces
+
+ int iDataCnt = strListLine.count();
+
+ if (iDataCnt > 1)
+ {
+ vYVal.push_back(strListLine.at(0).toDouble());
+ }
+
+ QStringList strListValid;
+ QString strTest;
+ for (int i = 1; i<iDataCnt; i++)
+ {
+ strTest = strListLine.at(i);
+ strTest = strTest.trimmed();
+ if (strTest.length() > 0)
+ {
+ strListValid.push_back(strTest);
+ }
+ }
+
+ if (strListValid.count() != iColumns)
+ {
+ cout << "Error! X data count = " << strListValid.count() << " vs " << iColumns << endl;
+ return false;
+ }
+
+ int curIdx = 0;
+ for (int i = 0; i < iColumns; i++)
+ {
+ curIdx = iColumns*iYLineCnt + i;
+ if (curIdx < imgSize)
+ pFloatImg[curIdx] = (strListValid.at(i).toDouble())*fDataFactor / 1000.0; //Unit: Gy
+ }
+ iYLineCnt++;
+ }//end of sub while
+
+ if (iYLineCnt != iRows)
+ {
+ cout << "Error! Y data count = " << iYLineCnt << " vs " << iRows << endl;
+ return false;
+ }
+ }// end of Y cm
+ }//end of asciibody while
+ }//if asciibody
+ } // main while
+ fin.close();
+
+ //img array to itk image
+
+ if (vXVal.size() < 2 || vYVal.size() < 2)
+ return false;
+
+ FloatImage2DType::PointType ptOriginItk;
+ FloatImage2DType::SizeType imgSizeItk;
+ FloatImage2DType::SpacingType imgSpacingItk;
+
+ ptOriginItk[0] = vXVal.at(0)*10.0;
+ ptOriginItk[1] = vYVal.at(0)*10.0;
+
+ imgSizeItk[0] = iColumns;
+ imgSizeItk[1] = iRows;
+
+ imgSpacingItk[0] = fabs(vXVal.at(1) - vXVal.at(0))*10.0; // cm to mm
+ imgSpacingItk[1] = fabs(vYVal.at(1) - vYVal.at(0))*10.0;
+
+ FloatImage2DType::IndexType idxStart;
+ idxStart[0] = 0;
+ idxStart[1] = 0;
+
+ FloatImage2DType::RegionType region;
+ region.SetSize(imgSizeItk);
+ region.SetIndex(idxStart);
+
+ FloatImage2DType::Pointer spFloatDoseImg = FloatImage2DType::New();
+ spFloatDoseImg->SetRegions(region);
+ spFloatDoseImg->SetSpacing(imgSpacingItk);
+ spFloatDoseImg->SetOrigin(ptOriginItk);
+
+ spFloatDoseImg->Allocate();
+ spFloatDoseImg->FillBuffer(0.0);
+
+ itk::ImageRegionIterator<FloatImage2DType> it(spFloatDoseImg, spFloatDoseImg->GetLargestPossibleRegion());
+
+ int idx = 0;
+ for (it.GoToBegin(); !it.IsAtEnd(); ++it)
+ {
+ if (idx < imgSize)
+ {
+ float curVal = pFloatImg[idx];
+ it.Set(curVal);
+ }
+ idx++;
+ }
+
+ if (pFloatImg != NULL)
+ delete[] pFloatImg;
+
+ QUTIL::SaveFloatImage2D(strFilePathMHA.toLocal8Bit().constData(), spFloatDoseImg);
+
+ return true;
+}
diff --git a/src/plastimatch/standalone/gamma_gui.h b/src/plastimatch/standalone/gamma_gui.h
index af1753a..19ebf76 100644
--- a/src/plastimatch/standalone/gamma_gui.h
+++ b/src/plastimatch/standalone/gamma_gui.h
@@ -58,6 +58,8 @@ public:
QString ConvertMGHProtonDoseToMha(QString& strPathBinnary, VEC3D& fDim, VEC3D& fOrigin, VEC3D& fSpacing);
+ bool ConvertOPG2FloatMHA(QString& strFilePathOPG, QString& strFilePathMHA);
+
public slots:
void SLT_Load_RD_Ref();
void SLT_Load_RD_Comp();
@@ -132,6 +134,7 @@ public:
void SLTM_ExportBatchReport();
void SLTM_LoadProtonDoseSetFile();
+ void SLTM_ConvertIBAOPG_Files();
public:
QStringList m_strlistPath_RD_Original_Ref; //RD files, before the conversion
diff --git a/src/plastimatch/standalone/gamma_gui.ui b/src/plastimatch/standalone/gamma_gui.ui
index 99dcf39..baa3e91 100644
--- a/src/plastimatch/standalone/gamma_gui.ui
+++ b/src/plastimatch/standalone/gamma_gui.ui
@@ -1048,6 +1048,7 @@
<string>Tool</string>
</property>
<addaction name="actionRename_RD_files"/>
+ <addaction name="actionConvert_IBA_OPG_files"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuView"/>
@@ -1095,6 +1096,11 @@
<string>Export Comp Profile as RFA300</string>
</property>
</action>
+ <action name="actionConvert_IBA_OPG_files">
+ <property name="text">
+ <string>Convert IBA OPG files</string>
+ </property>
+ </action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
@@ -1608,6 +1614,22 @@
</hint>
</hints>
</connection>
+ <connection>
+ <sender>actionConvert_IBA_OPG_files</sender>
+ <signal>triggered()</signal>
+ <receiver>gamma_guiClass</receiver>
+ <slot>SLTM_ConvertIBAOPG_Files()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>-1</x>
+ <y>-1</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>604</x>
+ <y>430</y>
+ </hint>
+ </hints>
+ </connection>
</connections>
<slots>
<slot>SLT_Load_RD_Ref()</slot>
@@ -1630,5 +1652,6 @@
<slot>SLTM_ExportBatchReport()</slot>
<slot>SLTM_LoadProtonDoseSetFile()</slot>
<slot>SLTM_ExportCompProfileRFA300_ASC()</slot>
+ <slot>SLTM_ConvertIBAOPG_Files()</slot>
</slots>
</ui>
diff --git a/src/plastimatch/standalone/hnd_to_pfm.cxx b/src/plastimatch/standalone/hnd_to_pfm.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/standalone/opencl_probe.cxx b/src/plastimatch/standalone/opencl_probe.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/standalone/opencl_probe.h b/src/plastimatch/standalone/opencl_probe.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/standalone/qt_util.cxx b/src/plastimatch/standalone/qt_util.cxx
index 75e44d5..aa2acb4 100644
--- a/src/plastimatch/standalone/qt_util.cxx
+++ b/src/plastimatch/standalone/qt_util.cxx
@@ -17,7 +17,7 @@
#include <QMessageBox>
#include "itk_resample.h" //plm
-bool QUTIL::QPointF_Compare(QPointF& ptData1, QPointF& ptData2)
+bool QUTIL::QPointF_Compare(const QPointF& ptData1, const QPointF& ptData2)
{
//return (ptData1.x() > ptData2.x()); //ASCENDING
return (ptData1.x() < ptData2.x()); //DESCENDING
diff --git a/src/plastimatch/standalone/qt_util.h b/src/plastimatch/standalone/qt_util.h
index c2d97f2..7f253c5 100644
--- a/src/plastimatch/standalone/qt_util.h
+++ b/src/plastimatch/standalone/qt_util.h
@@ -70,7 +70,7 @@ namespace QUTIL{
// typedef itk::ImageFileReader<FloatImageType> ReaderTypeYK;
- bool QPointF_Compare(QPointF& ptData1, QPointF& ptData2);
+ bool QPointF_Compare(const QPointF& ptData1, const QPointF& ptData2);
void ResampleFloatImg(FloatImageType::Pointer& spFloatInput, FloatImageType::Pointer& spFloatOutput, VEC3D& newSpacing);
diff --git a/src/plastimatch/standalone/shuffle_mha_main.cxx b/src/plastimatch/standalone/shuffle_mha_main.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/standalone/sobp_main.cxx b/src/plastimatch/standalone/sobp_main.cxx
index 3782b44..4ae518e 100644
--- a/src/plastimatch/standalone/sobp_main.cxx
+++ b/src/plastimatch/standalone/sobp_main.cxx
@@ -80,17 +80,17 @@ int main (int argc, char* argv[])
{
sscanf (argv[3], "%d", &Emin);
sscanf (argv[4], "%d", &Emax);
- mebs.set_energies(Emin, Emax);
+ mebs.set_energies(Emin, Emax);
}
- std::vector<float> weight;
- std::vector<float> energy;
+ std::vector<float> weight;
+ std::vector<float> energy;
mebs.optimizer(&weight, &energy);
- for (int i = 0; i < energy.size(); i++)
- {
- mebs.add_peak(energy[i], mebs.get_spread(), weight[i]);
- }
- mebs.generate();
- mebs.printparameters();
+ for (size_t i = 0; i < energy.size(); i++)
+ {
+ mebs.add_peak(energy[i], mebs.get_spread(), weight[i]);
+ }
+ mebs.generate();
+ mebs.printparameters();
return 0;
}
diff --git a/src/plastimatch/standalone/vf_invert_main.cxx b/src/plastimatch/standalone/vf_invert_main.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/sys/CMakeLists.txt b/src/plastimatch/sys/CMakeLists.txt
index c0acc19..dbb1192 100644
--- a/src/plastimatch/sys/CMakeLists.txt
+++ b/src/plastimatch/sys/CMakeLists.txt
@@ -53,8 +53,9 @@ endforeach ()
##-----------------------------------------------------------------------------
## LIBRARY DEPENDENCIES
##-----------------------------------------------------------------------------
-set (PLMSYS_LIBRARY_DEPENDENCIES
- )
+set (PLMSYS_LIBRARY_DEPENDENCIES
+ ${DLIB_LIBRARIES}
+ )
if (LIBDL_FOUND)
set (PLMSYS_LIBRARY_DEPENDENCIES
${PLMSYS_LIBRARY_DEPENDENCIES}
diff --git a/src/plastimatch/sys/compiler_warnings.h b/src/plastimatch/sys/compiler_warnings.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/sys/dlib_threads.cxx b/src/plastimatch/sys/dlib_threads.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/sys/dlib_threads.h b/src/plastimatch/sys/dlib_threads.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/sys/logfile.cxx b/src/plastimatch/sys/logfile.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/sys/plm_endian.cxx b/src/plastimatch/sys/plm_endian.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/sys/plm_macros.h b/src/plastimatch/sys/plm_macros.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/sys/plm_math.h b/src/plastimatch/sys/plm_math.h
old mode 100644
new mode 100755
index 3300f6a..318faca
--- a/src/plastimatch/sys/plm_math.h
+++ b/src/plastimatch/sys/plm_math.h
@@ -8,6 +8,7 @@
#include <float.h>
#include <math.h>
#include <string.h>
+#include <limits>
#include "compiler_warnings.h"
#ifndef M_PI
@@ -103,11 +104,16 @@ static inline void vec4_copy (double* v1, const double* v2) {
v1[0] = v2[0]; v1[1] = v2[1]; v1[2] = v2[2]; v1[3] = v2[3];
}
-template<class T> static inline double
+template<class T> static inline T
vec3_dot (const T* v1, const T* v2) {
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
}
+template<class T, class U> static inline float
+vec3_dot (const T* v1, const U* v2) {
+ return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
+}
+
static inline double vec4_dot (const double* v1, const double* v2) {
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2] + v1[3] * v2[3];
}
@@ -125,10 +131,17 @@ static inline void vec3_sub2 (double* v1, const double* v2) {
v1[0] -= v2[0]; v1[1] -= v2[1]; v1[2] -= v2[2];
}
+#if defined (commentout)
template<class T> static inline void
vec3_sub3 (T* v1, const T* v2, const T* v3) {
v1[0] = v2[0] - v3[0]; v1[1] = v2[1] - v3[1]; v1[2] = v2[2] - v3[2];
}
+#endif
+
+template<class T, class U, class V> static inline void
+vec3_sub3 (T* v1, const U* v2, const V* v3) {
+ v1[0] = v2[0] - v3[0]; v1[1] = v2[1] - v3[1]; v1[2] = v2[2] - v3[2];
+}
static inline void vec3_invert (double* v1) {
vec3_scale2 (v1, -1.0);
@@ -200,7 +213,7 @@ static inline void vec_outer (double* v1, const double* v2, const double* v3, co
#define m_idx(m1,c,i,j) m1[i*c+j]
/* v1 = m2 * v3 */
-static inline void mat43_mult_vec3 (double* v1, const double* m2, const double* v3) {
+static inline void mat43_mult_vec4 (double* v1, const double* m2, const double* v3) {
v1[0] = vec4_dot(&m2[0], v3);
v1[1] = vec4_dot(&m2[4], v3);
v1[2] = vec4_dot(&m2[8], v3);
@@ -228,9 +241,18 @@ static inline void mat_mult_mat (
/* 0 when value is NaN or infinity */
static inline int is_number (const double x)
{
+ // nan
if (!(x == x)) return 0;
+ // inf
if (x > DBL_MAX || x < -DBL_MAX) return 0;
+#if defined (commentout)
+ if (std::numeric_limits<double>::has_infinity &&
+ x == std::numeric_limits<double>::infinity())
+ {
+ return 0;
+ }
+#endif
return 1;
}
@@ -250,4 +272,7 @@ within_abs_tolerance (float value, float comp_value, float tolerance)
return (fabsf (value - comp_value) <= tolerance);
}
+#define NLMIN(T) (-std::numeric_limits<T>::max())
+#define NLMAX(T) std::numeric_limits<T>::max()
+
#endif
diff --git a/src/plastimatch/sys/plm_return_code.h b/src/plastimatch/sys/plm_return_code.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/sys/plm_sleep.cxx b/src/plastimatch/sys/plm_sleep.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/sys/plm_sleep.h b/src/plastimatch/sys/plm_sleep.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/sys/plm_timer.cxx b/src/plastimatch/sys/plm_timer.cxx
index d8fbcbb..9b2da1b 100644
--- a/src/plastimatch/sys/plm_timer.cxx
+++ b/src/plastimatch/sys/plm_timer.cxx
@@ -75,6 +75,13 @@ Plm_timer::stop ()
}
void
+Plm_timer::reset ()
+{
+ this->stop ();
+ d_ptr->acc_time = 0.;
+}
+
+void
Plm_timer::resume ()
{
if (!d_ptr->running) {
diff --git a/src/plastimatch/sys/plm_timer.h b/src/plastimatch/sys/plm_timer.h
index d161735..c194d78 100644
--- a/src/plastimatch/sys/plm_timer.h
+++ b/src/plastimatch/sys/plm_timer.h
@@ -15,6 +15,7 @@ public:
void start ();
void stop ();
+ void reset ();
void resume ();
double report ();
private:
diff --git a/src/plastimatch/sys/smart_pointer.h b/src/plastimatch/sys/smart_pointer.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/sys/string_util.cxx b/src/plastimatch/sys/string_util.cxx
old mode 100755
new mode 100644
index 3f7fc67..c827be2
--- a/src/plastimatch/sys/string_util.cxx
+++ b/src/plastimatch/sys/string_util.cxx
@@ -418,23 +418,52 @@ std::vector<std::string> string_split (
return elems;
}
-bool split_tag_val (
+bool
+split_key_val (
const std::string& s,
- std::string& tag,
+ std::string& key,
std::string& val,
char delim)
{
size_t loc = s.find (delim);
if (loc == std::string::npos) {
- tag = "";
+ key = string_trim (s);
val = "";
return false;
}
- tag = string_trim (s.substr (0, loc));
+ key = string_trim (s.substr (0, loc));
val = string_trim (s.substr (loc + 1));
return true;
}
+bool
+split_array_index (
+ const std::string& s,
+ std::string& array,
+ std::string& index)
+{
+ size_t start_loc = s.find ('[');
+ size_t end_loc = s.find (']');
+ if (start_loc == std::string::npos
+ && end_loc == std::string::npos)
+ {
+ array = string_trim (s);
+ index = "";
+ return true;
+ }
+ if (start_loc != std::string::npos
+ && end_loc != std::string::npos
+ && end_loc > start_loc + 1)
+ {
+ array = string_trim (s.substr (0, start_loc));
+ index = string_trim (s.substr (start_loc + 1, end_loc - start_loc - 1));
+ return true;
+ }
+ array = string_trim (s);
+ index = "";
+ return false;
+}
+
/* Explicit instantiations */
template PLMSYS_API std::string PLM_to_string(int value);
template PLMSYS_API std::string PLM_to_string(size_t value);
diff --git a/src/plastimatch/sys/string_util.h b/src/plastimatch/sys/string_util.h
index 18ed22d..e70e43c 100644
--- a/src/plastimatch/sys/string_util.h
+++ b/src/plastimatch/sys/string_util.h
@@ -50,7 +50,9 @@ template <typename T> PLMSYS_API std::string PLM_to_string(T *value, int n);
PLMSYS_API std::vector<std::string>& string_split (const std::string &s, char delim, std::vector<std::string> &elems);
PLMSYS_API std::vector<std::string> string_split (const std::string &s, char delim);
-PLMSYS_API bool split_tag_val (const std::string& s,
- std::string& tag, std::string& val, char delim = '=');
+PLMSYS_API bool split_key_val (const std::string& s,
+ std::string& key, std::string& val, char delim = '=');
+PLMSYS_API bool split_array_index (const std::string& s,
+ std::string& array, std::string& index);
#endif
diff --git a/src/plastimatch/test/api_test.cxx b/src/plastimatch/test/api_test.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/test/cpp_eps_test.cxx b/src/plastimatch/test/cpp_eps_test.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/test/cpp_limits_test.cxx b/src/plastimatch/test/cpp_limits_test.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/test/cpp_overflow_test.cxx b/src/plastimatch/test/cpp_overflow_test.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/test/cpp_sizeof_test.cxx b/src/plastimatch/test/cpp_sizeof_test.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/test/cpp_template_test.cxx b/src/plastimatch/test/cpp_template_test.cxx
old mode 100755
new mode 100644
index b834995..7c47bd4
--- a/src/plastimatch/test/cpp_template_test.cxx
+++ b/src/plastimatch/test/cpp_template_test.cxx
@@ -1,5 +1,6 @@
#include <stdio.h>
-
+#include <map>
+#include <string>
/* Simple test */
typedef void (*B) (int);
@@ -51,6 +52,17 @@ template < template<class J> class I > void l (J x) {
}
#endif
+/* This is an example inheriting from std::map */
+/* Cf. http://stackoverflow.com/questions/10477839/c-inheriting-from-stdmap
+ (The answer from Emilio Garavaglia, not the others) */
+template <class L> class M : public std::map<std::string,L>
+{
+public:
+ typename std::map<std::string,L>::iterator get_default (std::string s) {
+ return this->begin();
+ }
+};
+
int main
(
int argc,
@@ -63,4 +75,7 @@ int main
d< G<int> >(x);
h< int, G >(x);
k< G, int >(x);
+
+ M<int> m;
+ M<int>::iterator mit = m.get_default("FOO");
}
diff --git a/src/plastimatch/test/cuda/cuda_test.cu b/src/plastimatch/test/cuda/cuda_test.cu
index 8eff5fc..7d1b73f 100644
--- a/src/plastimatch/test/cuda/cuda_test.cu
+++ b/src/plastimatch/test/cuda/cuda_test.cu
@@ -4,6 +4,18 @@
// Simple utility function to check for CUDA runtime errors
void checkCUDAError (const char *msg);
+class A {
+public:
+ int a;
+ float b;
+public:
+ int get_a ();
+ void set_a (int val);
+};
+
+int A::get_a () { return this->a; }
+void A::set_a (int val) { this->a = val; }
+
// Part 3 of 5: implement the kernel
__global__ void
myFirstKernel(int *d_a)
@@ -136,6 +148,11 @@ cuda_mem_test (int argc, char** argv)
int
main (int argc, char** argv)
{
- //cuda_test_1 (argc, argv);
+ // do some c++ here
+ A a1;
+ a1.set_a (32);
+ printf ("C++ test: %d\n", a1.get_a());
+
+ // cuda_test_1 (argc, argv);
return cuda_mem_test (argc, argv);
}
diff --git a/src/plastimatch/test/dcmtk_test.cxx b/src/plastimatch/test/dcmtk_test.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/test/dlib_test.cxx b/src/plastimatch/test/dlib_test.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/test/dlib_thread_test.cxx b/src/plastimatch/test/dlib_thread_test.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/test/gabor_test.cxx b/src/plastimatch/test/gabor_test.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/test/itk_test.cxx b/src/plastimatch/test/itk_test.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/test/itk_test_directions.cxx b/src/plastimatch/test/itk_test_directions.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/test/itk_thread_test.cxx b/src/plastimatch/test/itk_thread_test.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/test/libyaml_test.cxx b/src/plastimatch/test/libyaml_test.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/test/plm_restart_test.cxx b/src/plastimatch/test/plm_restart_test.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/test/rapidjson_test.cxx b/src/plastimatch/test/rapidjson_test.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/test/rtplan_test.cxx b/src/plastimatch/test/rtplan_test.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/test/smartp_test_i.cxx b/src/plastimatch/test/smartp_test_i.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/test/smartp_test_ii.cxx b/src/plastimatch/test/smartp_test_ii.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/test/yamlcpp_test.cxx b/src/plastimatch/test/yamlcpp_test.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/util/CMakeLists.txt b/src/plastimatch/util/CMakeLists.txt
index 818b33d..c447de0 100644
--- a/src/plastimatch/util/CMakeLists.txt
+++ b/src/plastimatch/util/CMakeLists.txt
@@ -26,7 +26,7 @@ set (PLMUTIL_LIBRARY_SRC
hausdorff_distance.cxx hausdorff_distance.h
image_boundary.cxx image_boundary.h
image_center.cxx image_center.h
- itk_adjust.cxx
+ itk_adjust.cxx itk_adjust.h
itk_distance_map.cxx
itk_crop.cxx
itk_gabor.cxx
@@ -38,13 +38,14 @@ set (PLMUTIL_LIBRARY_SRC
proj_image_filter.cxx
plm_series.cxx
plm_study.cxx
- rt_study_warp.cxx rt_study_warp.h
+ rt_study_warp.cxx rt_study_warp.h
sift.cxx
simplify_points.cxx
ss_img_stats.cxx
synthetic_mha.cxx
synthetic_vf.cxx
threshbox.cxx
+ volume_adjust.cxx volume_adjust.h
vf_invert.cxx
)
if (FFTW_FOUND)
diff --git a/src/plastimatch/util/dicom_sro_save.cxx b/src/plastimatch/util/dicom_sro_save.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/util/dicom_sro_save.h b/src/plastimatch/util/dicom_sro_save.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/util/distance_map.cxx b/src/plastimatch/util/distance_map.cxx
old mode 100755
new mode 100644
index c458860..769830a
--- a/src/plastimatch/util/distance_map.cxx
+++ b/src/plastimatch/util/distance_map.cxx
@@ -23,12 +23,15 @@ public:
use_squared_distance = false;
maximum_distance = FLT_MAX;
algorithm = Distance_map::DANIELSSON;
+ vbb = ADAPTIVE_PADDING;
}
public:
Distance_map::Algorithm algorithm;
bool inside_is_positive;
bool use_squared_distance;
float maximum_distance;
+ Volume_boundary_behavior vbb;
+
UCharImageType::Pointer input;
FloatImageType::Pointer output;
public:
@@ -221,7 +224,12 @@ Distance_map_private::run_native_danielsson ()
{
/* Compute boundary of image
vb = volume of boundary, imgb = img of boundary */
- Plm_image pib (do_image_boundary (this->input));
+ Image_boundary ib;
+ ib.set_volume_boundary_behavior (vbb);
+ ib.set_input_image (this->input);
+ ib.run ();
+ UCharImageType::Pointer itk_ib = ib.get_output_image ();
+ Plm_image pib (itk_ib);
Volume::Pointer vb = pib.get_volume_uchar();
unsigned char *imgb = (unsigned char*) vb->img;
@@ -251,9 +259,6 @@ Distance_map_private::run_native_danielsson ()
vb->spacing[2] * vb->spacing[2]
};
- /* GCS FIX -- This is only implemented as distance to set,
- not distance to boundary. */
-
/* GCS FIX -- I'm not entirely sure if it is required to scan
both forward and backward for j direction. Need to test. */
@@ -403,6 +408,13 @@ Distance_map::set_input_image (UCharImageType::Pointer image)
d_ptr->input = image;
}
+void
+Distance_map::set_input_image (const Plm_image::Pointer& image)
+{
+ Plm_image::Pointer pi_clone = image->clone ();
+ d_ptr->input = pi_clone->itk_uchar ();
+}
+
void
Distance_map::set_use_squared_distance (bool use_squared_distance)
{
@@ -415,6 +427,12 @@ Distance_map::set_maximum_distance (float maximum_distance)
d_ptr->maximum_distance = maximum_distance;
}
+void
+Distance_map::set_volume_boundary_behavior (Volume_boundary_behavior vbb)
+{
+ d_ptr->vbb = vbb;
+}
+
void
Distance_map::set_inside_is_positive (bool inside_is_positive)
{
diff --git a/src/plastimatch/util/distance_map.h b/src/plastimatch/util/distance_map.h
old mode 100755
new mode 100644
index 2b6c884..228e09a
--- a/src/plastimatch/util/distance_map.h
+++ b/src/plastimatch/util/distance_map.h
@@ -6,6 +6,8 @@
#include "plmutil_config.h"
#include "itk_image_type.h"
+#include "plm_image.h"
+#include "volume_boundary_behavior.h"
class Distance_map_private;
class Plm_image;
@@ -34,6 +36,8 @@ public:
void set_input_image (const char* image_fn);
/*! \brief Set the input image as an ITK image. */
void set_input_image (const UCharImageType::Pointer image);
+ /*! \brief Set the input image as a Plm_image. */
+ void set_input_image (const Plm_image::Pointer& image);
/*! \brief Choose whether the output image is distance or squared
distance. The default is not squared distance. */
void set_use_squared_distance (bool use_squared_distance);
@@ -44,6 +48,9 @@ public:
void set_algorithm (const std::string& algorithm);
/*! \brief Set maximum distance */
void set_maximum_distance (float max_distance);
+ /*! \brief Set the volume boundary behavior, either
+ ZERO_PADDING, EDGE_PADDING, or ADAPTIVE_PADDING */
+ void set_volume_boundary_behavior (Volume_boundary_behavior vbb);
///@}
/*! \name Execution */
diff --git a/src/plastimatch/util/gabor.cxx b/src/plastimatch/util/gabor.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/util/gabor.h b/src/plastimatch/util/gabor.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/util/hausdorff_distance.cxx b/src/plastimatch/util/hausdorff_distance.cxx
index d399d13..a3b1f24 100644
--- a/src/plastimatch/util/hausdorff_distance.cxx
+++ b/src/plastimatch/util/hausdorff_distance.cxx
@@ -13,6 +13,7 @@
#include "hausdorff_distance.h"
#include "image_boundary.h"
#include "itk_image_load.h"
+#include "itk_image_save.h"
#include "itk_resample.h"
#include "logfile.h"
#include "plm_image.h"
@@ -25,6 +26,7 @@ public:
pct_hausdorff_distance_fraction = 0.95;
dmap_alg = "";
maximum_distance = FLT_MAX;
+ vbb = ADAPTIVE_PADDING;
this->clear_statistics ();
}
public:
@@ -51,6 +53,7 @@ public:
std::string dmap_alg;
float maximum_distance;
+ Volume_boundary_behavior vbb;
UCharImageType::Pointer ref_image;
UCharImageType::Pointer cmp_image;
@@ -111,6 +114,12 @@ Hausdorff_distance::set_maximum_distance (float maximum_distance)
d_ptr->maximum_distance = maximum_distance;
}
+void
+Hausdorff_distance::set_volume_boundary_behavior (Volume_boundary_behavior vbb)
+{
+ d_ptr->vbb = vbb;
+}
+
void
Hausdorff_distance::run_internal (
UCharImageType::Pointer image1,
@@ -124,6 +133,7 @@ Hausdorff_distance::run_internal (
dmap_filter.set_inside_is_positive (false);
dmap_filter.set_use_squared_distance (false);
dmap_filter.set_maximum_distance (d_ptr->maximum_distance);
+ dmap_filter.set_volume_boundary_behavior (d_ptr->vbb);
dmap_filter.run ();
FloatImageType::Pointer dmap = dmap_filter.get_output_image ();
@@ -137,10 +147,11 @@ Hausdorff_distance::run_internal (
/* Find boundary pixels */
Image_boundary ib;
+ ib.set_volume_boundary_behavior (d_ptr->vbb);
ib.set_input_image (image1);
ib.run ();
UCharImageType::Pointer itk_ib = ib.get_output_image ();
-
+
/* Convert to plm_image */
Plm_image pli_ib (itk_ib);
Volume::Pointer vol_ib = pli_ib.get_volume_uchar ();
diff --git a/src/plastimatch/util/hausdorff_distance.h b/src/plastimatch/util/hausdorff_distance.h
index 7105704..d33aa19 100644
--- a/src/plastimatch/util/hausdorff_distance.h
+++ b/src/plastimatch/util/hausdorff_distance.h
@@ -6,6 +6,7 @@
#include "plmutil_config.h"
#include "itk_image.h"
+#include "volume_boundary_behavior.h"
class Plm_image;
class Hausdorff_distance_private;
@@ -120,6 +121,9 @@ public:
/*! \brief Choose the maximum distance that is returned when
computing the distance map */
void set_maximum_distance (float maximum_distance);
+ /*! \brief Set the volume boundary behavior, either
+ ZERO_PADDING, EDGE_PADDING, or ADAPTIVE_PADDING */
+ void set_volume_boundary_behavior (Volume_boundary_behavior vbb);
///@}
/*! \name Execution */
diff --git a/src/plastimatch/util/image_boundary.cxx b/src/plastimatch/util/image_boundary.cxx
old mode 100755
new mode 100644
index 038b623..b85cd78
--- a/src/plastimatch/util/image_boundary.cxx
+++ b/src/plastimatch/util/image_boundary.cxx
@@ -13,17 +13,17 @@
#include "plm_image.h"
#include "plm_image_header.h"
#include "volume.h"
+#include "volume_boundary_behavior.h"
class Image_boundary_private {
public:
Image_boundary_private () {
- vbb = Image_boundary::EDGE_PADDING;
-// vbb = Image_boundary::ZERO_PADDING;
+ vbb = ADAPTIVE_PADDING;
}
public:
UCharImageType::Pointer input_image;
UCharImageType::Pointer output_image;
- Image_boundary::Volume_boundary_behavior vbb;
+ Volume_boundary_behavior vbb;
public:
void run ();
protected:
@@ -77,6 +77,28 @@ protected:
return 0;
}
+ return 0;
+ }
+
+ unsigned char classify_ap (
+ const Volume::Pointer& vol_in,
+ const unsigned char *img_in,
+ plm_long i, plm_long j, plm_long k, plm_long v)
+ {
+ /* If not inside volume, then not on boundary */
+ if (!img_in[v]) {
+ return 0;
+ }
+
+ /* Check for non-zero edge pixels; these are boundary if
+ dimension > 1 */
+ if (vol_in->dim[2] > 1 && (k == 0 || k == vol_in->dim[2]-1)
+ || vol_in->dim[1] > 1 && (j == 0 || j == vol_in->dim[1]-1)
+ || vol_in->dim[0] > 1 && (i == 0 || i == vol_in->dim[0]-1))
+ {
+ return 1;
+ }
+
/* Look for neighboring zero voxel in six-neighborhood,
ignoring voxels beyond boundary */
if (i != 0
@@ -130,10 +152,17 @@ Image_boundary_private::run ()
for (plm_long k = 0, v = 0; k < vol_in->dim[2]; k++) {
for (plm_long j = 0; j < vol_in->dim[1]; j++) {
for (plm_long i = 0; i < vol_in->dim[0]; i++, v++) {
- if (this->vbb == Image_boundary::ZERO_PADDING) {
+ switch (this->vbb) {
+ case ZERO_PADDING:
img_out[v] = classify_zp (vol_in, img_in, i, j, k, v);
- } else {
+ break;
+ case EDGE_PADDING:
img_out[v] = classify_ep (vol_in, img_in, i, j, k, v);
+ break;
+ case ADAPTIVE_PADDING:
+ default:
+ img_out[v] = classify_ap (vol_in, img_in, i, j, k, v);
+ break;
}
}
}
@@ -166,6 +195,12 @@ Image_boundary::set_input_image (
d_ptr->input_image = image;
}
+void
+Image_boundary::set_volume_boundary_behavior (Volume_boundary_behavior vbb)
+{
+ d_ptr->vbb = vbb;
+}
+
void
Image_boundary::run ()
{
diff --git a/src/plastimatch/util/image_boundary.h b/src/plastimatch/util/image_boundary.h
old mode 100755
new mode 100644
index f4551ce..b5af804
--- a/src/plastimatch/util/image_boundary.h
+++ b/src/plastimatch/util/image_boundary.h
@@ -6,6 +6,7 @@
#include "plmutil_config.h"
#include "itk_image.h"
+#include "volume_boundary_behavior.h"
class Plm_image;
class Image_boundary_private;
@@ -25,18 +26,6 @@ public:
Image_boundary_private *d_ptr;
public:
- /*! \brief This enum is used to control the algorithm behavior
- for voxels at the edge of the volume. If ZERO_PADDING is
- specified, all non-zero voxels at the edge of the volume
- will be treated as boundary voxels. If EDGE_PADDING is
- specified, non-zero voxels at the edge of the volume are
- only treated as boundary voxels if they neighbor
- a zero voxel. */
- enum Volume_boundary_behavior {
- ZERO_PADDING,
- EDGE_PADDING
- };
-public:
/*! \name Inputs */
///@{
@@ -46,7 +35,7 @@ public:
/*! \brief Set the input image as an ITK image. */
void set_input_image (const UCharImageType::Pointer image);
/*! \brief Set the volume boundary behavior, either
- ZERO_PADDING or EDGE_PADDING */
+ ZERO_PADDING, EDGE_PADDING, or ADAPTIVE_PADDING */
void set_volume_boundary_behavior (Volume_boundary_behavior vbb);
///@}
diff --git a/src/plastimatch/util/image_center.cxx b/src/plastimatch/util/image_center.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/util/image_center.h b/src/plastimatch/util/image_center.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/util/itk_adjust.cxx b/src/plastimatch/util/itk_adjust.cxx
old mode 100755
new mode 100644
index df92b01..a564cd4
--- a/src/plastimatch/util/itk_adjust.cxx
+++ b/src/plastimatch/util/itk_adjust.cxx
@@ -28,79 +28,6 @@ itk_adjust (FloatImageType::Pointer image_in, const Float_pair_list& al)
it.Set (pwlut.lookup (it.Get()));
}
return image_out;
-
-#if defined (commentout)
- /* Special processing for end caps */
- float left_slope = 1.0;
- float right_slope = 1.0;
- Float_pair_list::const_iterator ait_start = al.begin();
- Float_pair_list::const_iterator ait_end = al.end();
- if (ait_start->first == -std::numeric_limits<float>::max()) {
- left_slope = ait_start->second;
- ait_start++;
- }
- if ((--ait_end)->first == std::numeric_limits<float>::max()) {
- right_slope = ait_end->second;
- --ait_end;
- }
-
- /* Debug adjustment lists */
- Float_pair_list::const_iterator it_d = ait_start;
-#if defined (commentout)
- while (it_d != ait_end) {
- printf ("[%f,%f]\n", it_d->first, it_d->second);
- it_d ++;
- }
- printf ("[%f,%f]\n", it_d->first, it_d->second);
- printf ("slopes [%f,%f]\n", left_slope, right_slope);
- printf ("ait_start [%f,%f]\n", ait_start->first, ait_start->second);
- printf ("ait_end [%f,%f]\n", ait_end->first, ait_end->second);
-#endif
-
- for (it.GoToBegin(); !it.IsAtEnd(); ++it) {
- float vin = it.Get();
- float vout;
-
- /* Three possible cases: before first node, between two nodes, and
- after last node */
-
- /* Case 1 */
- if (vin <= ait_start->first) {
- vout = ait_start->second + (vin - ait_start->first) * left_slope;
-#if defined (commentout)
- printf ("[1] < %f (%f -> %f)\n", ait_start->first, vin, vout);
-#endif
- goto found_vout;
- }
- else if (ait_start != ait_end) {
- Float_pair_list::const_iterator ait = ait_start;
- Float_pair_list::const_iterator prev = ait_start;
- do {
- ait++;
- /* Case 2 */
- if (vin <= ait->first) {
- float slope = (ait->second - prev->second)
- / (ait->first - prev->first);
- vout = prev->second + (vin - prev->first) * slope;
-#if defined (commentout)
- printf ("[2] in (%f,%f) (%f -> %f)\n", prev->first,
- ait->first, vin, vout);
-#endif
- goto found_vout;
- }
- prev = ait;
- } while (ait != ait_end);
- }
- /* Case 3 */
- vout = ait_end->second + (vin - ait_end->first) * right_slope;
-#if defined (commentout)
- printf ("[3] > %f (%f -> %f)\n", ait_end->first, vin, vout);
-#endif
- found_vout:
- it.Set (vout);
- }
- return image_out;
-#endif
}
FloatImageType::Pointer
diff --git a/src/plastimatch/util/itk_distance_map.cxx b/src/plastimatch/util/itk_distance_map.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/util/itk_threshold.cxx b/src/plastimatch/util/itk_threshold.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/util/itk_threshold.h b/src/plastimatch/util/itk_threshold.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/util/vf_invert.cxx b/src/plastimatch/util/vf_invert.cxx
old mode 100755
new mode 100644
diff --git a/src/plastimatch/util/vf_invert.h b/src/plastimatch/util/vf_invert.h
old mode 100755
new mode 100644
diff --git a/src/plastimatch/util/volume_adjust.cxx b/src/plastimatch/util/volume_adjust.cxx
new file mode 100644
index 0000000..67b70a8
--- /dev/null
+++ b/src/plastimatch/util/volume_adjust.cxx
@@ -0,0 +1,40 @@
+/* -----------------------------------------------------------------------
+ See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
+ ----------------------------------------------------------------------- */
+#include "plmutil_config.h"
+#include <limits>
+
+#include "float_pair_list.h"
+#include "plm_math.h"
+#include "print_and_exit.h"
+#include "pwlut.h"
+#include "volume.h"
+#include "volume_adjust.h"
+
+Volume::Pointer
+volume_adjust (const Volume::Pointer& image_in, const Float_pair_list& al)
+{
+ Volume::Pointer vol_out = image_in->clone (PT_FLOAT);
+ float *vol_img = vol_out->get_raw<float> ();
+
+ Pwlut pwlut;
+ pwlut.set_lut (al);
+
+ for (plm_long v = 0; v < vol_out->npix; v++) {
+ vol_img[v] = pwlut.lookup (vol_img[v]);
+ }
+ return vol_out;
+}
+
+Volume::Pointer
+volume_adjust (const Volume::Pointer& image_in, const std::string& adj_string)
+{
+ Float_pair_list al = parse_float_pairs (adj_string);
+
+ if (al.empty()) {
+ print_and_exit ("Error: couldn't parse adjust string: %s\n",
+ adj_string.c_str());
+ }
+
+ return volume_adjust (image_in, al);
+}
diff --git a/src/plastimatch/util/volume_adjust.h b/src/plastimatch/util/volume_adjust.h
new file mode 100644
index 0000000..2376093
--- /dev/null
+++ b/src/plastimatch/util/volume_adjust.h
@@ -0,0 +1,15 @@
+/* -----------------------------------------------------------------------
+ See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information
+ ----------------------------------------------------------------------- */
+#ifndef _volume_adjust_h_
+#define _volume_adjust_h_
+
+#include "plmutil_config.h"
+#include "float_pair_list.h"
+
+PLMUTIL_API Volume::Pointer
+volume_adjust (const Volume::Pointer& image_in, const Float_pair_list& al);
+PLMUTIL_API Volume::Pointer
+volume_adjust (const Volume::Pointer& image_in, const std::string& adj_string);
+
+#endif
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/plastimatch.git
More information about the debian-med-commit
mailing list