CERN / TIGRE

TIGRE: Tomographic Iterative GPU-based Reconstruction Toolbox
BSD 3-Clause "New" or "Revised" License
529 stars 180 forks source link

Inverted u/v parameters in geometry setting #482

Closed taijizhao closed 10 months ago

taijizhao commented 10 months ago

First thank you so much for sharing the excellent toolbox! I used the matlab version years ago and now moving to the python version. However, I found that the u and v parameters in geometry are inverted between matlab and python. It seems that for matlab,

geo.nDetector=[256; 512];                   % number of pixels              (px)

256 and 512 represent pixel numbers in width(u) and high(v) respectively, and for python, they are the opposite. geo.offDetector has the same behavior. I caused some confusion when I tried to implement Wang's weighting for displaced detector using python. Is there some reason for this design? Thank you very much!

Expected Behavior

geo.nDetector[0] and geo.nDetector[1] represent pixel numbers in u and v direction respectively in both matlab and python.

Actual Behavior

set

geo.nDetector=[256; 512];

In Matlab, I got

图片2

In Python, I got

图片1

Code to reproduce the problem (If applicable)


%% Initialize
clear;
close all;
%% Geometry
% VARIABLE                                   DESCRIPTION                    UNITS
%-------------------------------------------------------------------------------------
% Distances
geo.DSD = 1536;                             % Distance Source Detector      (mm)
geo.DSO = 1000;                             % Distance Source Origin        (mm)
% Detector parameters
geo.nDetector=[256; 512];                   % number of pixels              (px)
geo.dDetector=[0.8; 0.8];                   % size of each pixel            (mm)
geo.sDetector=geo.nDetector.*geo.dDetector; % total size of the detector    (mm)
% Image parameters
geo.nVoxel=[256;256;256];                   % number of voxels              (vx)
geo.sVoxel=[256;256;256];                   % total size of the image       (mm)
geo.dVoxel=geo.sVoxel./geo.nVoxel;          % size of each voxel            (mm)
% Offsets
geo.offOrigin =[0;0;0];                     % Offset of image from origin   (mm)              
geo.offDetector=[0; 0];                     % Offset of Detector            (mm)
% Auxiliary 
geo.accuracy=0.5;                           % Variable to define accuracy of                      
geo.COR=0;                                  % y direction displacement for 
geo.rotDetector=[0;0;0];                    % Rotation of the detector, by                       
geo.mode='cone';                           
% define projection angles (in radians)
angles=linspace(0,2*pi,100);
% load phatnom image
head=headPhantom(geo.nVoxel);

projections=Ax(head,geo,angles,'interpolated');
noise_projections=addCTnoise(projections,'Poisson',1e5,'Gaussian',[0 10]);

% Plot Projections
plotProj(projections,angles)
import tigre
import numpy as np
from tigre.utilities import sample_loader
from tigre.utilities import CTnoise
import os
# set visible gpu devices
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
geo = tigre.geometry()
# VARIABLE                                   DESCRIPTION                    UNITS
# -------------------------------------------------------------------------------------
# Distances
geo.DSD = 1536  # Distance Source Detector      (mm)
geo.DSO = 1000  # Distance Source Origin        (mm)
# Detector parameters
geo.nDetector = np.array([256, 512])  # number of pixels              (px)
geo.dDetector = np.array([0.8, 0.8])  # size of each pixel            (mm)
geo.sDetector = geo.nDetector * geo.dDetector  # total size of the detector    (mm)
# Image parameters
geo.nVoxel = np.array([256, 256, 256])  # number of voxels              (vx)
geo.sVoxel = np.array([256, 256, 256])  # total size of the image       (mm)
geo.dVoxel = geo.sVoxel / geo.nVoxel  # size of each voxel            (mm)
# Offsets
geo.offOrigin = np.array([0, 0, 0])  # Offset of image from origin   (mm)
geo.offDetector = np.array([0, 0])  # Offset of Detector            (mm)
# Auxiliary
geo.accuracy = 0.5  # Variable to define accuracy of
geo.COR = 0  # y direction displacement for
geo.rotDetector = np.array([0, 0, 0])  # Rotation of the detector, by
geo.mode = "cone"  # Or 'parallel'. Geometry type.
#%% Define angles of projection and load phatom image

# define projection angles (in radians)
angles = np.linspace(0, 2 * np.pi, 50)
# load phatnom image
head = sample_loader.load_head_phantom(geo.nVoxel)

# Simulate forward projection.
# To match with mathematical notation, the projection operation is called Ax
projections = tigre.Ax(head, geo, angles)
#%% Plot Projections
tigre.plotproj(projections)

Specifications

tsadakane commented 10 months ago

Hi, @taijizhao I don't know if it's appropriate for me to answer, but I think that is the spec. It stems from the difference of the memory layout and how to specify the address between Matlab and Python. You can refer to the following comment: https://github.com/CERN/TIGRE/issues/191#issuecomment-750699972

taijizhao commented 10 months ago

Hi, @taijizhao I don't know if it's appropriate for me to answer, but I think that is the spec. It stems from the difference of the memory layout and how to specify the address between Matlab and Python. You can refer to the following comment: #191 (comment)

Thank you very much for the explaination! It is actually not an issue. I am just trying to understand the difference to avoid my mistakes when modifying the code.

AnderBiguri commented 10 months ago

Thanks @tsadakane for the link :) @taijizhao let me know if you have more questions :)