package affectors; import main.Node; import main.Globals; /** * This affector implements one half of a constant delay through a von Forrester equation. * This affector represents the flux INTO the delayed node from the previously delayed node and * is for use on both membrane and cytoplasmic nodes. Use {@link VonForresterB_Aff} for the flux out of the delayed node. *

* Effectively, this is a bucket brigade, or conveyor belt, where the delay is implemented * as a series of nodes, each a delayed version of the previous. Using too few delay * nodes will result in lowpass filtering. In general, you should look at the highest * frequency/most rapid change you care about, and use as many delay nodes as necessary * to preserve the features you want. *

* The parameter v is the velocity or rate that one delay node transfers into the * next. It should be equal to the number of delay nodes divided by the maximal * delay. *

* Formula *
dNodeDelayN/dt = vNodeDelayN-1 *

* Parameters * * * * *
Current delayed node [NodeDelayN] The delayed node * being calculated
Previous delayed node [NodeDelayN-1] The delayed node * feeding into this delayed node
Velocity [v] The rate of transfer into & out of this node. Should * be equal to the number of delay nodes/time of delay
*

* Usage *
&nodeDelayN *

* &VonForresterA_ICAff nodeDelayN-1 v *
* &endnodeDelayN * * @author Kerry Kim * @see VonForresterB_ECAff * @see VonForresterA_ICAff * @see VonForresterB_ICAff */ public class VonForresterA_Aff extends Affector { /* These store references to the parameters used by the Affector. For instance, if the affector uses some rate as part of its formula, that rate should be a parameter and needs to be declared here. You should give these parameters good names, such as halfLife or rateConstant. The convention is that that first word in the name is lowercase and all subsequent words are uppercase. You should replace this comment with a description of the first parameter. */ /** The rate of transfer between von Forrester delay nodes. */ int v; static final String affectorDescription = "Introduces a constant delay in a cytoplasmic node through von Forrester method"; static final String [] nodeDescriptions = {"Previous delay node"}; static final String [] paramDescriptions = {"Velocity"}; static final int [] whichSides = {-1}; public VonForresterA_Aff() {} protected void setLabelsAndTypes() { setDescriptions(affectorDescription, nodeDescriptions, paramDescriptions); /* This tells the rest of Ingeneue whether this Affector is supposed to operate on Nodes that reside in the membrane. The default is that an Affector operates only on cytoplasmic Nodes, or if it operates on membrane Nodes then it only operates on the sum of the concentrations across all faces of the cell. In either of these cases, you can just delete this method call. Otherwise, you need to pass true as the first argument (indicating that Affector operates on membrane Nodes) and the sides of each Node as the second argument (see comment near whichSides above). */ setSided(true, whichSides); /* This tells the rest of Ingeneue whether the Affector uses the concentration of the Node whose value it is helping determine. For instance, a Decay Affector calculates its value based on the concentration of the Node it is decaying. On the other hand, a translation Affector produces the same amount of protein regardless of the concentration of the protein. In the first of these cases, you need to inform the rest of Ingeneue that the formula uses the concentration of the target Node. In the latter, you must inform Ingeneue that it doesn't. The default is to assume that the Affector doesn't use the target Node's concentration, so in that case you can just delete this method call. */ // setContainsTarget(true); /* These four flags tell the rest of Ingeneue some characteristics of the Affector. ... and george, you have to remind me what they do. */ this.Type[GUI_CAPABLE] = 1; this.Type[CERTIFICATION] = Affector.RETURNS_DERIV; this.Type[MATHTYPE] = Affector.KK; this.Type[TERMTYPE] = Affector.CONVERSION; } /* This is where the rest of Ingeneue gives this Affector indices to each parameter that it uses. You should make a line for each parameter in the same order as they are described in paramDescriptions above, and then assign the values from param_nums as shown in the example below. */ public void setParameterNumbers(int [] param_nums) { v = param_nums[0]; } /* This is the formula for this Affector. Use Nodes[a].getIntegrationValue(side) to get the value of a node, where a is the position of the node in the nodeDescriptions array (starting from 0). Use params[parameterIndex] to get the value of a parameter, where parameterIndex is the index value assigned in setParameterNumbers (for instance, firstParameter or secondParameter in the example above). Most Affectors should be multiplied by Globals.characteristicTime. This example is the formula for DecayAff. */ public float getValue(Node which_node) { return Globals.characteristicTime*Nodes[0].getIntegrationValue(side)*params[v]; } }