STIR 6.5.0
conv_SimSET_crystal_pairs_to_STIR.cxx File Reference

Rebins a SimSET block-detector weight file, binned by crystal pair, into STIR projection data. More...

#include "stir/ProjData.h"
#include "stir/ProjDataInMemory.h"
#include "stir/ProjDataInfoPETScannerWithDiscreteDetectors.h"
#include "stir/DetectionPositionPair.h"
#include "stir/Bin.h"
#include "stir/Scanner.h"
#include "stir/format.h"
#include "stir/info.h"
#include "stir/warning.h"
#include "stir/error.h"
#include <algorithm>
#include <cstdint>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>

Functions

int main (int argc, char **argv)

Detailed Description

Rebins a SimSET block-detector weight file, binned by crystal pair, into STIR projection data.

SimSET run with a block detector and bin_by_crystal = true writes its weights indexed by crystal pair, not by sinogram bin. This utility maps each bin of a STIR template onto its detection position pairs, and sums the corresponding crystal-pair weights.

Usage
conv_SimSET_crystal_pairs_to_STIR output_prefix template_projdata weight_file mode
Parameters
output_prefixoutputs are written as output_prefix_<label>.hs
template_projdataprojection data describing the scanner and the output sinogram
weight_fileSimSET's weight_image_path from the bin.rec file
modemultiples or singles_scat, see below

The block layout is taken from the template's scanner, which has to agree with the simulated SimSET detector:

  • number of rings / crystals per block in axial direction: number of block rings in det.rec that contain active crystals (rings with only shielding do not count)
  • number of detectors per ring / crystals per block in transaxial direction: ring_num_blocks_in_ring in the ring parameter file
  • crystals per block in axial direction: number of active crystals per block along z
  • crystals per block in transaxial direction: number of active crystals per block along y

When every element of the block is an active crystal, the last two are block_layer_num_z_changes + 1 and block_layer_num_y_changes + 1.

File format and modes
A weight file is a SimSET header of 32768 bytes, followed by one or more grids of num_crystals x num_crystals native-endian floats. How many grids there are was decided at simulation time by the bin.rec file.
  • multiples expects 1 grid (e.g. scatter_param = 5, min_s = max_s = 2), written as label multiples.
  • singles_scat expects 2 grids, [unscattered][single Scatter estimation building blocks] (e.g. scatter_param = 4, min_s = 0, max_s = 1), written as labels unscattered and singles_scat. The number of grids in the file has to match the mode.
Crystal numbering
The template's scanner has to describe the simulated detector, including its block subdivision. The crystal index of a detection position is
block_index * (crystals_per_block_axial * crystals_per_block_transaxial)
+ axial_index_in_block * crystals_per_block_transaxial + transaxial_index_in_block
with block_index = axial_block * num_transaxial_blocks + transaxial_block. A template with the right total number of crystals but a different block subdivision would give a permuted, wrong, sinogram without any error. Only the upper triangle of each grid (crystal1 < crystal2) is used.

The views of the output are stored in reverse order (view -> num_views - 1 - view). SimSET's y axis points up (voxel row 0 is at yMax) and STIR's points down, so an image written row by row for SimSET is the same picture in both, with y_SimSET = -y_STIR. Both number their crystals counter-clockwise in their own frame, so seen from the object the two rings are numbered in opposite directions: SimSET crystal k is the mirror image of STIR detector k. Reversing the views undoes this mirror. The exact alignment depends on the template's view offset.

Warning
The whole grid is read into memory (4 num_crystals^2 bytes, 5.8 GB for 38016 crystals).
Only Cylindrical and BlocksOnCylindrical non-arc-corrected, non-TOF, templates are supported.
Author
Antonia Reeves