# SyneRBI Hackathon https://ukri.zoom.us/j/96748085345 Passcode 328111 SyneRBI challenge repo https://github.com/TomographicImaging/SyneRBI-Challenge Fairly recent Docker image with SIRF+CIL (both master) `docker pull harbor.stfc.ac.uk/imaging-tomography/sirfcil:dev-jupyterhub-gpu` ## Aims - Optimising the use of STIR GPU capabilities via `parallelproj` for reducing the computation time. - Evaluation metrics for the submissions to the challenge, see [Hackathon-000-Stochastic-QualityMetrics](https://github.com/TomographicImaging/Hackathon-000-Stochastic-QualityMetrics) - Working with scanners other than currently supported Siemens Biograph mMR and GE Signa. - Preparation of data (PET and mu-maps) as well as ROIs for evaluation. - Contributing to CCP SyneRBI website (experience with WordPress will be acquired). ## Groups Team | Topic ---- | ------ Edo | Quality metrics, https://github.com/TomographicImaging/SyneRBI-Challenge/tree/recon_with_metrics/metrics ~~Website (Training matrix)~~ Edo & Margaret & Vaggelis?| Stochastic framework + quality metric callback + demonstration of CIL framework with SIRF on PET data Casper + Margaret | CIL callbacks [CIL#1659](https://github.com/TomographicImaging/CIL/pull/1659) Kris | SIRF release finalisation and STIR Array/cuvec Evgueni | Repackage the NEMA preprocessing from the SIRF exercise, https://github.com/SyneRBI/SIRF-Exercises/blob/master/notebooks/PET/reconstruct_measured_data.ipynb Daniel | Script to generate the ROI's for the NEMA phantom Vaggelis |?? Imraj |?? ## framework Main issue/epic: [SyneRBI-Challenge#1](https://github.com/TomographicImaging/SyneRBI-Challenge/issues/1) ~~+ CIL callbacks [CIL#1659](https://github.com/TomographicImaging/CIL/pull/1659) @Casper~~ + update `main.py` @Casper + [Stochastic-QualityMetrics](https://github.com/TomographicImaging/Hackathon-000-Stochastic-QualityMetrics) & example notebook @Edo/Margaret/Vaggelis + Examples of adapting the CIL algorithms class e.g. OSEM + Partitioner for SIRF PET data + running with `docker` ~~or `devcontainers`~~ [SuperBuild#718](https://github.com/SyneRBI/SIRF-SuperBuild/pull/718) @Casper + GitHub Action to evaluate metrics & update leaderboard @Casper + self-hosted runner @Casper/Edo + SIRF/CIL compat like https://github.com/TomographicImaging/CIL/issues/1522 - SIRF objective function to be compatible with CIL Functions ```python # Solve with Nesterov (Thorax case) initial = image.get_uniform_copy(0) alpha = 0.25 tmp_f = KullbackLeibler(b=noisy_data, eta = background_term, backend="numba") f1 = OperatorCompositionFunction(tmp_f, acq_model) f2 = RelativeDifferencePrior() f2.set_epsilon(1e-5) f2.set_penalisation_factor(alpha) f2.set_up(image) objective = f1 + f2 step_size = 0.5 fista = FISTA(initial = initial, f = objective, g = IndicatorBox(lower=0), step_size = step_size, update_objective_interval=50, max_iteration=500) fista.run(verbose=1) ``` - Same as above for SIRF prior. These are smooth priors (.gradient method) - Sampler new class to be tested with SIRF Acquisition Data - HermanMeyer is important - [Preconditioner](https://github.com/TomographicImaging/CIL/issues/1588) and [StepSize](https://github.com/TomographicImaging/CIL/issues/1592) are important for the paper. For the competition people can implement their own classes to do it for PET recon. - Test Stochastic framework for SIRF data ```python ## create list of funcs def list_of_functions(data, data_background, attn_factors, image): list_funcs = [] list_ops = [] for i in range(len(data)): fi = KullbackLeibler(b=data[i], eta = data_background[i], backend="numba") acq_model = pet.AcquisitionModelUsingRayTracingMatrix() acq_model.set_num_tangential_LORs(10) asm_attn = pet.AcquisitionSensitivityModel(attn_factors[i]) acq_model.set_acquisition_sensitivity(asm_attn) acq_model.set_up(data[i],image) list_ops.append(acq_model) list_funcs.append(OperatorCompositionFunction(fi, acq_model)) return list_funcs, list_ops num_subsets = 32 method = SequentialSampling(64, num_subsets) # split data, back, attn data_split = [noisy_data.get_subset(i) for i in method.partition_list] data_background_split = [background_term.get_subset(i) for i in method.partition_list] attn_factors_split = [attn_factors.get_subset(i) for i in method.partition_list] # create list of funcs list_func, list_ops = list_of_functions(data_split, data_background_split, attn_factors_split, image) # sampling method selection = RandomSampling(len(list_func), num_subsets, seed=40) # shuffle=True # callbacks (rse from fista for MANY its) cb = MetricsDiagnostics(fista.solution, metrics_dict={"rse":RSE}, verbose=1) num_epochs = 50 sg_func = SGFunction(list_func, selection=selection) step_size_ista = 0.1 # sg_func.dask = True sgd = ISTA(initial = initial, f = sg_func, step_size = step_size_ista, g=G, update_objective_interval = num_subsets, max_iteration = num_epochs * num_subsets) sgd.run(verbose=1, callback=[cb]) plt.figure() plt.semilogy(sg_func.data_passes, sgd.rse,label='SGD') plt.xlabel('data-pases') plt.ylabel(r'$\|\|x^{k}-x^{*}\|\|$') plt.legend() plt.grid() ``` + Hydra scripts (can show you what I did for stochastic) # Data - mMR NEMA https://zenodo.org/records/1304454