[1]:
# -*- coding: utf-8 -*-
# Copyright 2024 Till Leissner
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Authored by: Till Leissner (University of Southern Denmark)
# Edited by: Margaret Duff (Science and Technology Facilities Council - UKRI )
#
# We acknowledge support from the ESS Lighthouse on Hard Materials in 3D, SOLID, funded by the Danish Agency for Science and Higher Education (grant No. 8144-00002B).
[2]:
### General imports
import os
import numpy as np
import glob
import matplotlib.pyplot as plt
#import json
from ipywidgets import interact
import ipywidgets as widgets
### Import all CIL components needed
import cil
from cil.framework import ImageData, ImageGeometry
from cil.plugins import tigre
from cil.io import TIFFWriter, TIFFStackReader
from cil.processors import CentreOfRotationCorrector, Binner, TransmissionAbsorptionConverter,RingRemover, Slicer
from cil.recon import FDK
from cil.utilities.display import show2D, show_geometry
### Import custom helper functions
import bruker2cil as bc
This notebook has been tested with CIL version 24.0.0
[3]:
print(cil.__version__)
24.0.0
Introduction#
This notebook showcases the volume reconstruction of microCT projection data obtained with a Bruker Skyscan 2214 using a flat panel detector and a source voltage of 125 kV at 69 µA. Projections are available as 16-bit tiffs.
The image normalisation
has been already applied during the data aquisition.
All files created during a scan are located in a single flat folder.
Four test data sets are provided:
01-switch-small: a 360 deg scan of a pushbutton switch (binning 4x4)
02-switch-large: a 360 deg scan of a pushbutton switch (no binning)
03-coffee: a 180 deg scan of a coffee bean
04-citron: a 180 deg scan of a citron
The data sets are available a compressed zip archives on
To run this notebook, we recommend making a new directory samples and then, in that directory, downloading and unpacking 01-switch-small e.g. using wget https://zenodo.org/records/11258475/files/01-switch-small.zip and running unzip 01-switch-small.zip.
Example reconstructions of the other datasets can be found in te folder extra_example_notebooks.
Set variables and paths#
To get started a few path variables have to be defined:
[4]:
datadir = './samples/01-switch-small' # Path to the dataset
dataset_prefix = '001_' # Filename prefix
# Usually you do not need to change the following.
infofile = os.path.join(datadir,dataset_prefix+'.info')
logfile = os.path.join(datadir,dataset_prefix+'.log')
Create acquisition geometry#
The function set_geometry will parse the “.info” and the “.log” files, determine the scan parameters and create the corresponding CIL acquisition geometry.
[5]:
#ag = bc.set_geometry(logfile,infofile=infofile) # This will use the info file to determine the actually achieved projection angles
ag = bc.set_geometry(logfile) # This will use the angular step size from the log file to determine the projection angles
show_geometry(ag)
[5]:
<cil.utilities.display.show_geometry at 0x7fbf7c072480>
Read files#
The helper function get_filelist will create a list of projection files. Further I check if the number of images corresponds to the number of angles obtained from the .info file. Afterwards the images are loaded using the CIL TIFFStackReader class and the projections and sinograms visualised.
[6]:
filelist = bc.get_filelist(datadir,dataset_prefix)
print(filelist)
if len(ag.angles) != len(filelist):
print('Warning: Number of files does not correspond to number of rotational steps!')
['./samples/01-switch-small/001_00000000.tif', './samples/01-switch-small/001_00000001.tif', './samples/01-switch-small/001_00000002.tif', './samples/01-switch-small/001_00000003.tif', './samples/01-switch-small/001_00000004.tif', './samples/01-switch-small/001_00000005.tif', './samples/01-switch-small/001_00000006.tif', './samples/01-switch-small/001_00000007.tif', './samples/01-switch-small/001_00000008.tif', './samples/01-switch-small/001_00000009.tif', './samples/01-switch-small/001_00000010.tif', './samples/01-switch-small/001_00000011.tif', './samples/01-switch-small/001_00000012.tif', './samples/01-switch-small/001_00000013.tif', './samples/01-switch-small/001_00000014.tif', './samples/01-switch-small/001_00000015.tif', './samples/01-switch-small/001_00000016.tif', './samples/01-switch-small/001_00000017.tif', './samples/01-switch-small/001_00000018.tif', './samples/01-switch-small/001_00000019.tif', './samples/01-switch-small/001_00000020.tif', './samples/01-switch-small/001_00000021.tif', './samples/01-switch-small/001_00000022.tif', './samples/01-switch-small/001_00000023.tif', './samples/01-switch-small/001_00000024.tif', './samples/01-switch-small/001_00000025.tif', './samples/01-switch-small/001_00000026.tif', './samples/01-switch-small/001_00000027.tif', './samples/01-switch-small/001_00000028.tif', './samples/01-switch-small/001_00000029.tif', './samples/01-switch-small/001_00000030.tif', './samples/01-switch-small/001_00000031.tif', './samples/01-switch-small/001_00000032.tif', './samples/01-switch-small/001_00000033.tif', './samples/01-switch-small/001_00000034.tif', './samples/01-switch-small/001_00000035.tif', './samples/01-switch-small/001_00000036.tif', './samples/01-switch-small/001_00000037.tif', './samples/01-switch-small/001_00000038.tif', './samples/01-switch-small/001_00000039.tif', './samples/01-switch-small/001_00000040.tif', './samples/01-switch-small/001_00000041.tif', './samples/01-switch-small/001_00000042.tif', './samples/01-switch-small/001_00000043.tif', './samples/01-switch-small/001_00000044.tif', './samples/01-switch-small/001_00000045.tif', './samples/01-switch-small/001_00000046.tif', './samples/01-switch-small/001_00000047.tif', './samples/01-switch-small/001_00000048.tif', './samples/01-switch-small/001_00000049.tif', './samples/01-switch-small/001_00000050.tif', './samples/01-switch-small/001_00000051.tif', './samples/01-switch-small/001_00000052.tif', './samples/01-switch-small/001_00000053.tif', './samples/01-switch-small/001_00000054.tif', './samples/01-switch-small/001_00000055.tif', './samples/01-switch-small/001_00000056.tif', './samples/01-switch-small/001_00000057.tif', './samples/01-switch-small/001_00000058.tif', './samples/01-switch-small/001_00000059.tif', './samples/01-switch-small/001_00000060.tif', './samples/01-switch-small/001_00000061.tif', './samples/01-switch-small/001_00000062.tif', './samples/01-switch-small/001_00000063.tif', './samples/01-switch-small/001_00000064.tif', './samples/01-switch-small/001_00000065.tif', './samples/01-switch-small/001_00000066.tif', './samples/01-switch-small/001_00000067.tif', './samples/01-switch-small/001_00000068.tif', './samples/01-switch-small/001_00000069.tif', './samples/01-switch-small/001_00000070.tif', './samples/01-switch-small/001_00000071.tif', './samples/01-switch-small/001_00000072.tif', './samples/01-switch-small/001_00000073.tif', './samples/01-switch-small/001_00000074.tif', './samples/01-switch-small/001_00000075.tif', './samples/01-switch-small/001_00000076.tif', './samples/01-switch-small/001_00000077.tif', './samples/01-switch-small/001_00000078.tif', './samples/01-switch-small/001_00000079.tif', './samples/01-switch-small/001_00000080.tif', './samples/01-switch-small/001_00000081.tif', './samples/01-switch-small/001_00000082.tif', './samples/01-switch-small/001_00000083.tif', './samples/01-switch-small/001_00000084.tif', './samples/01-switch-small/001_00000085.tif', './samples/01-switch-small/001_00000086.tif', './samples/01-switch-small/001_00000087.tif', './samples/01-switch-small/001_00000088.tif', './samples/01-switch-small/001_00000089.tif', './samples/01-switch-small/001_00000090.tif', './samples/01-switch-small/001_00000091.tif', './samples/01-switch-small/001_00000092.tif', './samples/01-switch-small/001_00000093.tif', './samples/01-switch-small/001_00000094.tif', './samples/01-switch-small/001_00000095.tif', './samples/01-switch-small/001_00000096.tif', './samples/01-switch-small/001_00000097.tif', './samples/01-switch-small/001_00000098.tif', './samples/01-switch-small/001_00000099.tif', './samples/01-switch-small/001_00000100.tif', './samples/01-switch-small/001_00000101.tif', './samples/01-switch-small/001_00000102.tif', './samples/01-switch-small/001_00000103.tif', './samples/01-switch-small/001_00000104.tif', './samples/01-switch-small/001_00000105.tif', './samples/01-switch-small/001_00000106.tif', './samples/01-switch-small/001_00000107.tif', './samples/01-switch-small/001_00000108.tif', './samples/01-switch-small/001_00000109.tif', './samples/01-switch-small/001_00000110.tif', './samples/01-switch-small/001_00000111.tif', './samples/01-switch-small/001_00000112.tif', './samples/01-switch-small/001_00000113.tif', './samples/01-switch-small/001_00000114.tif', './samples/01-switch-small/001_00000115.tif', './samples/01-switch-small/001_00000116.tif', './samples/01-switch-small/001_00000117.tif', './samples/01-switch-small/001_00000118.tif', './samples/01-switch-small/001_00000119.tif', './samples/01-switch-small/001_00000120.tif', './samples/01-switch-small/001_00000121.tif', './samples/01-switch-small/001_00000122.tif', './samples/01-switch-small/001_00000123.tif', './samples/01-switch-small/001_00000124.tif', './samples/01-switch-small/001_00000125.tif', './samples/01-switch-small/001_00000126.tif', './samples/01-switch-small/001_00000127.tif', './samples/01-switch-small/001_00000128.tif', './samples/01-switch-small/001_00000129.tif', './samples/01-switch-small/001_00000130.tif', './samples/01-switch-small/001_00000131.tif', './samples/01-switch-small/001_00000132.tif', './samples/01-switch-small/001_00000133.tif', './samples/01-switch-small/001_00000134.tif', './samples/01-switch-small/001_00000135.tif', './samples/01-switch-small/001_00000136.tif', './samples/01-switch-small/001_00000137.tif', './samples/01-switch-small/001_00000138.tif', './samples/01-switch-small/001_00000139.tif', './samples/01-switch-small/001_00000140.tif', './samples/01-switch-small/001_00000141.tif', './samples/01-switch-small/001_00000142.tif', './samples/01-switch-small/001_00000143.tif', './samples/01-switch-small/001_00000144.tif', './samples/01-switch-small/001_00000145.tif', './samples/01-switch-small/001_00000146.tif', './samples/01-switch-small/001_00000147.tif', './samples/01-switch-small/001_00000148.tif', './samples/01-switch-small/001_00000149.tif', './samples/01-switch-small/001_00000150.tif', './samples/01-switch-small/001_00000151.tif', './samples/01-switch-small/001_00000152.tif', './samples/01-switch-small/001_00000153.tif', './samples/01-switch-small/001_00000154.tif', './samples/01-switch-small/001_00000155.tif', './samples/01-switch-small/001_00000156.tif', './samples/01-switch-small/001_00000157.tif', './samples/01-switch-small/001_00000158.tif', './samples/01-switch-small/001_00000159.tif', './samples/01-switch-small/001_00000160.tif', './samples/01-switch-small/001_00000161.tif', './samples/01-switch-small/001_00000162.tif', './samples/01-switch-small/001_00000163.tif', './samples/01-switch-small/001_00000164.tif', './samples/01-switch-small/001_00000165.tif', './samples/01-switch-small/001_00000166.tif', './samples/01-switch-small/001_00000167.tif', './samples/01-switch-small/001_00000168.tif', './samples/01-switch-small/001_00000169.tif', './samples/01-switch-small/001_00000170.tif', './samples/01-switch-small/001_00000171.tif', './samples/01-switch-small/001_00000172.tif', './samples/01-switch-small/001_00000173.tif', './samples/01-switch-small/001_00000174.tif', './samples/01-switch-small/001_00000175.tif', './samples/01-switch-small/001_00000176.tif', './samples/01-switch-small/001_00000177.tif', './samples/01-switch-small/001_00000178.tif', './samples/01-switch-small/001_00000179.tif', './samples/01-switch-small/001_00000180.tif', './samples/01-switch-small/001_00000181.tif', './samples/01-switch-small/001_00000182.tif', './samples/01-switch-small/001_00000183.tif', './samples/01-switch-small/001_00000184.tif', './samples/01-switch-small/001_00000185.tif', './samples/01-switch-small/001_00000186.tif', './samples/01-switch-small/001_00000187.tif', './samples/01-switch-small/001_00000188.tif', './samples/01-switch-small/001_00000189.tif', './samples/01-switch-small/001_00000190.tif', './samples/01-switch-small/001_00000191.tif', './samples/01-switch-small/001_00000192.tif', './samples/01-switch-small/001_00000193.tif', './samples/01-switch-small/001_00000194.tif', './samples/01-switch-small/001_00000195.tif', './samples/01-switch-small/001_00000196.tif', './samples/01-switch-small/001_00000197.tif', './samples/01-switch-small/001_00000198.tif', './samples/01-switch-small/001_00000199.tif', './samples/01-switch-small/001_00000200.tif', './samples/01-switch-small/001_00000201.tif', './samples/01-switch-small/001_00000202.tif', './samples/01-switch-small/001_00000203.tif', './samples/01-switch-small/001_00000204.tif', './samples/01-switch-small/001_00000205.tif', './samples/01-switch-small/001_00000206.tif', './samples/01-switch-small/001_00000207.tif', './samples/01-switch-small/001_00000208.tif', './samples/01-switch-small/001_00000209.tif', './samples/01-switch-small/001_00000210.tif', './samples/01-switch-small/001_00000211.tif', './samples/01-switch-small/001_00000212.tif', './samples/01-switch-small/001_00000213.tif', './samples/01-switch-small/001_00000214.tif', './samples/01-switch-small/001_00000215.tif', './samples/01-switch-small/001_00000216.tif', './samples/01-switch-small/001_00000217.tif', './samples/01-switch-small/001_00000218.tif', './samples/01-switch-small/001_00000219.tif', './samples/01-switch-small/001_00000220.tif', './samples/01-switch-small/001_00000221.tif', './samples/01-switch-small/001_00000222.tif', './samples/01-switch-small/001_00000223.tif', './samples/01-switch-small/001_00000224.tif', './samples/01-switch-small/001_00000225.tif', './samples/01-switch-small/001_00000226.tif', './samples/01-switch-small/001_00000227.tif', './samples/01-switch-small/001_00000228.tif', './samples/01-switch-small/001_00000229.tif', './samples/01-switch-small/001_00000230.tif', './samples/01-switch-small/001_00000231.tif', './samples/01-switch-small/001_00000232.tif', './samples/01-switch-small/001_00000233.tif', './samples/01-switch-small/001_00000234.tif', './samples/01-switch-small/001_00000235.tif', './samples/01-switch-small/001_00000236.tif', './samples/01-switch-small/001_00000237.tif', './samples/01-switch-small/001_00000238.tif', './samples/01-switch-small/001_00000239.tif', './samples/01-switch-small/001_00000240.tif', './samples/01-switch-small/001_00000241.tif', './samples/01-switch-small/001_00000242.tif', './samples/01-switch-small/001_00000243.tif', './samples/01-switch-small/001_00000244.tif', './samples/01-switch-small/001_00000245.tif', './samples/01-switch-small/001_00000246.tif', './samples/01-switch-small/001_00000247.tif', './samples/01-switch-small/001_00000248.tif', './samples/01-switch-small/001_00000249.tif', './samples/01-switch-small/001_00000250.tif', './samples/01-switch-small/001_00000251.tif', './samples/01-switch-small/001_00000252.tif', './samples/01-switch-small/001_00000253.tif', './samples/01-switch-small/001_00000254.tif', './samples/01-switch-small/001_00000255.tif', './samples/01-switch-small/001_00000256.tif', './samples/01-switch-small/001_00000257.tif', './samples/01-switch-small/001_00000258.tif', './samples/01-switch-small/001_00000259.tif', './samples/01-switch-small/001_00000260.tif', './samples/01-switch-small/001_00000261.tif', './samples/01-switch-small/001_00000262.tif', './samples/01-switch-small/001_00000263.tif', './samples/01-switch-small/001_00000264.tif', './samples/01-switch-small/001_00000265.tif', './samples/01-switch-small/001_00000266.tif', './samples/01-switch-small/001_00000267.tif', './samples/01-switch-small/001_00000268.tif', './samples/01-switch-small/001_00000269.tif', './samples/01-switch-small/001_00000270.tif', './samples/01-switch-small/001_00000271.tif', './samples/01-switch-small/001_00000272.tif', './samples/01-switch-small/001_00000273.tif', './samples/01-switch-small/001_00000274.tif', './samples/01-switch-small/001_00000275.tif', './samples/01-switch-small/001_00000276.tif', './samples/01-switch-small/001_00000277.tif', './samples/01-switch-small/001_00000278.tif', './samples/01-switch-small/001_00000279.tif', './samples/01-switch-small/001_00000280.tif', './samples/01-switch-small/001_00000281.tif', './samples/01-switch-small/001_00000282.tif', './samples/01-switch-small/001_00000283.tif', './samples/01-switch-small/001_00000284.tif', './samples/01-switch-small/001_00000285.tif', './samples/01-switch-small/001_00000286.tif', './samples/01-switch-small/001_00000287.tif', './samples/01-switch-small/001_00000288.tif', './samples/01-switch-small/001_00000289.tif', './samples/01-switch-small/001_00000290.tif', './samples/01-switch-small/001_00000291.tif', './samples/01-switch-small/001_00000292.tif', './samples/01-switch-small/001_00000293.tif', './samples/01-switch-small/001_00000294.tif', './samples/01-switch-small/001_00000295.tif', './samples/01-switch-small/001_00000296.tif', './samples/01-switch-small/001_00000297.tif', './samples/01-switch-small/001_00000298.tif', './samples/01-switch-small/001_00000299.tif', './samples/01-switch-small/001_00000300.tif', './samples/01-switch-small/001_00000301.tif', './samples/01-switch-small/001_00000302.tif', './samples/01-switch-small/001_00000303.tif', './samples/01-switch-small/001_00000304.tif', './samples/01-switch-small/001_00000305.tif', './samples/01-switch-small/001_00000306.tif', './samples/01-switch-small/001_00000307.tif', './samples/01-switch-small/001_00000308.tif', './samples/01-switch-small/001_00000309.tif', './samples/01-switch-small/001_00000310.tif', './samples/01-switch-small/001_00000311.tif', './samples/01-switch-small/001_00000312.tif', './samples/01-switch-small/001_00000313.tif', './samples/01-switch-small/001_00000314.tif', './samples/01-switch-small/001_00000315.tif', './samples/01-switch-small/001_00000316.tif', './samples/01-switch-small/001_00000317.tif', './samples/01-switch-small/001_00000318.tif', './samples/01-switch-small/001_00000319.tif', './samples/01-switch-small/001_00000320.tif', './samples/01-switch-small/001_00000321.tif', './samples/01-switch-small/001_00000322.tif', './samples/01-switch-small/001_00000323.tif', './samples/01-switch-small/001_00000324.tif', './samples/01-switch-small/001_00000325.tif', './samples/01-switch-small/001_00000326.tif', './samples/01-switch-small/001_00000327.tif', './samples/01-switch-small/001_00000328.tif', './samples/01-switch-small/001_00000329.tif', './samples/01-switch-small/001_00000330.tif', './samples/01-switch-small/001_00000331.tif', './samples/01-switch-small/001_00000332.tif', './samples/01-switch-small/001_00000333.tif', './samples/01-switch-small/001_00000334.tif', './samples/01-switch-small/001_00000335.tif', './samples/01-switch-small/001_00000336.tif', './samples/01-switch-small/001_00000337.tif', './samples/01-switch-small/001_00000338.tif', './samples/01-switch-small/001_00000339.tif', './samples/01-switch-small/001_00000340.tif', './samples/01-switch-small/001_00000341.tif', './samples/01-switch-small/001_00000342.tif', './samples/01-switch-small/001_00000343.tif', './samples/01-switch-small/001_00000344.tif', './samples/01-switch-small/001_00000345.tif', './samples/01-switch-small/001_00000346.tif', './samples/01-switch-small/001_00000347.tif', './samples/01-switch-small/001_00000348.tif', './samples/01-switch-small/001_00000349.tif', './samples/01-switch-small/001_00000350.tif', './samples/01-switch-small/001_00000351.tif', './samples/01-switch-small/001_00000352.tif', './samples/01-switch-small/001_00000353.tif', './samples/01-switch-small/001_00000354.tif', './samples/01-switch-small/001_00000355.tif', './samples/01-switch-small/001_00000356.tif', './samples/01-switch-small/001_00000357.tif', './samples/01-switch-small/001_00000358.tif', './samples/01-switch-small/001_00000359.tif', './samples/01-switch-small/001_00000360.tif', './samples/01-switch-small/001_00000361.tif', './samples/01-switch-small/001_00000362.tif', './samples/01-switch-small/001_00000363.tif', './samples/01-switch-small/001_00000364.tif', './samples/01-switch-small/001_00000365.tif', './samples/01-switch-small/001_00000366.tif', './samples/01-switch-small/001_00000367.tif', './samples/01-switch-small/001_00000368.tif', './samples/01-switch-small/001_00000369.tif', './samples/01-switch-small/001_00000370.tif', './samples/01-switch-small/001_00000371.tif', './samples/01-switch-small/001_00000372.tif', './samples/01-switch-small/001_00000373.tif', './samples/01-switch-small/001_00000374.tif', './samples/01-switch-small/001_00000375.tif', './samples/01-switch-small/001_00000376.tif', './samples/01-switch-small/001_00000377.tif', './samples/01-switch-small/001_00000378.tif', './samples/01-switch-small/001_00000379.tif', './samples/01-switch-small/001_00000380.tif', './samples/01-switch-small/001_00000381.tif', './samples/01-switch-small/001_00000382.tif', './samples/01-switch-small/001_00000383.tif', './samples/01-switch-small/001_00000384.tif', './samples/01-switch-small/001_00000385.tif', './samples/01-switch-small/001_00000386.tif', './samples/01-switch-small/001_00000387.tif', './samples/01-switch-small/001_00000388.tif', './samples/01-switch-small/001_00000389.tif', './samples/01-switch-small/001_00000390.tif', './samples/01-switch-small/001_00000391.tif', './samples/01-switch-small/001_00000392.tif', './samples/01-switch-small/001_00000393.tif', './samples/01-switch-small/001_00000394.tif', './samples/01-switch-small/001_00000395.tif', './samples/01-switch-small/001_00000396.tif', './samples/01-switch-small/001_00000397.tif', './samples/01-switch-small/001_00000398.tif', './samples/01-switch-small/001_00000399.tif', './samples/01-switch-small/001_00000400.tif', './samples/01-switch-small/001_00000401.tif', './samples/01-switch-small/001_00000402.tif', './samples/01-switch-small/001_00000403.tif', './samples/01-switch-small/001_00000404.tif', './samples/01-switch-small/001_00000405.tif', './samples/01-switch-small/001_00000406.tif', './samples/01-switch-small/001_00000407.tif', './samples/01-switch-small/001_00000408.tif', './samples/01-switch-small/001_00000409.tif', './samples/01-switch-small/001_00000410.tif', './samples/01-switch-small/001_00000411.tif', './samples/01-switch-small/001_00000412.tif', './samples/01-switch-small/001_00000413.tif', './samples/01-switch-small/001_00000414.tif', './samples/01-switch-small/001_00000415.tif', './samples/01-switch-small/001_00000416.tif', './samples/01-switch-small/001_00000417.tif', './samples/01-switch-small/001_00000418.tif', './samples/01-switch-small/001_00000419.tif', './samples/01-switch-small/001_00000420.tif', './samples/01-switch-small/001_00000421.tif', './samples/01-switch-small/001_00000422.tif', './samples/01-switch-small/001_00000423.tif', './samples/01-switch-small/001_00000424.tif', './samples/01-switch-small/001_00000425.tif', './samples/01-switch-small/001_00000426.tif', './samples/01-switch-small/001_00000427.tif', './samples/01-switch-small/001_00000428.tif', './samples/01-switch-small/001_00000429.tif', './samples/01-switch-small/001_00000430.tif', './samples/01-switch-small/001_00000431.tif', './samples/01-switch-small/001_00000432.tif', './samples/01-switch-small/001_00000433.tif', './samples/01-switch-small/001_00000434.tif', './samples/01-switch-small/001_00000435.tif', './samples/01-switch-small/001_00000436.tif', './samples/01-switch-small/001_00000437.tif', './samples/01-switch-small/001_00000438.tif', './samples/01-switch-small/001_00000439.tif', './samples/01-switch-small/001_00000440.tif', './samples/01-switch-small/001_00000441.tif', './samples/01-switch-small/001_00000442.tif', './samples/01-switch-small/001_00000443.tif', './samples/01-switch-small/001_00000444.tif', './samples/01-switch-small/001_00000445.tif', './samples/01-switch-small/001_00000446.tif', './samples/01-switch-small/001_00000447.tif', './samples/01-switch-small/001_00000448.tif', './samples/01-switch-small/001_00000449.tif', './samples/01-switch-small/001_00000450.tif']
[7]:
reader = TIFFStackReader(file_name=filelist)
proj = reader.read_as_AcquisitionData(ag)
[8]:
fig = show2D(proj, slice_list=[('angle',0),('vertical', np.floor_divide(proj.shape[1],2))], size=(10,10), num_cols=2, cmap="gray", fix_range=[(0,60000),(0,20000)])
Data processing#
In the following a few CIL processors can be applied.
Optional: Apply Centre of Rotation Corrector#
Note, by setting the logging level to DEBUG the centre of rotation corrector prints out information on what it is doing. The plots display a measure of image sharpness (lower the better) against centre of rotation shift
[9]:
### Turn this on for more info
import logging
logging.basicConfig(level=logging.WARNING)
cil_log_level = logging.getLogger('cil.processors')
cil_log_level.setLevel(logging.DEBUG)
processor = CentreOfRotationCorrector.image_sharpness(slice_index='centre', backend='tigre')
processor.set_input(proj)
processor.get_output(out=proj)
DEBUG:cil.processors.CofR_image_sharpness:Initial search:
DEBUG:cil.processors.CofR_image_sharpness:search range is 191
DEBUG:cil.processors.CofR_image_sharpness:initial binning is 6
DEBUG:cil.processors.CofR_image_sharpness:fine search starting at 0.030298
DEBUG:cil.processors.CofR_image_sharpness:GSS between -0.015702 and 0.076297
INFO:cil.processors.CofR_image_sharpness:evaluated 17 points
INFO:cil.processors.CofR_image_sharpness:Centre of rotation correction found using image_sharpness
INFO:cil.processors.CofR_image_sharpness:backend FBP/FDK tigre
INFO:cil.processors.CofR_image_sharpness:Calculated from slice: centre
INFO:cil.processors.CofR_image_sharpness:Centre of rotation shift = 0.727376 pixels
INFO:cil.processors.CofR_image_sharpness:Centre of rotation shift = 0.016729 units at the object
INFO:cil.processors.CofR_image_sharpness:Return new dataset with centred geometry
[9]:
<cil.framework.framework.AcquisitionData at 0x7fbf7c15a4e0>
Optional: Slicing#
This will remove projection data that does not contain any information. This will save computational effort.
[10]:
roi = {'horizontal':(300,-300),'angle':(0,-1)} # The first and the last slice (0, and 360 deg) are equal. To avoid artefacts, the last slice is removed.
processor = Slicer(roi)
processor.set_input(proj)
proj = processor.get_output()
Optional: Ring artefact removal#
[11]:
#processor = RingRemover(decNum=4, wname='db35', sigma=1.5, info=True)
#processor.set_input(proj)
#proj = processor.get_output()
Optional: Data binning#
Useful for large datasets to reduce memory and computational expense. At the cost of potential image quality.
[12]:
#roi = {'horizontal':(None,None,4),'vertical':(None,None,4)}
#processor = Binner(roi)
#processor.set_input(proj)
#proj = processor.get_output()
Let’s plot the data set after applying of the processors:
[13]:
fig = show2D(proj, slice_list=[('angle',0),('vertical', np.floor_divide(proj.shape[1],2))], size=(10,3), num_cols=2, cmap="gray", fix_range=[(0,60000),(0,20000)])
Prepare back-projection#
In this section the following operations are applied to the data set:
The first vertical slices typically don’t contain anything except air. The mean grey value of this volume is used as background intensity. The dataset is dived by this value, such that “air” will have an transmission coefficient of 1.
The data will be converted from transmission to absorption data.
The correct dataset order is ensured.
The CIL image geometry class is created.
[14]:
#Plot histogram
plt.hist(proj.as_array().flatten(),bins=256);
plt.semilogy()
print(f'Min grey value {proj.min()}')
print(f'Max grey value {proj.max()}')
Min grey value 1675.0
Max grey value 56836.0
[15]:
# Substract Background
background = proj.get_slice(vertical=20, force=True).mean()
proj /= background
[16]:
# Prepare data for reconstruction
proj = TransmissionAbsorptionConverter(min_intensity=1e-6)(proj)
proj.reorder(order='tigre')
ig = proj.geometry.get_ImageGeometry()
Review projection data before running the recontruction#
[17]:
# Let's summarize the used geometries before we start the reconstruction.
print('Acquisition geometry:\n',ag,end='\n\n')
print('Projection geometry:\n',proj,end='\n\n')
print('Image geometry:\n',ig)
Acquisition geometry:
3D Cone-beam tomography
System configuration:
Source position: [ 0. , -98.706, 0. ]
Rotation axis position: [0., 0., 0.]
Rotation axis direction: [0., 0., 1.]
Detector position: [ 0. , 222.306, 0. ]
Detector direction x: [1., 0., 0.]
Detector direction y: [0., 0., 1.]
Panel configuration:
Number of pixels: [764 486]
Pixel size: [0.0748 0.0748]
Pixel origin: bottom-left
Channel configuration:
Number of channels: 1
Acquisition description:
Number of positions: 451
Angles 0-9 in degrees: [0. , 0.8, 1.6, 2.4, 3.2, 4. , 4.8, 5.6, 6.4, 7.2]
Angles 441-450 in degrees: [352.8, 353.6, 354.4, 355.2, 356. , 356.8, 357.6, 358.4, 359.2, 360. ]
Full angular array can be accessed with acquisition_data.geometry.angles
Distances in units: units distance
Projection geometry:
Number of dimensions: 3
Shape: (450, 486, 164)
Axis labels: ('angle', 'vertical', 'horizontal')
Image geometry:
Number of channels: 1
channel_spacing: 1.0
voxel_num : x164,y164,z486
voxel_size : x0.02299979066203132,y0.02299979066203132,z0.02299979066203132
center : x0,y0,z0
[18]:
print(f'Min grey value {proj.min()}')
print(f'Max grey value {proj.max()}')
show2D(proj, slice_list=[('angle',0),('vertical', np.floor_divide(proj.shape[1],2))], size=(10,3))
Min grey value -0.01897411234676838
Max grey value 3.505382776260376
[18]:
<cil.utilities.display.show2D at 0x7fbf73e8ae70>
[19]:
plt.hist(proj.as_array().flatten(),bins=256);
plt.semilogy();
Perform reconstruction#
[20]:
fdk = FDK(proj, ig)
recon = fdk.run()
FDK recon
Input Data:
angle: 450
vertical: 486
horizontal: 164
Reconstruction Volume:
vertical: 486
horizontal_y: 164
horizontal_x: 164
Reconstruction Options:
Backend: tigre
Filter: ram-lak
Filter cut-off frequency: 1.0
FFT order: 9
Filter_inplace: False
Display results#
[21]:
show2D(recon, slice_list= \
[('horizontal_x', np.floor_divide(ig.shape[2],2)), \
('horizontal_y', np.floor_divide(ig.shape[1],2)), \
('vertical', np.floor_divide(ig.shape[0],2))], \
num_cols=3, \
cmap="grey",
fix_range=(-0.0,2.7),
size=(15,6))
[21]:
<cil.utilities.display.show2D at 0x7fbf69ae6cf0>
[22]:
# Interactive plotting
def plot_results(recon,x,y,z):
show2D(recon, slice_list= \
[('horizontal_x', x), \
('horizontal_y', y), \
('vertical', z)], \
num_cols=3, \
cmap="grey",
fix_range=(-0.0,2.7),
size=(15,6))
interact(plot_results,
recon = widgets.fixed(recon), \
x = widgets.IntSlider(value=np.floor_divide(ig.shape[2],2), min=0, max=ig.shape[2], step=1), \
y = widgets.IntSlider(value=np.floor_divide(ig.shape[1],2), min=0, max=ig.shape[1], step=1), \
z = widgets.IntSlider(value=np.floor_divide(ig.shape[0],2), min=0, max=ig.shape[0], step=1))
[22]:
<function __main__.plot_results(recon, x, y, z)>
Optional: Save results as tiff files#
[23]:
# Save data to a subfolder of the data folder
subfolder = dataset_prefix+'Rec'
TIFFWriter(data=recon, file_name=os.path.join(datadir,subfolder,dataset_prefix),compression='uint8').write()
Optional: Save results as json files#
[24]:
import json
# Save to a JSON file
with open(os.path.join(datadir,subfolder,dataset_prefix+'_params.json'), 'w') as fp:
json.dump(bc.get_scanparams(logfile), fp, indent=4)
The notebook ‘compare-CIL-NRecon.ipynb’ allows you to compare the results from this showcase to the results obtained by the instrument software NRecon.
[ ]: