Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion documentation/release_5.0.htm
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,10 @@ <h3>Changed functionality</h3>
with multiple time frames (corresponding to the time frames of the data where the parametric image is derived from).
In some cases, there could only be a single time frame (start to end of the study).
</li>
<li><tt>apply_patlak_to_images</tt> no longer uses an existing file as a template for the dynamic image but will overwrite it.</li>
<li> <code>find_ML_normfactors3D</code> and <code>apply_ML_normfactors3D</code> can be used for scanner with virtual crystal (Only verified on mCT).
Contributed by Gefei Chen, see <a href=https://github.com/UCL/STIR/pull/833>PR 833</a>.
</li>
li><tt>apply_patlak_to_images</tt> no longer uses an existing file as a template for the dynamic image but will overwrite it.</li>
<li><tt>ROOT</tt> file I/O improvements. An entire entry's tree is no longer loaded by default and instead individual branches are loaded as needed.
ROOT file event processing is now up to 4x faster. In addition, there is now an option to <tt>check energy window information</tt> (defaulting to on).
Futhermore, added functionality to exclude true and unscattered event types from list mode processing. </li>
Expand Down
247 changes: 100 additions & 147 deletions src/buildblock/ML_norm.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

\author Kris Thielemans
\author Tahereh Niknejad
\author Gefei Chen

*/

Expand Down Expand Up @@ -971,46 +972,6 @@ get_fan_info(int& num_rings, int& num_detectors_per_ring,

}

void make_fan_data(FanProjData& fan_data,
const ProjData& proj_data)
{
int num_rings;
int num_detectors_per_ring;
int fan_size;
int max_delta;
shared_ptr<const ProjDataInfoCylindricalNoArcCorr> proj_data_info_ptr =
get_fan_info(num_rings, num_detectors_per_ring, max_delta, fan_size,
*proj_data.get_proj_data_info_sptr());

const int half_fan_size = fan_size/2;
fan_data = FanProjData(num_rings, num_detectors_per_ring, max_delta, 2*half_fan_size+1);

shared_ptr<SegmentBySinogram<float> > segment_ptr;
Bin bin;

for (bin.segment_num() = proj_data.get_min_segment_num(); bin.segment_num() <= proj_data.get_max_segment_num(); ++ bin.segment_num())
{
segment_ptr.reset(new SegmentBySinogram<float>(proj_data.get_segment_by_sinogram(bin.segment_num())));

for (bin.axial_pos_num() = proj_data.get_min_axial_pos_num(bin.segment_num());
bin.axial_pos_num() <= proj_data.get_max_axial_pos_num(bin.segment_num());
++bin.axial_pos_num())
for (bin.view_num() = 0; bin.view_num() < num_detectors_per_ring/2; bin.view_num()++)
for (bin.tangential_pos_num() = -half_fan_size;
bin.tangential_pos_num() <= half_fan_size;
++bin.tangential_pos_num())
{
int ra = 0, a = 0;
int rb = 0, b = 0;

proj_data_info_ptr->get_det_pair_for_bin(a, ra, b, rb, bin);

fan_data(ra, a, rb, b) =
fan_data(rb, b, ra, a) =
(*segment_ptr)[bin.axial_pos_num()][bin.view_num()][bin.tangential_pos_num()];
}
}
}

/// **** This function make fan_data from projecion file while removing the intermodule gaps **** ////
/// *** fan_data doesn't have gaps, proj_data has gaps *** ///
Expand All @@ -1027,45 +988,54 @@ void make_fan_data_remove_gaps(FanProjData& fan_data,

const int half_fan_size = fan_size/2;


// **** Added by me **** //


const int num_transaxial_blocks =
proj_data_info_ptr ->get_scanner_sptr()->
get_num_transaxial_blocks();
const int num_axial_blocks =
proj_data_info_ptr->get_scanner_sptr()->
get_num_axial_blocks();
const int num_transaxial_crystals_per_block =
proj_data_info_ptr->get_scanner_sptr()->
get_num_transaxial_crystals_per_block();
const int num_axial_crystals_per_block =
proj_data_info_ptr->get_scanner_sptr()->
get_num_axial_crystals_per_block();



const int num_transaxial_blocks_in_fansize = fan_size/num_transaxial_crystals_per_block;
const int new_fan_size = fan_size - num_transaxial_blocks_in_fansize;
const int virtual_axial_crystals =
proj_data_info_ptr->get_scanner_sptr()->
get_num_virtual_axial_crystals_per_block();

const int virtual_transaxial_crystals =
proj_data_info_ptr->get_scanner_sptr()->
get_num_virtual_transaxial_crystals_per_block();

const int num_transaxial_blocks =
proj_data_info_ptr ->get_scanner_sptr()->
get_num_transaxial_blocks();
const int num_axial_blocks =
proj_data_info_ptr->get_scanner_sptr()->
get_num_axial_blocks();
const int num_transaxial_crystals_per_block =
proj_data_info_ptr->get_scanner_sptr()->
get_num_transaxial_crystals_per_block();
const int num_axial_crystals_per_block =
proj_data_info_ptr->get_scanner_sptr()->
get_num_axial_crystals_per_block();

const int num_physical_transaxial_crystals_per_block = num_transaxial_crystals_per_block - virtual_transaxial_crystals;

const int num_physical_axial_crystals_per_block = num_axial_crystals_per_block - virtual_axial_crystals;
Comment on lines +1013 to +1015
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we could just as well provide the member functions for these 2 as well.



const int num_transaxial_blocks_in_fansize = fan_size/(num_transaxial_crystals_per_block);
const int new_fan_size = fan_size - num_transaxial_blocks_in_fansize*virtual_transaxial_crystals;
const int new_half_fan_size = new_fan_size/2;
const int num_axial_blocks_in_max_delta = max_delta/num_axial_crystals_per_block;
const int new_max_delta = max_delta - num_axial_blocks_in_max_delta - 1;
const int new_num_detectors_per_ring = num_detectors_per_ring - num_transaxial_blocks;
const int new_num_rings = num_rings - num_axial_blocks;

const int num_axial_blocks_in_max_delta = max_delta/(num_axial_crystals_per_block);
const int new_max_delta = max_delta - (num_axial_blocks_in_max_delta)*virtual_axial_crystals;
const int num_physical_detectors_per_ring = num_detectors_per_ring - num_transaxial_blocks*virtual_transaxial_crystals;
const int num_physical_rings = num_rings - (num_axial_blocks-1)*virtual_axial_crystals;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with this.



// **** End **** //

fan_data = FanProjData(new_num_rings, new_num_detectors_per_ring, new_max_delta, 2*new_half_fan_size+1);
fan_data = FanProjData(num_physical_rings, num_physical_detectors_per_ring, new_max_delta, 2*new_half_fan_size+1);



shared_ptr<SegmentBySinogram<float> > segment_ptr;
Bin bin;

for (bin.segment_num() = proj_data.get_min_segment_num(); bin.segment_num() <= proj_data.get_max_segment_num(); ++ bin.segment_num())
{
segment_ptr.reset(new SegmentBySinogram<float>(proj_data.get_segment_by_sinogram(bin.segment_num())));

for (bin.axial_pos_num() = proj_data.get_min_axial_pos_num(bin.segment_num());
bin.axial_pos_num() <= proj_data.get_max_axial_pos_num(bin.segment_num());
++bin.axial_pos_num())
Expand All @@ -1076,15 +1046,28 @@ void make_fan_data_remove_gaps(FanProjData& fan_data,
{
int ra = 0, a = 0;
int rb = 0, b = 0;

proj_data_info_ptr->get_det_pair_for_bin(a, ra, b, rb, bin);
int new_a = a - a/num_transaxial_crystals_per_block;
int new_b = b - b/num_transaxial_crystals_per_block;
int new_ra = ra - ra/ num_axial_crystals_per_block;
int new_rb = rb - rb/num_axial_crystals_per_block;

if ((ra == num_rings -1) || (rb == num_rings -1) || (a == num_detectors_per_ring-1) || (b == num_detectors_per_ring-1)) continue;

int a_in_block = a % num_transaxial_crystals_per_block;

if (a_in_block >= num_physical_transaxial_crystals_per_block)
continue;
int new_a = a - a / num_transaxial_crystals_per_block;

int ra_in_block = ra % num_axial_crystals_per_block;
if (ra_in_block >= num_physical_axial_crystals_per_block)
continue;
int new_ra = ra - ra / num_axial_crystals_per_block;

int b_in_block = b % num_transaxial_crystals_per_block;
if (b_in_block >= num_physical_transaxial_crystals_per_block)
continue;
int new_b = b - b / num_transaxial_crystals_per_block;

int rb_in_block = rb % num_axial_crystals_per_block;
if (rb_in_block >= num_physical_axial_crystals_per_block)
continue;
int new_rb = rb - rb / num_axial_crystals_per_block;

fan_data(new_ra, new_a, new_rb, new_b) =
fan_data(new_rb, new_b, new_ra, new_a) =
Expand All @@ -1094,52 +1077,10 @@ void make_fan_data_remove_gaps(FanProjData& fan_data,
}


void set_fan_data(ProjData& proj_data,
const FanProjData& fan_data)
{
int num_rings;
int num_detectors_per_ring;
int fan_size;
int max_delta;
shared_ptr<const ProjDataInfoCylindricalNoArcCorr> proj_data_info_ptr =
get_fan_info(num_rings, num_detectors_per_ring, max_delta, fan_size,
*proj_data.get_proj_data_info_sptr());

const int half_fan_size = fan_size/2;
assert(num_rings == fan_data.get_num_rings());
assert(num_detectors_per_ring == fan_data.get_num_detectors_per_ring());

Bin bin;
shared_ptr<SegmentBySinogram<float> > segment_ptr;

for (bin.segment_num() = proj_data.get_min_segment_num(); bin.segment_num() <= proj_data.get_max_segment_num(); ++ bin.segment_num())
{
segment_ptr.reset(new SegmentBySinogram<float>(proj_data.get_empty_segment_by_sinogram(bin.segment_num())));

for (bin.axial_pos_num() = proj_data.get_min_axial_pos_num(bin.segment_num());
bin.axial_pos_num() <= proj_data.get_max_axial_pos_num(bin.segment_num());
++bin.axial_pos_num())
for (bin.view_num() = 0; bin.view_num() < num_detectors_per_ring/2; bin.view_num()++)
for (bin.tangential_pos_num() = -half_fan_size;
bin.tangential_pos_num() <= half_fan_size;
++bin.tangential_pos_num())
{
int ra = 0, a = 0;
int rb = 0, b = 0;

proj_data_info_ptr->get_det_pair_for_bin(a, ra, b, rb, bin);

(*segment_ptr)[bin.axial_pos_num()][bin.view_num()][bin.tangential_pos_num()] =
fan_data(ra, a, rb, b);
}
proj_data.set_segment(*segment_ptr);
}
}

/// **** This function make proj_data from fan_data while adding the intermodule gaps **** ////
/// *** fan_data doesn't have gaps, proj_data has gaps *** ///
void set_fan_data_add_gaps(ProjData& proj_data,
const FanProjData& fan_data)
const FanProjData& fan_data, const float gap_value)
{
int num_rings;
int num_detectors_per_ring;
Expand All @@ -1148,37 +1089,40 @@ void set_fan_data_add_gaps(ProjData& proj_data,
shared_ptr<const ProjDataInfoCylindricalNoArcCorr> proj_data_info_ptr =
get_fan_info(num_rings, num_detectors_per_ring, max_delta, fan_size,
*proj_data.get_proj_data_info_sptr());

const int half_fan_size = fan_size/2;
//assert(num_rings == fan_data.get_num_rings());
//assert(num_detectors_per_ring == fan_data.get_num_detectors_per_ring());


// **** Added by Tahereh Nikjenad **** //

const int virtual_axial_crystals =
proj_data_info_ptr->get_scanner_sptr()->
get_num_virtual_axial_crystals_per_block();
const int virtual_transaxial_crystals =
proj_data_info_ptr->get_scanner_sptr()->
get_num_virtual_transaxial_crystals_per_block();
const int num_transaxial_crystals_per_block =
proj_data_info_ptr->get_scanner_sptr()->
get_num_transaxial_crystals_per_block();
const int num_axial_crystals_per_block =
proj_data_info_ptr->get_scanner_sptr()->
get_num_axial_crystals_per_block();

// const int num_axial_detectors = fan_data.get_num_rings(); // Number of ring in fan data (w/o gaps)
// const int num_transaxial_detectors = fan_data.get_num_detectors_per_ring(); // number of detector per ring in fan data w/o gaps

// const int num_axial_crystals_per_block = num_axial_detectors/num_axial_blocks; // number of axial detector per block in fan_data w/o gaps
// const int num_transaxial_crystals_per_block = num_transaxial_detectors/num_transaxial_blocks; // number of transaxial detector per block in fan_data w/o gaps


const int num_physical_transaxial_crystals_per_block = num_transaxial_crystals_per_block - virtual_transaxial_crystals;

const int num_physical_axial_crystals_per_block = num_axial_crystals_per_block - virtual_axial_crystals;


// **** End **** //

Bin bin;
shared_ptr<SegmentBySinogram<float> > segment_ptr;

for (bin.segment_num() = proj_data.get_min_segment_num(); bin.segment_num() <= proj_data.get_max_segment_num(); ++ bin.segment_num())
{
segment_ptr.reset(new SegmentBySinogram<float>(proj_data.get_empty_segment_by_sinogram(bin.segment_num())));

for (bin.axial_pos_num() = proj_data.get_min_axial_pos_num(bin.segment_num());
bin.axial_pos_num() <= proj_data.get_max_axial_pos_num(bin.segment_num());
++bin.axial_pos_num())
Expand All @@ -1191,19 +1135,29 @@ void set_fan_data_add_gaps(ProjData& proj_data,
int rb = 0, b = 0;

proj_data_info_ptr->get_det_pair_for_bin(a, ra, b, rb, bin);

(*segment_ptr)[bin.axial_pos_num()][bin.view_num()][bin.tangential_pos_num()] = 1e20;


if ((ra+1)% num_axial_crystals_per_block == 0) continue;
if ((rb+1)% num_axial_crystals_per_block == 0) continue;
if ((a+1)% num_transaxial_crystals_per_block == 0) continue;
if ((b+1)% num_transaxial_crystals_per_block == 0) continue;

int new_a = a - a/num_transaxial_crystals_per_block;
int new_b = b - b/num_transaxial_crystals_per_block;
int new_ra = ra - ra/ num_axial_crystals_per_block;
int new_rb = rb - rb/num_axial_crystals_per_block;
(*segment_ptr)[bin.axial_pos_num()][bin.view_num()][bin.tangential_pos_num()] = gap_value;


int a_in_block = a%num_transaxial_crystals_per_block;
if(a_in_block>=num_physical_transaxial_crystals_per_block)
continue;
int new_a = a-a/num_transaxial_crystals_per_block;

int ra_in_block = ra%num_axial_crystals_per_block;
if(ra_in_block>=num_physical_axial_crystals_per_block)
continue;
int new_ra = ra-ra/num_axial_crystals_per_block;

int b_in_block = b%num_transaxial_crystals_per_block;
if(b_in_block>=num_physical_transaxial_crystals_per_block)
continue;
int new_b = b-b/num_transaxial_crystals_per_block;

int rb_in_block = rb%num_axial_crystals_per_block;
if(rb_in_block>=num_physical_axial_crystals_per_block)
continue;
int new_rb = rb-rb/num_axial_crystals_per_block;


(*segment_ptr)[bin.axial_pos_num()][bin.view_num()][bin.tangential_pos_num()] =
Expand Down Expand Up @@ -1552,7 +1506,6 @@ void iterate_efficiencies(DetectorEfficiencies& efficiencies,
const FanProjData& model)
{
const int num_detectors_per_ring = model.get_num_detectors_per_ring();

assert(model.get_min_ra() == data_fan_sums.get_min_index());
assert(model.get_max_ra() == data_fan_sums.get_max_index());
assert(model.get_min_a() == data_fan_sums[data_fan_sums.get_min_index()].get_min_index());
Expand Down
9 changes: 2 additions & 7 deletions src/include/stir/ML_norm.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,17 +222,12 @@ get_fan_info(int& num_rings, int& num_detectors_per_ring,
int& max_ring_diff, int& fan_size,
const ProjDataInfo& proj_data_info);

void make_fan_data(FanProjData& fan_data,
const ProjData& proj_data);

void make_fan_data_remove_gaps(FanProjData& fan_data,
const ProjData& proj_data);

void set_fan_data(ProjData& proj_data,
const FanProjData& fan_data);

void set_fan_data_add_gaps(ProjData& proj_data,
const FanProjData& fan_data);
const FanProjData& fan_data,
const float gap_value=0.F);

void apply_block_norm(FanProjData& fan_data,
const BlockData3D& block_data,
Expand Down
Loading