from SpindleAssembly import PositionComponents
import numpy as np
import math
[docs]def generate_separation(**kwargs):
"""
Calculate distance and angle between ipMTs based on the Gaussian distribution with a given mean and standard
deviation
:param kwargs: model parameters
:type kwargs: object
:return: s: distance between ipMTs
:rtype: s: float
:return: alpha: angle between ipMTs in degrees
:rtype: float
"""
s = np.random.normal(loc=kwargs['separation'][0], scale=kwargs['separation'][1])
# Generate angle between MTs
alpha = np.random.normal(loc=kwargs['angle'][0], scale=kwargs['angle'][1])
return s, alpha
[docs]def check_MT_within_centrosome(pos, **kwargs):
"""
Add ipMT if its x and y coordinates do not exceed the radius of the
circular cross-section of a centrosome
:param pos: (x, y) -> local coordinates of ipMT
:param kwargs: object
:return: True or False
"""
centrosomeRadius = kwargs['CentrosomeRadius']
x = pos[0]
y = pos[1]
if not -centrosomeRadius <= x <= centrosomeRadius \
and -centrosomeRadius <= y <= centrosomeRadius:
return False
return True
[docs]def condition_for_fourth_ipMT( alpha2, alpha3, s, pos3 ):
"""
Condition of positioning the fourth ipMT
:param alpha2: Angle between ipMTs number 2 and 3
:type alpha2: float
:param alpha3: Angle between ipMTs number 3 and 4
:type alpha3: float
:param s: Separation between ipMTs
:type s: float
:param pos3: (x, y) Position of the third ipMT
:type pos3: tuple
:return: y coordinate of the ipMT, mewalpha angle of the ipMT
:rtype: float, float
"""
if math.radians(alpha3) >= math.pi - math.radians(alpha2):
newalpha = math.radians(alpha3) - (math.pi - math.radians(alpha2))
y = pos3[1] + s * math.sin(newalpha)
else:
newalpha = - math.radians(alpha3) + (math.pi - math.radians(alpha2))
y = pos3[1] - s * math.sin(newalpha)
return y, newalpha
[docs]def add_first_ipMT( i, **kwargs ):
"""
Add and position the first ipMT within the spindle
:param i: Sequential number of ipMT
:type i: int
:param kwargs: model parameters
:type kwargs: dict
:return: MTname, pos, alpha, kwargs
:rtype: str, tuple, float, dict
"""
x = -0.018
y = -0.018
pos = (x, y)
kwargs['x'] = x
kwargs['y'] = y
kwargs['index'] = 1
MTname, zBeginPos, zEndPos, l = PositionComponents.assign_ipMTs_right(pos, i, **kwargs)
pos = (x, y, zBeginPos, zEndPos, l)
alpha = 0
return MTname, pos, alpha, kwargs
[docs]def add_second_ipMT( pos, alpha1, i, **kwargs ):
"""
Add and position the second ipMT within the spindle
:param pos: (x, y) position of the previously added ipMT
:type pos: tuple
:param alpha1: Angle of the previously added ipMT
:type alpha1: float
:param i: Sequential number of ipMT
:type i: int
:param kwargs: model parameters
:type kwargs: dict
:return: MTname, pos, alpha, kwargs
:rtype: str, tuple, float, dict
"""
# Generate position of the ipMT
s, alpha = generate_separation(**kwargs)
x = pos[0] + s * math.cos(math.radians(alpha1))
y = pos[1] + s * math.sin(math.radians(alpha1))
pos = (x, y)
# Correct the position until it is within centrosome
counter = 0
while not check_MT_within_centrosome(pos, **kwargs):
if counter > 1000:
raise ValueError('Some MTs are located outside of the centrosomes. Consider restarting calculation')
break
s, alpha = generate_separation(**kwargs)
# Position MT
x = pos[0] + s * math.cos(math.radians(alpha1))
y = pos[1] + s * math.sin(math.radians(alpha1))
kwargs['x'] = x
kwargs['y'] = y
pos = (x, y)
counter += 1
# Add and position ipMT
kwargs['index'] = 2
MTname, zBeginPos, zEndPos, l = PositionComponents.assign_ipMTs_left(pos, i, **kwargs)
pos = (x, y, zBeginPos, zEndPos, l)
return MTname, pos, alpha, kwargs
[docs]def add_third_ipMT( pos2, alpha2, i, **kwargs ):
"""
Add and position the third ipMT within the spindle
:param pos2: (x, y) position of the previously added ipMT
:type pos2: tuple
:param alpha2: Angle of the previously added ipMT
:type alpha2: float
:param i: Sequential number of ipMT
:type i: int
:param kwargs: model parameters
:type kwargs: dict
:return: MTname, pos, alpha, kwargs
:rtype: str, tuple, float, dict
"""
# Generate position of the ipMT
s, alpha = generate_separation(**kwargs)
x = pos2[0] - s * math.cos(math.radians(alpha2))
y = pos2[1] + s * math.sin(math.radians(alpha2))
pos = (x, y)
# Correct the position until it is within centrosome
counter = 0
while not check_MT_within_centrosome(pos, **kwargs):
if counter > 1000:
raise ValueError('Some MTs are located outside of the centrosomes. Consider restarting calculation')
break
x = pos2[0] - s * math.cos(math.radians(alpha2))
y = pos2[1] + s * math.sin(math.radians(alpha2))
kwargs['x'] = x
kwargs['y'] = y
counter += 1
# Add and position ipMT
kwargs['index'] = 3
MTname, zBeginPos, zEndPos, l = PositionComponents.assign_ipMTs_right(pos, i, **kwargs)
pos = (x, y, zBeginPos, zEndPos, l)
return MTname, pos, alpha, kwargs
[docs]def add_fourth_ipMT( pos3, alpha2, alpha3, i, **kwargs ):
"""
Add and position the fourth ipMT within the spindle
:param pos3: (x, y) position of the previously added ipMT
:type pos3: tuple
:param alpha2: Angle of ipMT 2
:type alpha2: float
:param alpha3: Angle of ipMT 3
:type alpha3: float
:param i: Sequential number of ipMT
:type i: int
:param kwargs: model parameters
:type kwargs: dict
:return: MTname, pos, alpha, kwargs
:rtype: str, tuple, float, dict
"""
# Generate position of the ipMT
s, alpha = generate_separation(**kwargs)
y, newalpha = condition_for_fourth_ipMT(alpha2, alpha3, s, pos3)
x = pos3[0] - s * math.cos(newalpha)
pos = (x, y)
# Correct the position until it is within centrosome
counter = 0
while not check_MT_within_centrosome(pos, **kwargs):
if counter > 1000:
raise ValueError('Some MTs are located outside of the centrosomes. Consider restarting calculation')
break
y, newalpha = condition_for_fourth_ipMT(alpha2, alpha3, s, pos3)
x = pos3[0] - s * math.cos(newalpha)
kwargs['x'] = x
kwargs['y'] = y
counter += 1
# Add and position ipMT
kwargs['index'] = 4
MTname, zBeginPos, zEndPos, l = PositionComponents.assign_ipMTs_left(pos, i, **kwargs)
pos = (x, y, zBeginPos, zEndPos, l)
return MTname, pos, newalpha, kwargs
[docs]def add_fifth_ipMT( pos4, alpha4, i, **kwargs ):
"""
Add and position the fifth ipMT within the spindle
:param pos4: (x, y) position of the previously added ipMT
:type pos4: tuple
:param alpha4: Angle of the previously added ipMT
:type alpha4: float
:param i: Sequential number of ipMT
:type i: int
:param kwargs: model parameters
:type kwargs: dict
:return: MTname, pos, alpha, kwargs
:rtype: str, tuple, float, dict
"""
# Generate position of the ipMT
s, alpha = generate_separation(**kwargs)
x = pos4[0] - s * math.cos(-math.radians(alpha4))
y = pos4[1] + s * math.sin(-math.radians(alpha4))
pos = (x, y)
# Correct the position until it is within centrosome
counter = 0
while not check_MT_within_centrosome(pos, **kwargs):
if counter > 1000:
raise ValueError('Some MTs are located outside of the centrosomes. Consider restarting calculation')
break
x = pos4[0] - s * math.cos(-math.radians(alpha4))
y = pos4[1] + s * math.sin(-math.radians(alpha4))
kwargs['x'] = x
kwargs['y'] = y
counter += 1
# Add and position ipMT
kwargs['index'] = 5
MTname, zBeginPos, zEndPos, l = PositionComponents.assign_ipMTs_right(pos, i, **kwargs)
pos = (x, y, zBeginPos, zEndPos, l)
return MTname, pos, alpha, kwargs
[docs]def add_sixth_ipMT( pos5, alpha4, alpha5, i, **kwargs ):
"""
Add and position sixth ipMT within the spindle
:param pos5: (x, y) position of the previously added ipMT
:type pos5: tuple
:param alpha4: Angle of the ipMT 4
:type alpha4: float
:param alpha5: Angle of the ipMT 5
:type alpha5: float
:param i: Sequential number of ipMT
:type i: int
:param kwargs: model parameters
:type kwargs: dict
:return: MTname, pos, alpha, kwargs
:rtype: str, tuple, float, dict
"""
# Generate position of the ipMT
s, alpha = generate_separation(**kwargs)
x = pos5[0] + s * math.cos(-math.radians(alpha5) + math.radians(alpha4))
y = pos5[1] + s * math.sin(-math.radians(alpha5) + math.radians(alpha4))
pos = (x, y)
# Correct the position until it is within centrosome
counter = 0
while not check_MT_within_centrosome(pos, **kwargs):
if counter > 1000:
raise ValueError('Some MTs are located outside of the centrosomes. Consider restarting calculation')
break
x = pos5[0] + s * math.cos(-math.radians(alpha5) + math.radians(alpha4))
y = pos5[1] + s * math.sin(-math.radians(alpha5) + math.radians(alpha4))
kwargs['x'] = x
kwargs['y'] = y
counter += 1
# Add and position ipMT
kwargs['index'] = 6
MTname, zBeginPos, zEndPos, l = PositionComponents.assign_ipMTs_left(pos, i, **kwargs)
pos = (x, y, zBeginPos, zEndPos, l)
return MTname, pos, alpha, kwargs