{ "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 }