[docs]defset_pressure(self,pressure):"""Set new pressure."""pass
[docs]defstep_growth(self,current_volume,dt):"""Step through the growth controller to calculate normal growth. Returns new pressure. """pass
[docs]defstep_divided(self,current_volume,dt):"""Step through the growth controller after division."""pass
[docs]classPIDController(GrowthController):"""Class to control growth by a PID controller, in which changes to a cell's internal pressure governs how much it grows in the next frame. Attributes: growth_type (Growth): Type of growth exhibited by cells. growth_rate (float): Rate of growth of cells. initial_pressure (float): Initial pressure of cells. target_volume (float): Target volume of cells. Kp (float): P variable of the PID controller. Ki (float): I variable of the PID controller. Kd (float): D variable of the PID controller. """def__init__(self,current_volume,growth_type=GrowthType.LINEAR,growth_rate=1,initial_pressure=0.01,target_volume=30,Kp=0.05,Ki=0.00001,Kd=0.5,):self.growth_type=growth_typeself.growth_rate=growth_rate# in cubic microns per frameself.Kp=Kpself.Ki=Kiself.Kd=Kdself.PID_scale=15self.initial_pressure=initial_pressureself.target_volume=target_volumeself.integral=0self.previous_error=0self.previous_pressure=self.initial_pressureself.next_volume=current_volume
[docs]defstep_growth(self,current_volume,dt):"""Step through the growth controller to calculate normal growth. Args: current_volume (float): Current volume of the cell. dt (float): Time step. Returns: float: The pressure at the next time step. """matchself.growth_type:caseGrowthType.LINEAR:self.next_volume+=self.growth_rate*dtcaseGrowthType.EXPONENTIAL:self.next_volume*=1+self.growth_rate*dtcaseGrowthType.LOGISTIC:self.next_volume=self.next_volume*(1+self.growth_rate*(1-self.next_volume/self.target_volume)*dt)case_:raiseValueError("Growth type must be one of LINEAR, EXPONENTIAL, or LOGISTIC.")self.next_volume=min(self.next_volume,self.target_volume)volume_deviation=1-current_volume/self.next_volume# Update pressure based on PID outputerror=volume_deviationintegral=self.integral+errorderivative=error-self.previous_errorpid=self.Kp*error+self.Ki*integral+self.Kd*derivativenext_pressure=self.previous_pressure+pid*self.PID_scale# Update previous error and pressure for the next iterationself.previous_error=errorself.integral=integralself.previous_pressure=next_pressurereturnnext_pressure