Source code for simularium_readdy_models.kinesin.kinesin_util

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import numpy as np
import readdy
import random

from ..common import ReaddyUtil
from ..microtubules.microtubules_util import MicrotubulesUtil


parameters = {}


[docs]def set_parameters(p): global parameters parameters = p return p
[docs]class KinesinUtil: def __init__(self, parameters): """ Utility functions for ReaDDy kinesin models Parameters need to be accessible in ReaDDy callbacks which can't be instance methods, so parameters are global """ set_parameters(parameters)
[docs] @staticmethod def add_kinesin(position_offset, simulation): """ add a kinesin to the simulation """ positions = np.array( [ [0.0, 3.0, 0.0], [0.0, 3.0, -5.0], [0.0, 0.0, 4.0], # [0., 30., 0.] ] ) types = [ "hips", "motor#ADP", "motor#ADP", # "cargo" ] kinesin = simulation.add_topology("Kinesin", types, positions + position_offset) for i in range(1, 3): kinesin.get_graph().add_edge(0, i)
[docs] @staticmethod def set_kinesin_state(topology, recipe, from_motor_state, to_motor_state): """ change the state of a motor and update the kinesin state to match for a dictionary of types and radii [nm] returns dictionary mapping all types to radii """ motors = ReaddyUtil.get_vertices_of_type(topology, "motor", False) if len(motors) < 2: raise Exception( f"Failed to find 2 motors, found {len(motors)}\n" + ReaddyUtil.topology_to_string(topology) ) motor_types = [ topology.particle_type_of_vertex(motors[0]), topology.particle_type_of_vertex(motors[1]), ] other_state = "" motors_in_from_state = [] for i in range(2): if from_motor_state in motor_types[i]: motors_in_from_state.append(motors[i]) else: other_state = motor_types[i][motor_types[i].index("#") + 1 :] if len(motors_in_from_state) < 1: if parameters["verbose"]: print(f"Couldn't find a motor in state {from_motor_state}") return None if len(motors_in_from_state) > 1: motor_to_set = random.choice(motors_in_from_state) other_state = from_motor_state else: motor_to_set = motors_in_from_state[0] recipe.change_particle_type(motor_to_set, f"motor#{to_motor_state}") if "ADP" in to_motor_state and "ADP" in other_state: recipe.change_topology_type("Microtubule-Kinesin#Releasing") else: new_states = [to_motor_state, other_state] new_states.sort() recipe.change_topology_type( f"Microtubule-Kinesin#{new_states[0]}-{new_states[1]}" ) return motor_to_set
[docs] @staticmethod def reaction_function_motor_bind_tubulin(topology): """ bind a kinesin motor in ADP state to a free tubulinB """ if parameters["verbose"]: print("Bind tubulin") recipe = readdy.StructuralReactionRecipe(topology) motor = KinesinUtil.set_kinesin_state(topology, recipe, "new", "apo") if motor is None: raise Exception( "Failed to find new motor\n" + ReaddyUtil.topology_to_string(topology) ) tubulin = ReaddyUtil.get_neighbor_of_type( topology, motor, "tubulinB#bound", False, error_msg="Failed to find bound tubulin", ) if parameters["verbose"]: print( ReaddyUtil.vertex_to_string(topology, motor) + " ++ " + ReaddyUtil.vertex_to_string(topology, tubulin) ) tubulin_pos = ReaddyUtil.get_vertex_position(topology, tubulin) # TODO calculate position offset from tubulin neighbors recipe.change_particle_position(motor, tubulin_pos + (0.0, 4.0, 0.0)) return recipe
[docs] @staticmethod def reaction_function_motor_bind_ATP(topology): """ set bound apo motor's state to ATP (and implicitly simulate ATP binding) """ if parameters["verbose"]: print("Bind ATP") recipe = readdy.StructuralReactionRecipe(topology) motor = KinesinUtil.set_kinesin_state(topology, recipe, "apo", "ATP") if motor is None: raise Exception( "Failed to find motor in apo state\n" + ReaddyUtil.topology_to_string(topology) ) if parameters["verbose"]: print(ReaddyUtil.vertex_to_string(topology, motor)) return recipe
[docs] @staticmethod def reaction_function_motor_release_tubulin(topology): """ release a bound motor from tubulin """ if parameters["verbose"]: print("Release tubulin") recipe = readdy.StructuralReactionRecipe(topology) motor = KinesinUtil.set_kinesin_state(topology, recipe, "ATP", "ADP") if motor is None: raise Exception( "Failed to find motor in ATP state\n" + ReaddyUtil.topology_to_string(topology) ) tubulin = ReaddyUtil.get_neighbor_of_type( topology, motor, "tubulinB#bound", False, error_msg="Failed to find bound tubulin", ) if parameters["verbose"]: print( ReaddyUtil.vertex_to_string(topology, motor) + " -X- " + ReaddyUtil.vertex_to_string(topology, tubulin) ) # ReaddyUtil.set_flags(topology, recipe, tubulin, [], ["bound"]) # TODO fix bug # workaround pt = topology.particle_type_of_vertex(tubulin) recipe.change_particle_type(tubulin, f"tubulinB#{pt[-3:]}") removed, message = ReaddyUtil.try_remove_edge(topology, recipe, motor, tubulin) if not removed: raise Exception(message + "\n" + ReaddyUtil.topology_to_string(topology)) return recipe
[docs] @staticmethod def reaction_function_cleanup_release_tubulin(topology): """ cleanup after releasing a bound motor from tubulin """ recipe = readdy.StructuralReactionRecipe(topology) motors = ReaddyUtil.get_vertices_of_type(topology, "motor", False) if len(motors) > 0: recipe.change_topology_type("Kinesin") else: recipe.change_topology_type("Microtubule") if parameters["verbose"]: print("Cleaned up release tubulin") return recipe
[docs] @staticmethod def rate_function_motor_bind_ATP(topology): """ rate function for a motor binding ATP """ return parameters["motor_bind_ATP_rate"]
[docs] @staticmethod def rate_function_motor_release_tubulin(topology): """ rate function for a bound motor releasing from tubulin """ return parameters["motor_release_tubulin_rate"]
[docs] @staticmethod def add_kinesin_bonds_and_repulsions(motor_types, force_constant, system, util): """ add bonds between tubulins """ necklinker_force_constant = 0.002 * force_constant util.add_bond(["hips"], motor_types, necklinker_force_constant, 2.0, system) util.add_bond(["hips"], ["cargo"], force_constant, 30.0, system) util.add_repulsion(motor_types, motor_types, force_constant, 4.0, system) util.add_repulsion(["hips"], motor_types, force_constant, 2.0, system) util.add_repulsion(["hips"], ["cargo"], force_constant, 30.0, system)
[docs] @staticmethod def add_tubulin_bonds_and_repulsions(tubulin_types, force_constant, system, util): """ add bonds between tubulins """ util.add_polymer_bond_2D( # bonds between protofilaments tubulin_types, [0, 0], tubulin_types, [0, -1], force_constant, 5.2, system ) util.add_polymer_bond_2D( # bonds between rings tubulin_types, [0, 0], tubulin_types, [-1, 0], force_constant, 4.0, system ) all_tubulin_types = [] for t in range(len(tubulin_types)): all_tubulin_types += MicrotubulesUtil.get_all_polymer_tubulin_types( tubulin_types[t] ) util.add_repulsion( all_tubulin_types, all_tubulin_types, force_constant, 4.0, system )
[docs] @staticmethod def add_kinesin_angles_and_dihedrals(tubulin_types, force_constant, system, util): """ add kinesin angles """ # angles from tubulins to bound motor util.add_polymer_angle_2D( tubulin_types, [-1, 0], ["tubulinB#bound_"], [0, 0], ["motor#apo", "motor#ATP", "motor#ADP"], [], 1e32, 0.0, system, )
# util.add_polymer_angle_2D( # tubulin_types, [1, 0], # ["tubulinB#bound_"], [0, 0], # ["motor#apo", "motor#ATP", "motor#ADP"], [], # 1e32, np.pi / 2., system # ) # util.add_polymer_angle_2D( # tubulin_types, [0, -1], # ["tubulinB#bound_"], [0, 0], # ["motor#apo", "motor#ATP", "motor#ADP"], [], # 1e32, 1.84, system # ) # util.add_polymer_angle_2D( # tubulin_types, [0, 1], # ["tubulinB#bound_"], [0, 0], # ["motor#apo", "motor#ATP", "motor#ADP"], [], # 1e32, 1.54, system # ) # # angle from bound tubulin to hips # util.add_polymer_angle_2D( # ["tubulinB#bound_"], [0, 0], # ["motor#ATP"], [], # ["hips"], [], # 0.5 * force_constant, np.pi * 5./9., system # ) # # angle from bound motor to free motor through hips # util.add_angle( # ["motor#ATP"], # ["hips"], # ["motor#ADP"], # 0.1 * force_constant, np.pi * 8./9., system # ) # # dihedrals from tubulins to hips # util.add_polymer_dihedral_2D( # tubulin_types, [-1, 0], # ["tubulinB#bound_"], [0, 0], # ["motor#ATP"], [], # ["hips"], [], # 1.5 * force_constant, np.pi * 17./18., system # ) # util.add_polymer_dihedral_2D( # tubulin_types, [1, 0], # ["tubulinB#bound_"], [0, 0], # ["motor#ATP"], [], # ["hips"], [], # 1.5 * force_constant, np.pi / 18., system # ) # util.add_polymer_dihedral_2D( # tubulin_types, [0, -1], # ["tubulinB#bound_"], [0, 0], # ["motor#ATP"], [], # ["hips"], [], # 1.5 * force_constant, 1.79, system # ) # util.add_polymer_dihedral_2D( # tubulin_types, [0, 1], # ["tubulinB#bound_"], [0, 0], # ["motor#ATP"], [], # ["hips"], [], # 1.5 * force_constant, 1.44, system # ) # # dihedral from bound tubulin to free motor # util.add_polymer_dihedral_2D( # ["tubulinB#bound_"], [0, 0], # ["motor#ATP"], [], # ["hips"], [], # ["motor#ADP"], [], # 0.5 * force_constant, np.pi * 4./9., system # )
[docs] @staticmethod def add_angles_between_tubulins(tubulin_types, force_constant, system, util): """ add angles between tubulins """ util.add_polymer_angle_2D( tubulin_types, [0, 1], tubulin_types, [0, 0], tubulin_types, [-1, 0], force_constant, 1.75, system, ) util.add_polymer_angle_2D( tubulin_types, [0, 1], tubulin_types, [0, 0], tubulin_types, [1, 0], force_constant, 1.40, system, ) util.add_polymer_angle_2D( tubulin_types, [0, -1], tubulin_types, [0, 0], tubulin_types, [-1, 0], force_constant, 1.40, system, ) util.add_polymer_angle_2D( tubulin_types, [0, -1], tubulin_types, [0, 0], tubulin_types, [1, 0], force_constant, 1.75, system, ) util.add_polymer_angle_2D( tubulin_types, [-1, 0], tubulin_types, [0, 0], tubulin_types, [1, 0], force_constant, np.pi, system, ) util.add_polymer_angle_2D( tubulin_types, [0, -1], tubulin_types, [0, 0], tubulin_types, [0, 1], force_constant, 2.67, system, )
[docs] @staticmethod def add_motor_tubulin_interactions( motor_types, bound_tubulin_types, tubulin_types, force_constant, system, util ): """ add repulsions between motors and tubulins """ bound_types = [] for t in bound_tubulin_types: bound_types += MicrotubulesUtil.get_all_polymer_tubulin_types(t) all_types = [] for t in tubulin_types: all_types += MicrotubulesUtil.get_all_polymer_tubulin_types(t) util.add_bond(motor_types, bound_types, force_constant, 4.0, system) util.add_repulsion(motor_types, all_types, force_constant, 3.0, system)
[docs] @staticmethod def add_motor_bind_tubulin_reaction(system, rate, reaction_distance): """ bind a kinesin motor in ADP state to a free tubulinB """ # spatial reactions polymer_numbers = MicrotubulesUtil.get_all_polymer_tubulin_types("") # kinesin_states = ["ADP-apo", "ADP-ATP"] i = 1 for n in polymer_numbers: # first motor binding system.topologies.add_spatial_reaction( f"Bind_Tubulin#ADP-ADP{i}: " f"Kinesin(motor#ADP) + Microtubule(tubulinB#{n}) -> " f"Microtubule-Kinesin#Binding(motor#new--tubulinB#bound_{n})", rate=rate, radius=4.0 + reaction_distance, ) # # second motor binding # for s in kinesin_states: # system.topologies.add_spatial_reaction( # f"Bind_Tubulin#{s}{i}: " # f"Microtubule-Kinesin#{s}(motor#ADP) + " # f"Microtubule-Kinesin#{s}(tubulinB#{n}) -> " # "Microtubule-Kinesin#Binding(motor#new--" # f"tubulinB#bound_{n}) [self=true]", # rate=rate, # radius=4.0 + reaction_distance, # ) i += 1 # structural reaction system.topologies.add_structural_reaction( "Finish_Bind_Tubulin", topology_type="Microtubule-Kinesin#Binding", reaction_function=KinesinUtil.reaction_function_motor_bind_tubulin, rate_function=ReaddyUtil.rate_function_infinity, )
[docs] @staticmethod def add_motor_bind_ATP_reaction(system): """ set bound apo motor's state to ATP (and implicitly simulate ATP binding) """ kinesin_states = ["ADP-apo", "ATP-apo", "apo-apo"] for state in kinesin_states: system.topologies.add_structural_reaction( f"Bind_ATP#{state}", topology_type=f"Microtubule-Kinesin#{state}", reaction_function=KinesinUtil.reaction_function_motor_bind_ATP, rate_function=KinesinUtil.rate_function_motor_bind_ATP, )
[docs] @staticmethod def add_motor_release_tubulin_reaction(system): """ release a bound motor from tubulin """ kinesin_states = ["ADP-ATP", "ATP-ATP", "ATP-apo"] for state in kinesin_states: system.topologies.add_structural_reaction( f"Release_Tubulin#{state}", topology_type=f"Microtubule-Kinesin#{state}", reaction_function=KinesinUtil.reaction_function_motor_release_tubulin, rate_function=KinesinUtil.rate_function_motor_release_tubulin, ) system.topologies.add_structural_reaction( "Cleanup_Release_Tubulin", topology_type="Microtubule-Kinesin#Releasing", reaction_function=KinesinUtil.reaction_function_cleanup_release_tubulin, rate_function=ReaddyUtil.rate_function_infinity, )