How to make a Voxelised DNA Structure¶
DNA Structures are built from L-string seeded fractals.
L-strings and L-systems provide a grammar that can be used to generate a fractal. In this work, Hilbert curves are generated that are then converted into cubic placement ‘voxels’ for use in modelling.
[ ]:
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 matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
Producing L-Strings¶
The hilbert
model encodes a few basic fractals which can create Hilbert curves. These are
h.X: n<XFn<XFX-Fn>>XFX&F+>>XFX-F>X->
h.A: B-F+CFC+F-D&FnD-F+&&CFC+F+B<<
h.B: A&FnCFBnFnDnn-F-Dn|FnB|FCnFnA<<
h.C: |Dn|FnB-F+CnFnA&&FA&FnC+F+BnFnD<<
h.D: |CFB-F+B|FA&FnA&&FB-F+B|FC<<
Reference to these are all stored in hilbert.SUBSTITIONS
.
The L-String language works as follows:
interpret
F
as DrawForward(1);interpret
+
as Yaw(90);interpret
-
as Yaw(-90);interpret
n
as Pitch(90);interpret
&
as Pitch(-90);interpret
>
as Roll(90);interpret
<
as Roll(-90);interpret
|
as Yaw(180);
To ‘iterate’ an L-String, replace any reference to a subsititution with its value.
[ ]:
print("h.X:", h.X)
print("h.A:", h.A)
print("h.B:", h.B)
print("h.C:", h.C)
print("h.D:", h.D)
print("\nh.X iterated once:", h.iterate_lstring(h.X))
Drawing Fractals¶
The function generate_path
will generate a list of XYZ-points for a fractal L-String as below, which can then be plotted in matplotlib
[ ]:
print("Points seperated by 1 unit, no intermediate points")
print(h.generate_path("F", distance=1, n=1))
print("-")
print("Points seperated by 1 unit, 2 intermediate points")
print(h.generate_path("F", distance=1, n=2))
[ ]:
x_curve = np.array(h.generate_path(h.X, distance=1, n=10))
fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")
ax.plot(x_curve[:, 0], x_curve[:, 1], x_curve[:, 2])
[ ]:
x_iterated = h.iterate_lstring(h.X)
x_curve2 = np.array(h.generate_path(x_iterated, distance=1, n=10))
fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")
ax.plot(x_curve2[:, 0], x_curve2[:, 1], x_curve2[:, 2])
Making voxelised representations.¶
The voxelisation
model can convert the path of this curve to a voxelised representation, of straight and curved boxes.
[ ]:
voxelised_fractal = v.VoxelisedFractal.fromLString(h.X)
# This can be plotted
voxelised_fractal.to_pretty_plot()
Exporting large-scale structures to text.¶
[ ]:
# And this can be returned as a data frame, or as text
voxelised_fractal.to_frame()
[ ]: