{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Making large scale structures in Geant4\n",
"\n",
"Geant4 simulations use a large scale structure "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import sys\n",
"from pathlib import Path\n",
"\n",
"try:\n",
" # The voxelisation library produces the cubic voxelisation that\n",
" # can be used to build DNA\n",
" from fractaldna.structure_models import voxelisation as v\n",
"\n",
" # The hilbert module produces and handles L-Strings\n",
" from fractaldna.structure_models import hilbert as h\n",
"except (ImportError, ModuleNotFoundError):\n",
" sys.path.append(str(Path.cwd().parent.parent.parent))\n",
" from fractaldna.structure_models import voxelisation as v\n",
" from fractaldna.structure_models import hilbert as h\n",
"\n",
"import numpy as np\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"from mpl_toolkits.mplot3d import Axes3D"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Fractal Cell Shapes\n",
"\n",
"### Generating a square shape"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Start with the initial L-String X for a Hilbert Curve\n",
"initial_string = \"X\"\n",
"# Iterate it as required (here, nn=3)\n",
"# for nn = 8, this takes about two hours on my 16GB RAM Mac\n",
"nn = 3\n",
"iterated_lstring = h.iterate_lstring(initial_string)\n",
"for _ in range(nn - 1):\n",
" iterated_lstring = h.iterate_lstring(iterated_lstring)\n",
"\n",
"vf = v.VoxelisedFractal.fromLString(iterated_lstring, pbar=True)\n",
"vf.center_fractal()\n",
"# fig = vf.to_plot()\n",
"# fig.savefig('results/fractal-X-3-centred.svg')\n",
"\n",
"# If you are saving a BIG fractal, try using the to_text() method instead\n",
"# as large dataframes are very slow to generate beyond 6 iterations.\n",
"# (Very slow as in multiple hours slow!)\n",
"# with open(f'results/fractal-X-{nn}-centred.csv', 'w') as ff:\n",
"# ff.write(vf.to_text())\n",
"vf.to_frame().to_csv(f\"results/fractal-X-{nn}-centred.csv\", index=False, sep=\" \")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Generating a Rectangular Shape\n",
"The seed `XFXFX` will generate a rectangular shape with aspect ratio 1:1:3"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Start with the initial L-String XFXFX for a Hilbert Curve\n",
"initial_string = \"XFXFX\"\n",
"# Iterate it as required (here, nn=4)\n",
"nn = 4\n",
"iterated_lstring = h.iterate_lstring(initial_string)\n",
"for _ in range(nn - 1):\n",
" iterated_lstring = h.iterate_lstring(iterated_lstring)\n",
"\n",
"vf = v.VoxelisedFractal.fromLString(iterated_lstring, pbar=True)\n",
"vf.center_fractal()\n",
"# fig = vf.to_plot()\n",
"# fig.savefig(f'results/fractal-XFXFX-{nn}-centred.svg')\n",
"\n",
"vf.to_frame().to_csv(f\"results/fractal-XFXFX-{nn}-centred.csv\", index=False, sep=\" \")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"*Note that the x-axis is compressed relative to the others in the below image*\n",
"\n",
"
"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Importing a shape from a path\n",
"\n",
"The `voxelisation` model can convert the path of this curve to a voxelised representation, of straight\n",
"and curved boxes.\n",
"\n",
"In this example we perform this on a text file with X/Y/Z columns:\n",
"```\n",
"X\tY\tZ\n",
"-22\t-106\t216\n",
"-22\t-107\t216\n",
"-22\t-107\t215\n",
"-22\t-108\t215\n",
"-22\t-108\t214\n",
"-23\t-108\t214\n",
"-23\t-109\t214\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%%capture\n",
"df = pd.read_csv(\"results/example-path.csv\", sep=\"\\t\")\n",
"fig = plt.figure()\n",
"ax = fig.add_subplot(111, projection=\"3d\")\n",
"ax.plot(df.X, df.Y, df.Z)\n",
"fig.savefig(\"example-path.svg\")\n",
"\n",
"vf = v.VoxelisedFractal.from_path(df.values)\n",
"fig_fractal = vf.to_plot()\n",
"fig_fractal.savefig(\"example-path-voxels.svg\")\n",
"\n",
"vf.to_frame().to_csv(\"results/example-path-voxels.csv\", sep=\" \", index=False)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Left: Source Plot, Right:Voxelised Plot\n",
"\n",
"
\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Generating Random Volumes\n",
"\n",
"It can be useful to generate randomised volumes for testing a simulation. \n",
"This was the subject of (this article)[https://doi.org/10.1016/j.ejmp.2018.02.011].\n",
"\n",
"To generate a randomised volume, the `fractaldna.structure_models.random_placements`\n",
"is available.\n",
"\n",
"In that paper, 200,000 non overlapping prisms were simulated in a r=3000nm \n",
"ball.\n",
"The prisms had dimensions 30x30x100nm"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from fractaldna.structure_models import random_placements as rp\n",
"\n",
"# Generating 200,000 prisms can take around 4-5 hours\n",
"prisms = rp.generate_non_overlapping_prisms(\n",
" n_prisms=200_000,\n",
" size=[30, 30, 100], # nanometres\n",
" rad=3000, # nanometres\n",
" early_exit=-1,\n",
" verbose=True,\n",
")\n",
"\n",
"df = prisms.to_frame()\n",
"df.to_csv(\"results/prisms_200k_r3000.csv\", sep=\" \", index=False)"
]
}
],
"metadata": {
"language_info": {
"name": "python",
"pygments_lexer": "ipython3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}