Skip to content

Commit

Permalink
add basic element sphere
Browse files Browse the repository at this point in the history
  • Loading branch information
paulmueller committed Feb 6, 2019
1 parent 5ca2e8b commit fff6233
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 0 deletions.
3 changes: 3 additions & 0 deletions cellsino/elements/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .sphere import Sphere

available = [Sphere]
87 changes: 87 additions & 0 deletions cellsino/elements/base_element.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import copy

import numpy as np


class BaseElement(object):
def __init__(self, object_index, medium_index, fl_brightness,
points):
"""Initialize a basic element
Parameters
----------
object_index: float
Refractive index of the element
medium_index: float
Refractive index of surrounding medium
fl_brightness: float
Fluorescence brightness
points: 2d ndarray
Coordinates of the element the element
Notes
-----
When subclassing this class, override this method with
additional parameters (e.g. position, size) and call it
with super(ClassName, self).__init__(...).
"""
#: refractive index of the object
self.object_index = object_index
#: refractive index of the medium
self.medium_index = medium_index
#: brightness of the fluorescence signal
self.fl_brightness = fl_brightness
#: 2D array of points describing the geometrical object. This
#: variable is used for affine transforms (e.g. when rotating
#: the object).
self.points = np.array(points)

def transform(self, x=0, y=0, z=0, rot_main=0, rot_in_plane=0,
rot_perp_plane=0):
"""Rotate and translate self.points
Notes
-----
- By convention, sinogram generation in cellsino is performed by
modifying the pitch (rotation about y-axis).
- Rotation is performed prior to translation. First, the points
are rotated about the y-axis (``rot_main``, the main sinogram
acquisition angle). Second, the points are rotated about the
x-axis (``rot_perp_plane``, perpendicular to the imaging plane).
Third, the points are rotated about the z-axis (``rot_in_plane``,
within the imaging plane).
"""
Rx = np.array([
[1, 0, 0],
[0, np.cos(rot_perp_plane), -np.sin(rot_perp_plane)],
[0, np.sin(rot_perp_plane), np.cos(rot_perp_plane)],
])

Ry = np.array([
[np.cos(rot_main), 0, np.sin(rot_main)],
[0, 1, 0],
[-np.sin(rot_main), 0, np.cos(rot_main)],
])

Rz = np.array([
[np.cos(rot_in_plane), -np.sin(rot_in_plane), 0],
[np.sin(rot_in_plane), np.cos(rot_in_plane), 0],
[0, 0, 1]
])

R = np.dot(np.dot(Rx, Rz), Ry)
rotated = np.dot(R, self.points.T).T
rotated_pad = np.pad(rotated, ((0, 0), (0, 1)), mode="constant",
constant_values=1)

T = np.array([[1, 0, 0, x],
[0, 1, 0, y],
[0, 0, 1, z],
[0, 0, 0, 1],
])
translated = np.dot(T, rotated_pad.T)[:-1].T

# return a copy of the current instance with points transformed
telement = copy.copy(self)
telement.points = translated
return telement
30 changes: 30 additions & 0 deletions cellsino/elements/sphere.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import numpy as np

from .base_element import BaseElement


class Sphere(BaseElement):
def __init__(self, object_index, medium_index, fl_brightness,
center, radius):
"""Sphere element
Parameters
----------
object_index: float
Refractive index of the element
medium_index: float
Refractive index of surrounding medium
fl_brightness: float
Fluorescence brightness
center: list-like
Center coordinates (x, y, z) of the sphere [m]
radius:
Radius of the sphere [m]
"""
#: radius of the sphere
self.radius = radius
points = np.atleast_2d(center)
super(Sphere, self).__init__(object_index=object_index,
medium_index=medium_index,
fl_brightness=fl_brightness,
points=points)
22 changes: 22 additions & 0 deletions tests/test_elements_transform.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import numpy as np

from cellsino.elements.base_element import BaseElement


def test_translation():
points = np.array([[0, 0, 0]])
el = BaseElement(object_index=1.36,
medium_index=1.335,
fl_brightness=0,
points=points)

el2 = el.transform(x=1, y=2, z=-3)
assert np.all(el2.points[0] == [1 ,2, -3])


if __name__ == "__main__":
# Run all tests
loc = locals()
for key in list(loc.keys()):
if key.startswith("test_") and hasattr(loc[key], "__call__"):
loc[key]()

0 comments on commit fff6233

Please sign in to comment.