Making large scale structures in Geant4

Geant4 simulations use a large scale structure

[ ]:
import sys
from pathlib import Path

try:
    # The voxelisation library produces the cubic voxelisation that
    # can be used to build DNA
    from fractaldna.structure_models import voxelisation as v

    # The hilbert module produces and handles L-Strings
    from fractaldna.structure_models import hilbert as h
except (ImportError, ModuleNotFoundError):
    sys.path.append(str(Path.cwd().parent.parent.parent))
    from fractaldna.structure_models import voxelisation as v
    from fractaldna.structure_models import hilbert as h

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

Fractal Cell Shapes

Generating a square shape

[ ]:
# Start with the initial L-String X for a Hilbert Curve
initial_string = "X"
# Iterate it as required (here, nn=3)
# for nn = 8, this takes about two hours on my 16GB RAM Mac
nn = 3
iterated_lstring = h.iterate_lstring(initial_string)
for _ in range(nn - 1):
    iterated_lstring = h.iterate_lstring(iterated_lstring)

vf = v.VoxelisedFractal.fromLString(iterated_lstring, pbar=True)
vf.center_fractal()
# fig = vf.to_plot()
# fig.savefig('results/fractal-X-3-centred.svg')

# If you are saving a BIG fractal, try using the to_text() method instead
# as large dataframes are very slow to generate beyond 6 iterations.
# (Very slow as in multiple hours slow!)
# with open(f'results/fractal-X-{nn}-centred.csv', 'w') as ff:
#     ff.write(vf.to_text())
vf.to_frame().to_csv(f"results/fractal-X-{nn}-centred.csv", index=False, sep=" ")

6ca7b7e0bf504730a02ada8060b7a20c

Generating a Rectangular Shape

The seed XFXFX will generate a rectangular shape with aspect ratio 1:1:3

[ ]:
# Start with the initial L-String XFXFX for a Hilbert Curve
initial_string = "XFXFX"
# Iterate it as required (here, nn=4)
nn = 4
iterated_lstring = h.iterate_lstring(initial_string)
for _ in range(nn - 1):
    iterated_lstring = h.iterate_lstring(iterated_lstring)

vf = v.VoxelisedFractal.fromLString(iterated_lstring, pbar=True)
vf.center_fractal()
# fig = vf.to_plot()
# fig.savefig(f'results/fractal-XFXFX-{nn}-centred.svg')

vf.to_frame().to_csv(f"results/fractal-XFXFX-{nn}-centred.csv", index=False, sep=" ")

Note that the x-axis is compressed relative to the others in the below image

5a130e1376804a37a3e21eaaaf33841b

Importing a shape from a path

The voxelisation model can convert the path of this curve to a voxelised representation, of straight and curved boxes.

In this example we perform this on a text file with X/Y/Z columns:

X   Y   Z
-22 -106    216
-22 -107    216
-22 -107    215
-22 -108    215
-22 -108    214
-23 -108    214
-23 -109    214
[ ]:
%%capture
df = pd.read_csv("results/example-path.csv", sep="\t")
fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")
ax.plot(df.X, df.Y, df.Z)
fig.savefig("example-path.svg")

vf = v.VoxelisedFractal.from_path(df.values)
fig_fractal = vf.to_plot()
fig_fractal.savefig("example-path-voxels.svg")

vf.to_frame().to_csv("results/example-path-voxels.csv", sep=" ", index=False)

Left: Source Plot, Right:Voxelised Plot

2b92836f5cd243f99250fd8f96d3340a 034f3d7744e146d3bcc4cb3ac797c57d

Generating Random Volumes

It can be useful to generate randomised volumes for testing a simulation. This was the subject of (this article)[https://doi.org/10.1016/j.ejmp.2018.02.011].

To generate a randomised volume, the fractaldna.structure_models.random_placements is available.

In that paper, 200,000 non overlapping prisms were simulated in a r=3000nm ball. The prisms had dimensions 30x30x100nm

[ ]:
from fractaldna.structure_models import random_placements as rp

# Generating 200,000 prisms can take around 4-5 hours
prisms = rp.generate_non_overlapping_prisms(
    n_prisms=200_000,
    size=[30, 30, 100],  # nanometres
    rad=3000,  # nanometres
    early_exit=-1,
    verbose=True,
)

df = prisms.to_frame()
df.to_csv("results/prisms_200k_r3000.csv", sep=" ", index=False)