def __init__(self, filament, order, *args, **keyargs): """ コンストラクタ 初期化時に呼ばれる 引数: filament: 粒子を内包するフィラメントのインスタンス order: フィラメント内の順番 """ # 内部のインスタンスへ引数のリンクを保存 self.order = order self.filament = filament # フィラメントを内包する培地インスタンスのリンクを保存 self.medium = self.filament.medium # 先頭粒子か後続粒子か if self.is_head(): # 配置時の向きはランダム init_pos_th = random.random() * (2*math.pi) - math.pi # 配置時の場所はfilament_init_rangeの範囲内 init_pos_r = random.random() * config.getfloat("lc","filament_init_range") self.x = self.n_x = math.cos(init_pos_th) * init_pos_r self.y = self.n_y = math.sin(init_pos_th) * init_pos_r self.th = self.n_th = random.random() * (2*math.pi) - math.pi # 速度はinit_verocityに従う self.v = self.n_v = config.getfloat("lc","init_verocity") else: # 後続粒子は1つ前の粒子に追従する self.x = self.n_x = self.prev().x self.y = self.n_y = self.prev().y self.th = self.n_th = self.prev().th self.v = self.n_v = self.prev().v self.w = 0.0 # 角速度を初期化
def factory(self): for p in self.particles: p.factory() if len(self.particles) > config.getfloat("lc","filament_init_length") and random.random() < (config.getfloat("lc","division_rate")/self.medium.filament_num): self.division() if random.random() < (config.getfloat("lc","growth_rate")/self.medium.filament_num): self.growth() if random.random() < (config.getfloat("lc","switch_rate")/self.medium.filament_num): self.switch()
def interact_neighborhood(self): """ 近傍粒子との相互作用を行う """ neighborhoods = [] # 近傍粒子へのリンクを格納するテンポラリ # 角速度=後続粒子の向きの変化量の平均 # curv_sin_sum,curv_cos_sumは平均を取るための合計値を格納するテンポラリ curv_sin_sum = 0.0 # sin値の合計 curv_cos_sum = 0.0 # cos値の合計 # 培地内のすべてのフィラメントのすべての粒子を総覧 for f in self.medium.filaments: for p in f.particles: dx = math.fabs(self.x - p.x) dy = math.fabs(self.y - p.y) dl = math.sqrt(math.pow(dx,2) + math.pow(dy, 2)) # 近傍範囲内の粒子ならテンポラリにリンクを格納 if dl < config.getfloat("lc","neighbor_range"): neighborhoods.append(p) # この粒子の同一フィラメント内の他の粒子の場合、 # 角速度とする粒子数の範囲内で # テンポラリの合計値を更新する if f == self.filament and p.order < config.getfloat("lc","angle_ave_step"): # 変化量のsin,cos値の合計をとる curv_sin_sum = curv_sin_sum + math.sin(p.w) curv_cos_sum = curv_cos_sum + math.cos(p.w) # 近傍粒子の計算 th_sin_sum = 0.0 # 近傍粒子の向きのsin値合計 th_cos_sum = 0.0 # 近傍粒子の向きのcos値合計 for p in neighborhoods: # ラジアンの合計値を計算するために符号を調整 # 向き同士の成す角が鈍角なら向きを反転する必要がある if math.cos(self.th - p.th) < 0: th_sin_sum = th_sin_sum - math.sin(p.th) th_cos_sum = th_cos_sum - math.cos(p.th) else: th_sin_sum = th_sin_sum + math.sin(p.th) th_cos_sum = th_cos_sum + math.cos(p.th) # 近傍粒子の向きの合計値から平均値を計算 th_sin_ave = th_sin_sum / len(neighborhoods) th_cos_ave = th_cos_sum / len(neighborhoods) # 平均値からこの粒子の次の向きを計算 candidate_th = math.atan2(th_sin_ave, th_cos_ave) # 角速度を計算するため、後続粒子の平均とする範囲内の粒子の、 # 角度変化量の平均を計算する curv_sin_ave = curv_sin_sum / config.getfloat("lc","angle_ave_step") curv_cos_ave = curv_cos_sum / config.getfloat("lc","angle_ave_step") curv_ave = math.atan2(curv_sin_ave, curv_cos_ave) # ガウス分布に従う摂動を計算する rand = random.gauss(curv_ave*config.getfloat("lc","amplitude_rate"), config.getfloat("lc","amplitude_std")) # 次の向きに摂動を加える candidate_th = candidate_th + rand self.drive(candidate_th, self.v)
def __init__(self, *args, **keyargs): self.filament_num = config.getfloat("lc","filament_init_num") for i in range(config.getint("lc","filament_init_num")): self.setout()