# Starguide reconstruction in forward function

**URL:** <https://pytomography.discourse.group/t/starguide-reconstruction-in-forward-function/82>\
**Category:** General\
**Created:** [December 18, 2024, 6:07pm UTC](https://pytomography.discourse.group/t/starguide-reconstruction-in-forward-function/82 "2024-12-18T18:07:45Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Yazdan](https://avatars.discourse-cdn.com/v4/letter/y/858c86/32.png) [@Yazdan](https://pytomography.discourse.group/u/Yazdan)\
**Post date:** [December 18, 2024, 6:07pm UTC](https://pytomography.discourse.group/t/starguide-reconstruction-in-forward-function/82/1 "2024-12-18T18:07:45Z")

</div>

Thank you Luke for this exceptional effort.  
I am trying to recon starguide data and I see Seperable1DBlurNet.forward recives an 2D input in some place and throws an erro in permute function.  
Do you have any idea how to solve it?  
Thank you

---

<div class="post-metadata">

**Author:** ![lukepolson](https://avatars.discourse-cdn.com/v4/letter/l/e9a140/32.png) [@lukepolson](https://pytomography.discourse.group/u/lukepolson)\
**Post date:** [January 15, 2025, 3:25am UTC](https://pytomography.discourse.group/t/starguide-reconstruction-in-forward-function/82/2 "2025-01-15T03:25:45Z")

</div>

Hey Yazdan, sorry for the super late reply here, can you share a screenshot of what you are doing? Or would you like to set up a video call?

---

<div class="post-metadata">

**Author:** ![Yazdan](https://avatars.discourse-cdn.com/v4/letter/y/858c86/32.png) [@Yazdan](https://pytomography.discourse.group/u/Yazdan)\
**Post date:** [January 15, 2025, 8:56am UTC](https://pytomography.discourse.group/t/starguide-reconstruction-in-forward-function/82/3 "2025-01-15T08:56:00Z")

</div>

You are welcome Luke. Thank you for your response.  
this is the code I copied from your instruction:

# code

# 

import yazdan  
import sys  
import os  
from glob import glob  
from termcolor import cprint  
from natsort import os\_sorted  
from tqdm import tqdm  
import pandas as pd  
import SimpleITK as sitk  
import numpy as np  
import shutil  
import matplotlib.pyplot as plt  
import pydicom  
from pytomography.transforms.SPECT import SPECTAttenuationTransform, SPECTPSFTransform  
from pytomography.io.SPECT import dicom  
from pytomography.algorithms import OSEM  
from pytomography.likelihoods import PoissonLogLikelihood  
from pytomography.projectors.SPECT import StarGuideSystemMatrix  
############################ import defaults ############################  
if **name** == “ **main** ”:  
scatter\_correction = True  
# Define the path to the data  
PATH = r’D:\test-pytomography’  
# Get the file paths of the 12 projection DICOM files  
path\_NM = os.path.join(PATH, ‘starguide’, ‘NM\_files’)  
files\_NM = glob(os.path.join(path\_NM, “\*”))[:12]  
# Retrieve metadata and projection data  
object\_meta, proj\_meta = dicom.get\_starguide\_metadata(files\_NM, nearest\_theta=0.1)  
projections = dicom.get\_starguide\_projections(files\_NM)  
print(projections.shape) # Expected output: torch.Size([2, 2575, 16, 112])  
# Obtain the attenuation map and transform  
path\_CT = os.path.join(PATH, ‘starguide’, ‘CT\_files’)  
files\_CT = [os.path.join(path\_CT, file) for file in os.listdir(path\_CT)]  
files\_CT = [x for x in files\_CT if not “.ini” in x]  
attenuation\_map = dicom.get\_starguide\_attenuation\_map\_from\_CT\_slices(files\_CT, files\_NM, index\_peak=0)  
attenuation\_transform = SPECTAttenuationTransform(attenuation\_map, assume\_padded=False)  
print(“attenuation map generated”)  
# Define the PSF transform  
psf\_meta = dicom.get\_psfmeta\_from\_scanner\_params(  
‘G8-LEHR’, # Collimator parameters from the header  
energy\_keV=140.5, # Imaging of Tc-99m  
material=‘tungsten’, # Known material  
shape=‘square’ # Collimator hole shape  
)  
psf\_transform = SPECTPSFTransform(psf\_meta, assume\_padded=False)  
print(“psf\_transform was defined”)  
# Build the system matrix  
system\_matrix = StarGuideSystemMatrix(  
object\_meta=object\_meta,  
proj\_meta=proj\_meta,  
# obj2obj\_transforms=[psf\_transform],  
proj2proj\_transforms=  
)  
print(“system matrix was defined”)  
# Separate photopeak and scatter for the likelihood  
photopeak = projections[0]  
# yazdan.image.view([photopeak])  
if scatter\_correction:  
scatter = dicom.get\_energy\_window\_scatter\_estimate\_projections(  
files\_NM[0],  
projections,  
index\_peak=0,  
index\_lower=1  
)  
# Define the likelihood and reconstruct using OSEM  
likelihood = PoissonLogLikelihood(system\_matrix, photopeak, additive\_term=scatter)  
else:  
likelihood = PoissonLogLikelihood(system\_matrix, photopeak)

```
reconstruction_algorithm = OSEM(likelihood)
print("reconstruction_algorithm was set")

recon_pytomography = reconstruction_algorithm(n_iters=4, n_subsets=4)
print("reconstruction_algorithm was executed")

# Load vendor reconstruction for comparison

```

# Output

it recives a 2D array in forward. I changed the data, the error exists with ether a single bed or multi bed scan.

this is the error:  
torch.Size([5, 3350, 16, 112])  
attenuation map generated  
psf\_transform was defined  
system matrix was defined  
reconstruction\_algorithm was set  
Traceback (most recent call last):  
File “C:\Users\Yazdan\Downloads\pytomoexample.py”, line 83, in   
recon\_pytomography = reconstruction\_algorithm(n\_iters=4, n\_subsets=4)  
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  
File “C:\Users\Yazdan\anaconda3\envs\image\Lib\site-packages\pytomography\algorithms\preconditioned\_gradient\_ascent.py”, line 119, in **call**  
likelihood\_gradient = self.likelihood.compute\_gradient(self.object\_prediction, subset\_idx)  
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  
File “C:\Users\Yazdan\anaconda3\envs\image\Lib\site-packages\pytomography\likelihoods\poisson\_log\_likelihood.py”, line 34, in compute\_gradient  
self.projections\_predicted = self.system\_matrix.forward(object, subset\_idx) + additive\_term\_subset  
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  
File “C:\Users\Yazdan\anaconda3\envs\image\Lib\site-packages\torch\utils\_contextlib.py”, line 116, in decorate\_context  
return func(\*args, \*\*kwargs)  
^^^^^^^^^^^^^^^^^^^^^  
File “C:\Users\Yazdan\anaconda3\envs\image\Lib\site-packages\pytomography\projectors\SPECT\starguide\_system\_matrix.py”, line 64, in forward  
obj\_translate\_rot = self.\_translate\_object(obj\_rotate, offsets\_i/self.object\_meta.dx)  
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  
File “C:\Users\Yazdan\anaconda3\envs\image\Lib\site-packages\pytomography\projectors\SPECT\starguide\_system\_matrix.py”, line 167, in \_translate\_object  
obj\_translated = Translate(translation)(obj.permute((0,3,1,2))).permute((0,2,3,1))  
^^^^^^^^^^^^^^^^^^^^^^  
RuntimeError: permute(sparse\_coo): number of dimensions in the tensor input does not match the length of the desired ordering of dimensions i.e. input.dim() = 3 is not equal to len(dims) = 4
