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
28 changes: 28 additions & 0 deletions scripts/hackathon_scripts/synerby26/Foam_Like_Dataset_Generator
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import os
import numpy as np
import foam_ct_phantom

#Activate foam_env
OUTPUT_DIR = './Dataset_Hackathon/'
NUM_SAMPLES = 30
PIXSIZE = 0.004

if not os.path.exists(OUTPUT_DIR):
os.makedirs(OUTPUT_DIR)

phantom_file = 'phantom_hackathon.h5'
if not os.path.exists(phantom_file):
foam_ct_phantom.FoamPhantom.generate(phantom_file, seed=42, n_bubbles=2000, n_crystals=5000, radius=0.1, height=1.0)

phantom = foam_ct_phantom.FoamPhantom(phantom_file)
angles = np.linspace(0, np.pi, 720, endpoint=False)
for i in range(NUM_SAMPLES):
current_cz = 0.2 + (i * 0.02)

gt_filename = os.path.join(OUTPUT_DIR, f'gt_{i:04d}.h5')
sino_filename = os.path.join(OUTPUT_DIR, f'sino_{i:04d}.h5')

geom_vol = foam_ct_phantom.VolumeGeometry(512, 512, 1, float(PIXSIZE), 0.0, 0.0, float(current_cz))
phantom.generate_volume(gt_filename, geom_vol)
geom_proj = foam_ct_phantom.ParallelGeometry(1, 900, angles, float(PIXSIZE), 0.0, 0.0, float(current_cz))
phantom.generate_projections(sino_filename, geom_proj)
146 changes: 146 additions & 0 deletions scripts/hackathon_scripts/synerby26/Model_example_scripts
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import os
import numpy as np
import h5py
import LION.CTtools.ct_utils as ct_utils
import LION.CTtools.ct_geometry as ctgeo
from LION.utils.parameter import LIONParameter
import torch
import glob
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
import torch.utils.data as data_utils
from LION.classical_algorithms.fdk import fdk
from LION.optimizers.Noise2InverseSolver import Noise2InverseSolver
from LION.models.CNNs.UNets.Unet import UNet
from torch.utils.data import DataLoader
from torch.optim.adam import Adam
import torch.nn as nn
import random

##Activate lion_env

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
seed = 42
random.seed(seed)
torch.manual_seed(seed)
torch.cuda.manual_seed_all(seed)
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False


OUTPUT_DIR = './Dataset_Hackathon/'
SAVE_DIR = "./trained_models"
if not os.path.exists(SAVE_DIR):
os.makedirs(SAVE_DIR)


class FoamLike(Dataset):
def __init__(self, mode, parameters: LIONParameter):
self.path_to_dataset = parameters.path_to_dataset
self.mode = mode

self.target_angles = parameters.geometry.angles
self.num_target_angles = len(self.target_angles)

all_sino = sorted(glob.glob(os.path.join(self.path_to_dataset, 'sino_*.h5')))
all_gt = sorted(glob.glob(os.path.join(self.path_to_dataset, 'gt_*.h5')))

max_samples = getattr(parameters, 'max_samples', len(all_sino))
all_sino = all_sino[:max_samples]
all_gt = all_gt[:max_samples]

num = len(all_sino)
if mode == "train":
self.sino_files = all_sino[:int(num * 0.8)]
self.gt_files = all_gt[:int(num * 0.8)]
elif mode == "validation":
self.sino_files = all_sino[int(num * 0.8):int(num * 0.9)]
self.gt_files = all_gt[int(num * 0.8):int(num * 0.9)]
else:
self.sino_files = all_sino
self.gt_files = all_gt

def __len__(self):
return len(self.sino_files)

def __getitem__(self, index):
f_sino = h5py.File(self.sino_files[index], 'r')

total_in_file = 720
step = total_in_file // self.num_target_angles

sino = f_sino['projs'][::step, :, 0].astype(np.float32)
sino = sino[:self.num_target_angles, :]
f_sino.close()

f_gt = h5py.File(self.gt_files[index], 'r')
gt = f_gt['volume'][0, :, :].astype(np.float32)
f_gt.close()

input_tensor = torch.from_numpy(sino).unsqueeze(0)
target_tensor = torch.from_numpy(gt).unsqueeze(0)

return input_tensor, target_tensor

#Number of angles
n_angles = 360

#Geometry of the experiment
geometry = ctgeo.Geometry(
image_shape=[1, 512, 512],
image_size=[300 / 512, 300, 300],
detector_shape=[1, 900],
detector_size=[1, 900],
dso=575, dsd=1050, mode="fan",
angles=np.linspace(0, 2 * np.pi, n_angles, endpoint=False),
)

params = LIONParameter()
params.geometry = geometry
params.path_to_dataset = OUTPUT_DIR
params.max_samples = 30

#30 samples
samples = FoamLike(mode="all", parameters=params)


#Add noise to the sample sinograms
sigma_paper = 5
sigma_blurred_paper = 0.8
ks = int(sigma_blurred_paper * 3) * 2 + 1

noisy_list_y = []
target_list = []

for i in range(30):
_, target = samples[i]

sino_clean, _ = samples[i]
y=ct_utils._sinogram_add_noise(sino_clean, I0=10000, sigma=sigma_paper, sigma_blur=sigma_blurred_paper, ks_value=3)
noisy_list_y.append(y.view(1, 360, 900))
target_list.append(target.view(1, 512, 512))
if i == 0:
print(f"Min sino_clean: {sino_clean.min().item():.4f}")
print(f"Max sino_clean: {sino_clean.max().item():.4f}")

sino_tensor_y = torch.stack(noisy_list_y)
target_tensor = torch.stack(target_list)
train_data = data_utils.TensorDataset(sino_tensor_y, target_tensor)
dataloader = DataLoader(train_data, batch_size=5, shuffle=True)

#Noise2Inverse
model = UNet().to(device)
optimizer = Adam(model.parameters(), lr=1e-4)
loss_fn = nn.MSELoss()

n2i_params = Noise2InverseSolver.default_parameters()
n2i_params.splits = 4
n2i_params.algo = fdk
n2i_params.strategy = Noise2InverseSolver.X_one_strategy(n2i_params.splits)

solver = Noise2InverseSolver(model, optimizer, loss_fn, n2i_params, geometry, verbose=True, device=device)

solver.set_training(dataloader)
solver.train(500)
solver.save_final_results("final_model_N2I.pt", SAVE_DIR)

20 changes: 20 additions & 0 deletions scripts/hackathon_scripts/synerby26/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
This repository contains a complete tutorial for generating synthetic foam data and its subsequent reconstruction and denoising using the Noise2Inverse algorithm with the LION library.

Tutorial Structure
The workflow is divided into two main steps to ensure version compatibility:

- Creation of analytical bubble structures (Foam_env).
- Training a neural network for self-supervised denoising (lion_env).

Create the environment with the specific version of Python for generating the Dataset, activate the enviroment and instal the necessary stuff:
conda create -n foam_env python=3.9
conda activate foam_env
pip install foam-ct-phantom h5py numpy torch

For installing LION:
git clone https://github.com/CambridgeCIA/LION.git
cd LION
git submodule update --init --recursive # Legacy: for MSD_pytorch_
conda env create --file=env_base.yml --name=lion # You can change 'lion' to a different env name
conda activate lion
pip install .
Loading