19 namespace neuroscience {
23 tension_ = param->neurite_default_tension;
26 density_ = param->neurite_default_density;
35 Base::Initialize(event);
48 diameter = e.diameter_left;
49 direction = e.direction_left;
52 diameter = e.diameter_right;
53 direction = e.direction_right;
71 auto* ne = bdm_static_cast<NeuriteElement*>(event.
new_agents[0]);
80 auto new_agent1 =
event.new_agents[0];
81 auto new_agent2 =
event.new_agents[1];
90 auto* proximal = bdm_static_cast<NeuriteElement*>(new_agent1);
94 mother_->UpdateRelative(*
this, *proximal);
98 proximal->UpdateDependentPhysicalVariables();
100 proximal->UpdateLocalCoordinateAxis();
103 auto* proximal = bdm_static_cast<NeuriteElement*>(new_agent1);
104 auto* branch = bdm_static_cast<NeuriteElement*>(new_agent2);
108 proximal->SetDaughterRight(branch->GetAgentPtr<
NeuriteElement>());
112 mother_->UpdateRelative(*
this, *proximal);
116 proximal->UpdateDependentPhysicalVariables();
118 proximal->UpdateLocalCoordinateAxis();
124 aptrs->push_back(GetAgentPtr<>());
135 return {
"mass_location_",
"diameter_",
"actual_length_",
"spring_axis_"};
215 }
else if (mother_agentma) {
216 mother_->RemoveDaughter(Base::GetAgentPtr<NeuriteElement>());
218 }
else if (mother_neurite && mother_neurite->GetDaughterRight() ==
nullptr) {
226 mother_->RemoveDaughter(Base::GetAgentPtr<NeuriteElement>());
229 mother_->UpdateDependentPhysicalVariables();
251 return bdm_static_cast<NeuriteElement*>(event.
new_agents[1]);
260 auto rand_noise = random->template UniformArray<3>(-0.1, 0.1);
263 growth_direction.Normalize();
264 return Branch(diameter, growth_direction);
270 auto rand_noise = random->template UniformArray<3>(-0.1, 0.1);
273 return Branch(branch_diameter, growth_direction);
284 const Real3& direction_1,
const Real3& direction_2) {
288 Fatal(
"NeuriteElements",
289 "Bifurcation only allowed on a terminal neurite element");
294 auto* new_branch_l = bdm_static_cast<NeuriteElement*>(event.
new_agents[0]);
295 auto* new_branch_r = bdm_static_cast<NeuriteElement*>(event.
new_agents[1]);
296 return {new_branch_l, new_branch_r};
301 const Real3& direction_2) {
302 Log::Fatal(
"NeuriteElement::Bifurcate",
"Not Implemented");
303 std::array<NeuriteElement*, 2> dummy;
308 const Real3& direction_1,
const Real3& direction_2) {
314 return Bifurcate(l, d, d, direction_1, direction_2);
329 spring_axis_, angle_between_branches * 0.5, perp_plane);
331 spring_axis_, -angle_between_branches * 0.5, perp_plane);
333 return Bifurcate(l, d, d, direction_1, direction_2);
350 Fatal(
"NeuriteElement",
"Given object is not a daughter!");
355 if (
mother_ == &old_relative) {
358 auto new_neurite_agent_ptr =
359 bdm_static_cast<const NeuriteElement*>(&new_relative)
372 Fatal(
"NeuriteElement",
"Given object is not the mother!");
398 }
else if (mother_agentma !=
nullptr) {
403 }
else if (actual_length_ < param->neurite_min_length &&
404 mother_neurite !=
nullptr &&
405 mother_neurite->GetRestingLength() <
407 mother_neurite->GetDaughterRight() ==
nullptr &&
411 mother_neurite->RemoveFromSimulation();
430 auto relative_ml =
mother_->OriginOf(Base::GetUid());
445 if (tension == 0.0) {
486 bdm_static_cast<const NeuriteElement*>(neighbor)->GetMother() ||
490 }
else if (
auto* neighbor_soma =
dynamic_cast<const NeuronSoma*
>(neighbor)) {
503 force_from_neighbor = force_from_neighbor *
h_over_m;
507 if (force_from_neighbor[0] != 0 || force_from_neighbor[1] != 0 ||
508 force_from_neighbor[2] != 0) {
512 if (std::abs(force_from_neighbor[3]) <
520 real_t part_for_point_mass = 1.0 - force_from_neighbor[3];
525 force_from_neighbor[0] * force_from_neighbor[3];
527 force_from_neighbor[1] * force_from_neighbor[3];
529 force_from_neighbor[2] * force_from_neighbor[3];
535 Real3 force_on_my_mothers_point_mass{0, 0, 0};
547 force_on_my_point_mass +=
551 force_on_my_point_mass +=
555 Real3 force_from_neighbors = {0, 0, 0};
562 uint64_t non_zero_neighbor_force = 0;
567 force,
this, force_from_neighbors, force_on_my_mothers_point_mass,
570 ctxt->
ForEachNeighbor(calculate_neighbor_forces, *
this, squared_radius);
572 if (non_zero_neighbor_force > 1) {
581 force_on_my_point_mass *= h_over_m;
584 force_on_my_point_mass += force_from_neighbors;
589 if (
mother_->IsNeuriteElement()) {
590 bdm_static_cast<NeuriteElement*>(
mother_.Get())
591 ->SetStaticnessNextTimestep(
false);
593 bdm_static_cast<NeuronSoma*>(
mother_.Get())
594 ->SetStaticnessNextTimestep(
false);
600 if (force_on_my_point_mass ==
Real3{0, 0, 0}) {
604 real_t force_norm = force_on_my_point_mass.
Norm();
612 auto& displacement = force_on_my_point_mass;
613 real_t& displacement_norm = force_norm;
616 if (displacement_norm > core_param->simulation_max_displacement) {
617 displacement = displacement * (core_param->simulation_max_displacement /
626 if (displacement ==
Real3{0, 0, 0}) {
657 if (norm_of_z < 1E-10) {
672 Base::SetPropagateStaticness();
682 const Real3& position)
const {
688 const Real3& position)
const {
692 auto x = position * axis_0;
693 auto y = position * axis_1;
694 auto z = position * axis_2;
700 const Real3& position)
const {
701 return {position[0], std::atan2(position[2], position[1]),
702 std::sqrt(position[1] * position[1] + position[2] * position[2])};
706 const Real3& position)
const {
707 return {position[0], position[2] * std::cos(position[1]),
708 position[2] * std::sin(position[1])};
712 const std::array<real_t, 2>& position)
const {
717 Real3 polar_position{position[0], position[1], r};
723 const Real3& position)
const {
780 if (
auto* mother_neurite =
782 if (mother_neurite->GetDaughterRight() ==
nullptr) {
783 length += mother_neurite->LengthToProximalBranchingPoint();
795 auto relative_ml =
mother_->OriginOf(Base::GetUid());
814 str <<
"Position: " << pos[0] <<
", " << pos[1] <<
", " << pos[2]
815 <<
", " << std::endl;
816 str <<
"x_axis_: " << n.
x_axis_[0] <<
", " << n.
x_axis_[1] <<
", "
817 << n.
x_axis_[2] <<
", " << std::endl;
818 str <<
"y_axis_: " << n.
y_axis_[0] <<
", " << n.
y_axis_[1] <<
", "
819 << n.
y_axis_[2] <<
", " << std::endl;
820 str <<
"z_axis_: " << n.
z_axis_[0] <<
", " << n.
z_axis_[1] <<
", "
821 << n.
z_axis_[2] <<
", " << std::endl;
824 str <<
"volume_: " << n.
volume_ << std::endl;
825 str <<
"diameter_: " << n.
diameter_ << std::endl;
826 str <<
"is_axon_: " << n.
is_axon_ << std::endl;
829 str <<
"tension_: " << n.
tension_ << std::endl;
838 if (mother_agentma) {
840 }
else if (mother_neurite) {
845 str <<
"mother_ " << mother << std::endl;
867 return bdm_static_cast<NeuriteElement*>(event.
new_agents[0]);
874 if (mother_neurite ==
nullptr ||
875 mother_neurite->GetDaughterRight() !=
nullptr) {
879 auto* proximal_ne = mother_neurite;
884 SetMother(mother_neurite->GetMother()->GetNeuronOrNeuriteAgentPtr());
900 proximal_ne->RemoveFromSimulation();
906 Fatal(
"NeuriteElement",
907 "Can't extend a side neurite since daughter_right is not a nullptr!");
912 return bdm_static_cast<NeuriteElement*>(event.new_agents[0]);
921 real_t new_length = param->neurite_default_actual_length;
923 real_t x_coord = std::sin(theta) * std::cos(phi);
924 real_t y_coord = std::sin(theta) * std::sin(phi);
925 real_t z_coord = std::cos(theta);
927 z_coord * soma->
kZAxis[0],
929 z_coord * soma->
kZAxis[1],
931 z_coord * soma->
kZAxis[2]};
934 auto new_begin_location = soma->
GetPosition() + (axis_direction * radius);
935 auto new_spring_axis = axis_direction * new_length;
937 auto new_mass_location = new_begin_location + new_spring_axis;
957 const Real3& direction) {
964 auto dir_1 = direction;
969 dir_1 = direction + proj;
1002 auto new_position = other_ml - (other_sa * distal_portion);
1018 const Real3& direction) {
1023 auto dir = direction;
1026 real_t angle_with_side_branch =
1028 if (angle_with_side_branch < 0.78 ||
1029 angle_with_side_branch > 2.35) {
1033 dir = direction_normalized + p;
1036 auto new_spring_axis = direction_normalized * length;
Contains code required by all agents.
void SetPropagateStaticness(bool value=true)
AgentPointer< TAgent > GetAgentPtr() const
Return agent pointer.
virtual Shape GetShape() const =0
void SetStaticnessNextTimestep(bool value) const
void CreateNewAgents(const NewAgentEvent &event, const std::initializer_list< Agent * > &prototypes)
virtual void RemoveFromSimulation()
static const Real3 kZAxis
Third axis of the local coordinate system.
static const Real3 kXAxis
First axis of the local coordinate system.
static const Real3 kYAxis
Second axis of the local coordinate system.
const Real3 & GetPosition() const override
real_t GetDiameter() const override
virtual void ForEachNeighbor(Functor< void, Agent * > &lambda, const Agent &query, void *criteria)=0
virtual Real4 Calculate(const Agent *lhs, const Agent *rhs) const
static void Fatal(const std::string &location, const Args &... parts)
Prints fatal error message.
void Normalize()
Normalize the array in-place.
MathArray GetNormalizedArray() const
Get a nomalized copy of the MathArray.
real_t Uniform(real_t max=1.0)
Random * GetRandom()
Returns a thread local random number generator.
ExecutionContext * GetExecutionContext()
Returns a thread local execution context.
static Simulation * GetActive()
This function returns the currently active Simulation simulation.
const Param * GetParam() const
Returns the simulation parameters.
const Real3 & GetZAxis() const
bool BranchPermitted() const
NeuriteElement * ExtendSideNeuriteElement(real_t length, real_t diameter, const Real3 &direction)
Extend a side neurite element and assign it to daughter right.
friend std::ostream & operator<<(std::ostream &str, const NeuriteElement &n)
real_t LengthToProximalBranchingPoint() const
void SetSpringConstant(real_t spring_constant)
NeuriteElement * Branch()
Create a branch for this neurite element.
void UpdateDependentPhysicalVariables() override
void Update(const NewAgentEvent &event) override
AgentPointer< NeuronOrNeurite > & GetMother()
Real3 TransformCoordinatesPolarToGlobal(const std::array< real_t, 2 > &position) const
P -> G : P -> L, then L -> G.
void CriticalRegion(std::vector< AgentPointer<>> *aptrs) override
Real3 TransformCoordinatesGlobalToLocal(const Real3 &position) const
real_t diameter_
NB: Use setter and don't assign values directly.
AgentPointer< NeuronOrNeurite > mother_
real_t GetDiameter() const override
Real3 x_axis_
First axis of the local coordinate system equal to cylinder axis.
void SetPosition(const Real3 &position) override
void UpdateRelative(const NeuronOrNeurite &old_relative, const NeuronOrNeurite &new_relative) override
Real3 CalculateDisplacement(const InteractionForce *force, real_t squared_radius, real_t dt) override
AgentPointer< NeuriteElement > daughter_left_
void SetDaughterRight(const AgentPointer< NeuriteElement > &daughter)
std::set< std::string > GetRequiredVisDataMembers() const override
NeuriteElement * SplitNeuriteElement(real_t distal_portion=0.5)
Split this neurite element into two segments.
void UpdateLocalCoordinateAxis()
void SetDaughterLeft(const AgentPointer< NeuriteElement > &daughter)
void Copy(const NeuriteElement &rhs)
Real3 OriginOf(const AgentUid &daughter_uid) const override
void Initialize(const NewAgentEvent &event) override
std::array< NeuriteElement *, 2 > Bifurcate()
Growth cone bifurcation.
void UpdateVolume()
Recomputes volume, after diameter has been changed.
const Real3 & GetPosition() const override
void ApplyDisplacement(const Real3 &displacement) override
real_t GetSpringConstant() const
void SetRestingLength(real_t resting_length)
real_t density_
NB: Use setter and don't assign values directly.
const AgentPointer< NeuriteElement > & GetDaughterRight() const
bool BifurcationPermitted() const
void InitializeSideExtensionOrBranching(NeuriteElement *mother, real_t length, real_t diameter, const Real3 &direction)
Real3 ProximalEnd() const
void RemoveDaughter(const AgentPointer< NeuriteElement > &daughter) override
StructureIdentifierSWC GetIdentifierSWC() const override
Real3 GetUnitaryAxisDirectionVector() const
Real3 position_
position_ is the middle point of cylinder
void InitializeNewNeuriteExtension(NeuronSoma *soma, real_t diameter, real_t phi, real_t theta)
TODO.
void SetDiameter(real_t diameter) override
void RetractTerminalEnd(real_t speed)
void SetAdherence(real_t adherence)
AgentPointer< NeuriteElement > daughter_right_
Real3 force_to_transmit_to_proximal_mass_
The part of the inter-object force transmitted to the mother (parent node)
real_t GetAdherence() const
void SetSpringAxis(const Real3 &axis)
bool has_neurite_neighbor_
Helper variable needed in CalculateDisplacement.
const Real3 & GetAxis() const
Returns the axis direction of a neurite element.
void SetDensity(real_t density)
void SetRestingLengthForDesiredTension(real_t tension)
const Real3 & GetSpringAxis() const
real_t adherence_
NB: Use setter and don't assign values directly.
int GetBranchOrder() const
const Real3 & GetYAxis() const
void ElongateTerminalEnd(real_t speed, const Real3 &direction)
void SetMassLocation(const Real3 &mass_location)
Real3 TransformCoordinatesPolarToLocal(const Real3 &position) const
void ChangeVolume(real_t speed)
real_t GetRestingLength() const
Real3 TransformCoordinatesLocalToPolar(const Real3 &position) const
void ChangeDiameter(real_t speed)
Real3 ForceTransmittedFromDaugtherToMother(const NeuronOrNeurite &mother)
void SetMother(const AgentPointer< NeuronOrNeurite > &mother)
Real3 y_axis_
Second axis of the local coordinate system.
void InitializeNeuriteBifurcation(NeuriteElement *mother, real_t length, real_t diameter, const Real3 &direction)
TODO.
Real3 z_axis_
Third axis of the local coordinate system.
void SetTension(real_t tension)
const Real3 & GetMassLocation() const
return end of neurite element position
void RemoveProximalNeuriteElement()
void SetActualLength(real_t actual_length)
Should not be used, since the actual length depends on the geometry.
const AgentPointer< NeuriteElement > & GetDaughterLeft() const
void UpdateDiameter()
Recomputes diameter after volume has changed.
void RunDiscretization() override
void InitializeSplitOrBranching(NeuriteElement *other, real_t distal_portion)
void MovePointMass(real_t speed, const Real3 &direction)
Real3 TransformCoordinatesGlobalToPolar(const Real3 &position) const
G -> L : G -> L, then L -> P.
const Real3 & GetXAxis() const
Real3 TransformCoordinatesLocalToGlobal(const Real3 &position) const
AgentPointer< NeuronOrNeurite > GetNeuronOrNeuriteAgentPtr() const
static Real3 Perp3(const Real3 &a, real_t random)
static Real3 RotAroundAxis(const Real3 &vector, real_t theta, const Real3 &axis)
static MathArray< real_t, N > CrossProduct(const MathArray< real_t, N > &a, const MathArray< real_t, N > &b)
static real_t AngleRadian(const Real3 &a, const Real3 &b)
static constexpr real_t kPi
value of pi
static Real3 ProjectionOnto(const Real3 &a, const Real3 &b)
InlineVector< Agent *, 3 > new_agents
virtual NewAgentEventUid GetUid() const =0
const TParamGroup * Get() const
real_t simulation_time_step
Contains the parameters to bifurcate a growth cone.
static const NewAgentEventUid kUid
This event splits the current neurite element into two elements and adds a new side branch as daughte...
static const NewAgentEventUid kUid
uint64_t & non_zero_neighbor_force
bool & has_neurite_neighbor
const InteractionForce * force
Real3 & force_from_neighbors
Real3 & force_on_my_mothers_point_mass
void operator()(Agent *neighbor, real_t squared_distance) override
Contains the parameters to extend a new neurite from a neuron soma.
static const NewAgentEventUid kUid
real_t neurite_default_actual_length
Contains the parameters to add a side neurite element.
static const NewAgentEventUid kUid
Contains the parameters to split a neurite element into two segments.
static const NewAgentEventUid kUid