<jupyter_start><jupyter_text>Computing the path length in an object This tutorial show you how to compute the path length for 3 objects (here from STL files). ![3D objects](screenshot.png)We store the parameters of the scanning geometry using a JSON file (`param.json`):```json{  "WindowSize": [512, 512],  "Source": {    "Position": [-40.0,  0.0, 0.0, "cm"],    "Shape": "PointSource"  },  "Detector": {    "Position": [40.0, 0.0, 0.0, "cm"],    "UpVector": [0, 0, -1],    "NumberOfPixels": [641, 320],    "Spacing": [0.25, 0.25, "mm"]  },  "Samples": [    {      "Label": "cubes",      "Path": "cubes.stl",      "Unit": "mm"    },    {      "Label": "gVXR",      "Path": "gVXR.stl",      "Unit": "mm"    },    {      "Label": "spheres",      "Path": "spheres.stl",      "Unit": "mm"    }  ]}```Below is the corresponding 3D view.![3D view](3d-view.png)  Import packages<jupyter_code>import json # Load the JSON file
import numpy as np # To save the image in ASCII
import SimpleITK as sitk # To save the image in a binary (optional)

import matplotlib.pyplot as plt # For plotting (optional)

import gvxrPython3 as gvxr # Simulate X-ray images<jupyter_output><empty_output><jupyter_text>Load the JSON file<jupyter_code>with open('config.json') as f:
  params = json.load(f)<jupyter_output><empty_output><jupyter_text>Create an OpenGL context<jupyter_code>gvxr.createWindow(0, 1, "EGL");

window_size = params["WindowSize"];
gvxr.setWindowSize(
    window_size[0],
    window_size[1]
);<jupyter_output><empty_output><jupyter_text>Set up the beam<jupyter_code>source_position = params["Source"]["Position"];
gvxr.setSourcePosition(
    source_position[0],
    source_position[1],
    source_position[2],
    source_position[3]
);

source_shape = params["Source"]["Shape"]

if source_shape == "ParallelBeam":
    gvxr.useParallelBeam();
elif source_shape == "PointSource":
    gvxr.usePointSource();
else:
    raise "Unknown source shape:" + source_shape;<jupyter_output><empty_output><jupyter_text>Set up the detector<jupyter_code>detector_position = params["Detector"]["Position"];
gvxr.setDetectorPosition(
    detector_position[0],
    detector_position[1],
    detector_position[2],
    detector_position[3]
);

detector_up = params["Detector"]["UpVector"];
gvxr.setDetectorUpVector(
    detector_up[0],
    detector_up[1],
    detector_up[2]
);

detector_number_of_pixels = params["Detector"]["NumberOfPixels"];
gvxr.setDetectorNumberOfPixels(
    detector_number_of_pixels[0],
    detector_number_of_pixels[1]
);

pixel_spacing = params["Detector"]["Spacing"];
gvxr.setDetectorPixelSize(
    pixel_spacing[0],
    pixel_spacing[1],
    pixel_spacing[2]
);<jupyter_output><empty_output><jupyter_text>Load the polygon meshes<jupyter_code>for mesh in params["Samples"]:

    gvxr.loadMeshFile(
        mesh["Label"],
        mesh["Path"],
        mesh["Unit"]
    );

    gvxr.addPolygonMeshAsInnerSurface(mesh["Label"]);<jupyter_output><empty_output><jupyter_text>Dummy beam spectrum<jupyter_code>gvxr.addEnergyBinToSpectrum(1,"keV",10); # 10 photons of 1 keV<jupyter_output><empty_output><jupyter_text>Compute the path length for every object<jupyter_code>path_length = {};
for mesh in params["Samples"]:
    path_length[mesh["Label"]] = gvxr.computeLBuffer(mesh["Label"]);<jupyter_output><empty_output><jupyter_text>Save the path length using Numpy<jupyter_code>for key in path_length:
    np.savetxt(key + "_path_length.txt", path_length[key]);<jupyter_output><empty_output><jupyter_text>Save the path length using SITK<jupyter_code>for key in path_length:
    volume = sitk.GetImageFromArray(path_length[key]);
    volume.SetSpacing([pixel_spacing[0], pixel_spacing[1]]);
    sitk.WriteImage(volume, key + "_path_length.mha", useCompression=True);<jupyter_output><empty_output><jupyter_text>Display the path length using Matplotlib<jupyter_code>for key in path_length:
    fig=plt.figure();
    imgplot = plt.imshow(path_length[key], cmap="gray");
    plt.title("Path length (in cm) of " + key);
    plt.colorbar();
    plt.savefig(key + "_path_length.pdf");<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.147008547008547, 'fraction_numerical': 0.01684981684981685, 'mean_word_length': 5.430141287284145, 'pattern_counts': {'":': 21, '<': 45, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '11', 'dir': 'jupyter-structured-clean-dedup', 'id': '485170', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 1526, 'n_tokens_neox': 1473, 'n_words': 284, 'path': 'other_demos/1-lbuffer/1-lbuffer.ipynb', 'repo_name': 'effepivi/gvxr-demos', 'size': '4095'}