From fbc49172a3fce73100bcbb3b0f6e25037965753a Mon Sep 17 00:00:00 2001 From: Markus Jehl Date: Tue, 9 Jul 2024 13:42:39 +0000 Subject: [PATCH] Correctly using gaps between blocks. Also, small unrelated bugfix in extend_projdata. --- src/buildblock/extend_projdata.cxx | 2 +- src/buildblock/interpolate_projdata.cxx | 41 +++++++++++++++---------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/buildblock/extend_projdata.cxx b/src/buildblock/extend_projdata.cxx index 1ecd11c15..59fa14288 100644 --- a/src/buildblock/extend_projdata.cxx +++ b/src/buildblock/extend_projdata.cxx @@ -93,7 +93,7 @@ extend_segment(const SegmentBySinogram& segment, if (extend_without_wrapping) { out[axial_pos][min_dim[2] + view_edge] = out[axial_pos][min_dim[2] + view_extension]; - out[axial_pos][max_dim[2] - view_extension] = out[axial_pos][max_dim[2] - view_extension]; + out[axial_pos][max_dim[2] - view_edge] = out[axial_pos][max_dim[2] - view_extension]; } else if (flip_views) { diff --git a/src/buildblock/interpolate_projdata.cxx b/src/buildblock/interpolate_projdata.cxx index 6557b7dba..a8047fcc1 100644 --- a/src/buildblock/interpolate_projdata.cxx +++ b/src/buildblock/interpolate_projdata.cxx @@ -240,20 +240,7 @@ interpolate_projdata(ProjData& proj_data_out, }; } else - { // for BlocksOnCylindrical, views and tangential positions are scaled by a fixed value - auto transaxial_bucket_size_in = (proj_data_in_info.get_scanner_sptr()->get_num_transaxial_blocks_per_bucket() - 1) - * proj_data_in_info.get_scanner_sptr()->get_transaxial_block_spacing() - + (proj_data_in_info.get_scanner_sptr()->get_num_transaxial_crystals_per_block() - 1) - * proj_data_in_info.get_scanner_sptr()->get_transaxial_crystal_spacing(); - auto transaxial_bucket_size_out = (proj_data_out_info.get_scanner_sptr()->get_num_transaxial_blocks_per_bucket() - 1) - * proj_data_out_info.get_scanner_sptr()->get_transaxial_block_spacing() - + (proj_data_out_info.get_scanner_sptr()->get_num_transaxial_crystals_per_block() - 1) - * proj_data_out_info.get_scanner_sptr()->get_transaxial_crystal_spacing(); - // TODO: for now assuming the bucket sizes are the same (so ignoring the above and not adding an offset when translating - // crystal positions) - auto scale_factor = (double)proj_data_out_info.get_scanner_sptr()->get_transaxial_crystal_spacing() - / (double)proj_data_in_info.get_scanner_sptr()->get_transaxial_crystal_spacing(); - + { // only extending in axial direction - an extension of 2 was found to be sufficient proj_data_interpolator.set_coef(extend_segment(segment, 5, 2, 5)); @@ -270,7 +257,7 @@ interpolate_projdata(ProjData& proj_data_out, } // define a function to translate indices in the output proj data to indices in input proj data - index_converter = [&proj_data_out_info, &proj_data_in_info, m_offset, m_sampling, scale_factor]( + index_converter = [&proj_data_out_info, &proj_data_in_info, m_offset, m_sampling]( const BasicCoordinate<3, int>& index_out) -> BasicCoordinate<3, double> { // translate index on output to coordinate auto bin @@ -294,10 +281,30 @@ interpolate_projdata(ProjData& proj_data_out, const auto proj_data_in_info_ptr = dynamic_cast(&proj_data_in_info); const int dets_per_module_in = proj_data_in_info_ptr->get_scanner_sptr()->get_num_transaxial_crystals_per_bucket(); + double crystal1_out_module_idx = det1_num_out % dets_per_module_out; + double crystal1_out_module_pos + = static_cast( + std::floor(crystal1_out_module_idx + / proj_data_out_info_ptr->get_scanner_sptr()->get_num_transaxial_crystals_per_block())) + * proj_data_out_info_ptr->get_scanner_sptr()->get_transaxial_block_spacing() + + static_cast(static_cast(crystal1_out_module_idx) + % proj_data_out_info_ptr->get_scanner_sptr()->get_num_transaxial_crystals_per_block()) + * proj_data_out_info_ptr->get_scanner_sptr()->get_transaxial_crystal_spacing(); double crystal1_num_in - = det1_module * dets_per_module_in + static_cast(det1_num_out % dets_per_module_out) * scale_factor; + = det1_module * dets_per_module_in + + crystal1_out_module_pos / proj_data_in_info.get_scanner_sptr()->get_transaxial_crystal_spacing(); + double crystal2_out_module_idx = det2_num_out % dets_per_module_out; + double crystal2_out_module_pos + = static_cast( + std::floor(crystal2_out_module_idx + / proj_data_out_info_ptr->get_scanner_sptr()->get_num_transaxial_crystals_per_block())) + * proj_data_out_info_ptr->get_scanner_sptr()->get_transaxial_block_spacing() + + static_cast(static_cast(crystal2_out_module_idx) + % proj_data_out_info_ptr->get_scanner_sptr()->get_num_transaxial_crystals_per_block()) + * proj_data_out_info_ptr->get_scanner_sptr()->get_transaxial_crystal_spacing(); double crystal2_num_in - = det2_module * dets_per_module_in + static_cast(det2_num_out % dets_per_module_out) * scale_factor; + = det2_module * dets_per_module_in + + crystal2_out_module_pos / proj_data_in_info.get_scanner_sptr()->get_transaxial_crystal_spacing(); auto crystal1_num_in_floor = std::max(static_cast(std::floor(crystal1_num_in)), det1_module * dets_per_module_in); auto crystal1_num_in_ceil