In- and output¶
A Qiber3D.Network
can either be created from from an image stack, or an already reconstructed source like a .mv3d
or .swc
file.
To load the network simply pass its path to Qiber3D.Network.load()
.
Based on the file suffix the corresponding part of Qiber3D.IO.load
is used.
Note
The examples presented here use the corresponding image stacks from figshare
doi:10.6084/m9.figshare.13655606.
The Qiber3D.helper.Example
class can be used to download the data easily.
microvascular_network.nd2
- FigID: 26211077 (1.06 GB)microvascular_network.tif
- FigID: 30771817 (1.06 GB)microvascular_network-C2.tif
- FigID: 30771877 (362 MB)microvascular_network-C2-reduced.tif
- FigID: 31106104 (40MB)
Note
To directly download the files on the commandline curl
can be used.
Just replace $(FigID)
with the number from the list above.
curl -X GET "https://api.figshare.com/v2/file/download/$(FigID)"
ND2 example¶
>>> import logging
>>> from Qiber3D import Network, config
>>> from Qiber3D.helper import Example, change_log_level
>>> config.log_level = change_log_level(logging.DEBUG) # This will show 3D renderings of the intermediate steps
>>> config.extract.nd2_channel_name = 'FITC'
>>> net_ex = Example.nd2()
>>> net = Network.load(net_ex)
Qiber3D_extract [INFO] Load image data from microvascular_network.nd2
Qiber3D_extract [INFO] Image voxel size: [1.230,1.230,2.500]
Qiber3D_extract [INFO] Median Filter (despeckle)
Qiber3D_extract [INFO] Z-Drop correction
Qiber3D_extract [INFO] Resample image to cubic voxels
Qiber3D_extract [INFO] Apply gaussian filter
Qiber3D_extract [INFO] Generate binary representation
Qiber3D_extract [INFO] Binary representation used a threshold of 4.9% (otsu)
Qiber3D_extract [INFO] Morph binary representation
Qiber3D_extract [INFO] reconstruct image
Qiber3D_reconstruct [INFO] Skeletonize image by thinning
Qiber3D_reconstruct [INFO] Euclidean distance transformation
Link up skeleton: 100%|██████████| 13/13 [00:15<00:00, 1.17s/it]
Qiber3D_reconstruct [INFO] Build Qiber3D.Network from the raw graph
Qiber3D_reconstruct [INFO] Cleaning Network
Qiber3D_reconstruct [INFO] Smooth Segments
>>> print(net)
Input file: microvascular_network.nd2
Number of fibers: 405 (clustered 109)
Number of segments: 966
Number of branch points: 327
Total length: 43192.45
Total volume: 5146410.65
Average radius: 5.770
Cylinder radius: 6.158
Bounding box volume: 683663872
A reconstructed network can quickly be saved with Qiber3D.Network.save()
.
Without arguments, just the reconstructed network is saved.
If the image stack at the different stages should be preserved set `save_steps
to True
.
Saving the reconstruction steps can consume a lot of space.
>>> net.save(save_steps=True)
Qiber3D_core [INFO] Network saved to microvascular_network.qiber
The created .qiber
can be loaded as any other supported file type.
>>> net = Network.load('microvascular_network.qiber')
TIFF example¶
The same example can be run using a .tif version of the same data.
Note
While the reduced dataset is the same subject, the reduced resolution and greyscale range will result in altered results.
>>> from Qiber3D import Network, config
>>> from Qiber3D.helper import Example
>>> config.extract.voxel_size = [1.2302, 1.2302, 2.5]
>>> config.extract.low_memory = True
>>> net_ex = Example.tiff()
>>> net = Network.load(net_ex, channel=1)
Qiber3D_extract [INFO] Load image data from microvascular_network.tif
Qiber3D_extract [INFO] Image voxel size: [1.230,1.230,2.500]
Qiber3D_extract [INFO] Median Filter (despeckle)
Qiber3D_extract [INFO] Z-Drop correction
Qiber3D_extract [INFO] Resample image to cubic voxels
Qiber3D_extract [INFO] Apply gaussian filter
Qiber3D_extract [INFO] Generate binary representation
Qiber3D_extract [INFO] Binary representation used a threshold of 4.9% (otsu)
Qiber3D_extract [INFO] Morph binary representation
Qiber3D_extract [INFO] reconstruct image
Qiber3D_reconstruct [INFO] Skeletonize image by thinning
Qiber3D_reconstruct [INFO] Euclidean distance transformation
Qiber3D_reconstruct [INFO] Build Qiber3D.Network from the raw graph
Qiber3D_reconstruct [INFO] Cleaning Network
Qiber3D_reconstruct [INFO] Smooth Segments
>>> print(net)
Input file: microvascular_network.tif
Number of fibers: 406 (clustered 111)
Number of segments: 971
Number of branch points: 329
Total length: 43241.93
Total volume: 5150823.10
Average radius: 5.775
Cylinder radius: 6.158
Bounding box volume: 683658224
A reconstructed network can saved as we did before with Qiber3D.Network.save()
.
The save function can be given a name for the save file.
>>> net.save('reconstructed_net.qiber')
Qiber3D_core [INFO] Network saved to reconstructed_net.qiber
Synthetic example¶
The settings for the different image filters can be accessed through the Qiber3D.config
module.
In next example the image to be reconstructed is already cleaned up and just needs to be binarized.
As source we will use a rasterized version of the synthetic test network (:meth:’Qiber3D.IO.load.synthetic_network’).
>>> from Qiber3D import config
>>> from Qiber3D import Network, IO
>>> syn_net = IO.load.synthetic_network()
# set up the resolution of the synthetic network
>>> voxel_resolution = 5
>>> config.extract.voxel_size = [1 / voxel_resolution] * 3
# switching off unneeded filters,
# as the synthetic network is already cleaned
>>> config.extract.morph.apply = False
>>> config.extract.median.apply = False
>>> config.extract.smooth.apply = False
>>> config.extract.z_drop.apply = False
# set a specific threshold to preserve radius
>>> config.extract.binary.threshold = 29
# export the synthetic network as .tif file
>>> syn_net.export('synthetic.tif', voxel_resolution=voxel_resolution, overwrite=True)
Qiber3D_render [INFO] Rasterizing network (voxel resolution : 5.00E+00 voxel/unit)
Qiber3D_core [INFO] Network exported to synthetic.tif.
# import .tif file
>>> net = Network.load('synthetic.tif')
Qiber3D_render [INFO] Rasterizing network (voxel resolution : 5.00E+00 voxel/unit)
Qiber3D_core [INFO] Network exported to synthetic.tif
Qiber3D_extract [INFO] Load image data from synthetic.tif
Qiber3D_extract [INFO] Image voxel size: [0.200,0.200,0.200]
Qiber3D_extract [INFO] Resample image to cubic voxels
Qiber3D_extract [INFO] Generate binary representation
Qiber3D_extract [INFO] Binary representation used a threshold of 29.0% (direct)
Qiber3D_extract [INFO] reconstruct image
Qiber3D_reconstruct [INFO] Skeletonize image by thinning
Qiber3D_reconstruct [INFO] Euclidean distance transformation
Qiber3D_reconstruct [INFO] Link up skeleton
Qiber3D_reconstruct [INFO] Build Qiber3D.Network from the raw graph
Qiber3D_reconstruct [INFO] Cleaning Network
Qiber3D_reconstruct [INFO] Smooth Segments
>>> print(net)
Input file: synthetic.tif
Number of fibers: 4 (clustered 2)
Number of segments: 11
Number of branch points: 4
Total length: 1120.84
Total volume: 4665.63
Average radius: 0.960
Cylinder radius: 1.151
Bounding box volume: 799821
Based on the synthetic network we can explore further export options of a Qiber3D.Network
.
syn_net.export('synthetic.json')
Qiber3D_core [INFO] Network exported to synthetic.json
{
"meta": {
"created": "2021-01-26T14:39:31.774967", "app_name": "Qiber3D", "app_version": "0.4.0", "source": null,
"name": "synthetic"
}, "network": {
"fiber": {
"0": {
"fid": 0, "volume": 1651.7148841392172, "average_radius": 0.8604967317483905,
"cylinder_radius": 1.0789216328856772, "length": 451.65352873495203, "sid_list": [0, 1, 2, 3, 4]
}, "1": {
"fid": 1, "volume": 1750.7734629144547, "average_radius": 0.9743524445038705,
"cylinder_radius": 1.322617429184498, "length": 318.5749324139831, "sid_list": [8, 5, 6, 7]
}, "2": {
"fid": 2, "volume": 600.3195103585697, "average_radius": 1.128023071088283, "cylinder_radius": 1.145703995907954,
"length": 145.5753120928598, "sid_list": [9]
}, "3": {
"fid": 3, "volume": 685.8592471183374, "average_radius": 0.9674890076192243,
"cylinder_radius": 0.9836495172449595, "length": 225.6339048471931, "sid_list": [10]
}
}, "extractor_data": null, "bbox": [[10.0, 7.8, -2.7], [153.4, 112.1, 51.2]],
"bbox_size": [143.4, 104.3, 53.900000000000006], "bbox_volume": 806161.8180000001,
"center": [81.7, 59.949999999999996, 24.250000000000004], "volume": 4688.667104530579,
"average_radius": 0.9359459559513582, "max_radius": 1.7082413328724901, "cylinder_radius": 1.1434670669897804,
"length": 1141.437678088988, "segment": {
"0": {
"sid": 0, "volume": 17.301298158883707, "average_radius": 0.3663121252534919,
"cylinder_radius": 0.3701523254210267, "length": 40.19461319013881, "direction": [3.6000000000000014, 36.6, 5.7],
"point": [
[20.0, 10.0, -0.0], [19.6, 11.6, -0.2], [19.2, 13.2, -0.3], [18.8, 14.7, -0.4], [18.5, 16.2, -0.5],
[18.2, 17.6, -0.6], [17.9, 19.0, -0.7], [17.7, 20.4, -0.7], [17.5, 21.7, -0.7], [17.3, 23.0, -0.7],
Full output: synthetic.json
syn_net.export('synthetic.xlsx')
Qiber3D_core [INFO] Network exported to synthetic.xlsx
Full output: synthetic.xlsx
syn_net.export('synthetic.csv')
Qiber3D_core [INFO] Network exported to synthetic.csv
FID;SID;X;Y;Z;Radius
0;0;20.000;10.000;-0.000;0.500
0;0;19.600;11.600;-0.200;0.473
0;0;19.200;13.200;-0.300;0.448
0;0;18.800;14.700;-0.400;0.425
0;0;18.500;16.200;-0.500;0.404
0;0;18.200;17.600;-0.600;0.385
0;0;17.900;19.000;-0.700;0.367
0;0;17.700;20.400;-0.700;0.351
0;0;17.500;21.700;-0.700;0.337
0;0;17.300;23.000;-0.700;0.324
0;0;17.200;24.200;-0.700;0.313
0;0;17.000;25.400;-0.700;0.304
0;0;16.900;26.600;-0.700;0.296
Full output: synthetic.csv
syn_net.export('synthetic.mv3d')
Qiber3D_core [INFO] Network exported to synthetic.mv3d
# MicroVisu3D file (created by Qiber3D 0.4.0)
# Number of lines 11
# Number of points 1404
# Number of inter. 5
#
# No x y z d
#
0 20.000 10.000 -0.000 1.000
0 19.600 11.600 -0.200 0.946
0 19.200 13.200 -0.300 0.897
0 18.800 14.700 -0.400 0.851
0 18.500 16.200 -0.500 0.809
0 18.200 17.600 -0.600 0.770
0 17.900 19.000 -0.700 0.735
Full output: synthetic.mv3d
syn_net.export('synthetic.x3d')
Qiber3D_core [INFO] Network exported to synthetic.x3d
<?xml version="1.0" encoding ="UTF-8"?>
<X3D profile="Immersive" version="3.0">
<head>
<meta name="filename" content="docs\x3d\synthetic_show.x3d"/>
<meta name="generator" content="Visualization ToolKit X3D exporter v0.9.1"/>
<meta name="numberofelements" content="11"/>
</head>
<Scene>
<Background skyColor="1.00000000000000000e+00 1.00000000000000000e+00 1.00000000000000000e+00"/>
<Viewpoint fieldOfView="5.23598790168762207e-01" position="8.18827030567863687e+01 6.01443915117113974e+01 3.86125999329838692e+02" description="Default View" orientation="0.00000000000000000e+00 0.00000000000000000e+00 1.00000000000000000e+00 -0.00000000000000000e+00" centerOfRotation="8.18827030567863687e+01 6.01443915117113974e+01 2.42252174161411489e+01"/>
<NavigationInfo type='"EXAMINE" "FLY" "ANY"' speed="4.00000000000000000e+00" headlight="true"/>
<DirectionalLight ambientIntensity="1.00000000000000000e+00" intensity="0.00000000000000000e+00" color="1.00000000000000000e+00 1.00000000000000000e+00 1.00000000000000000e+00"/>
<Transform DEF="ROOT" translation="0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00">
Full output: synthetic.x3d