3D kinematics using dual quaternions: theory and applications in neuroscience

The last time I programmed in LISP it was installed into an IBM-XT clone from a 4 inch paper floppy. I experimented with it for awhile but was soon back to programming in an early Basic.

Now that the era of VB being the worlds most used programming language is long over I’m forced to experiment with the now popular Python, which looks like it will maybe remain that way long enough to make it worth becoming proficient in. But perhaps I may soon need to experiment with LISP again.

I took a look for what was available for Python. I found that there is a “pyquaternion” and it properly installed into PyCharm, so I’m set to go with this:

http://kieranwynn.github.io/pyquaternion/

I’m not a natural born math wiz, and am still unsure how you would most efficiently use it to sum forces in the “j” loop, I commented out in code while getting all the rest of the program working:

def update():
    for i in range(ne):
        # Keep on a sphere by converting to Spherical then using its radius back again.
        s = cart2sphere(xyze[i])  # Cartesian to Spherical.
        sphe[i] = s[0], s[1], SphereRadius  # Change r to SphereRadius.
        xyze[i] = sphere2cart(sphe[i])  # Spherical to Cartesian again.
# Change x,y,z according to Lennard-Jones attraction/repulsion.
  #      for j in range(1):
  #          if i != j:

For calculating spherical distances between the points I adapted the Haversine Formula, and can adapt to return a 0 to 1 fractional distance.

# ------------------------------------------------------------------------------+
#
#   Nathan A. Rooy
#   Haversine Formula
#   June, 2016
# https://nathanrooy.github.io/posts/2016-09-07/haversine-with-python/
# ------------------------------------------------------------------------------+
# Radian Haversine to calculate distance between two points on a sphere.
# Distance is given and returned in Radians, max distance away is Pi
# Haversine(-HalfPi, 0, HalfPi, 0) = pole to pole = Pi = half around sphere.

import math

Pi=3.141592653589793238462643383279502884197169399375105820974944592307816406286
HalfPi=Pi/2
Radian=Pi*2

def Haversine(lat1, lon1, lat2, lon2):
    phi_1 = lat1
    phi_2 = lat2
    delta_phi = lat2 - lat1
    delta_lambda = lon2 - lon1
    a = math.sin(delta_phi / 2.0)**2 + math.cos(phi_1) * math.cos(phi_2) * math.sin(delta_lambda / 2.0)**2
    return 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))

print(Haversine(-HalfPi, 0, HalfPi, 0))
print(Haversine(-HalfPi, 0, HalfPi/2, 0))
print(Haversine(-HalfPi, 0, 0, 0))
print(Haversine(-HalfPi/2, 0, 0, HalfPi))

The above code might be replaced by a quaternion too. But since I’m not a natural born math wiz I’m not sure what the proper way of adding a 3D displacement vector to the x,y,z points. I have a long (re)learning curve ahead. All help up the hill is appreciated.

In this example a small vector of the same value should draw all the points to one side of the sphere. For bubble-like cell migration behavior this “ljp=” line of code would be used alone for displacement/magnitude, without complicating things by adding accelerations as in gasses in a vacuum.

epsilon = 1     # Energy minimum
sigma = 1       # Distance to zero crossing point

print("Lennard-Jones potential at radius of 0.01 to 5")
print("  i   r      ljp")
print("------------------------------------")

    # Lennard-Jones potential
for i in range(1,501):
    r=i/100
    ljp = 4*epsilon*((sigma/r)**12-(sigma/r)**6)
    print("{:3}{:7}   {}".format(i, r, ljp))

From experience I learned that at some point along the way towards modeling a human is the frustrating problem of the usual methods not working as expected, to overcome. An easy quaternion example of cells packing together on a spherical cortex of a small brain or “fold” of large ones might become useful, to others in this forum.