package affectors; import java.io.PrintWriter; import java.util.Enumeration; import java.util.Vector; import main.Node; import main.Cell; import main.Globals; /** This is the wrapper for meta-affectors which need to be put through a saturating function. Use around Sum and Product Affectors when the terms inside of those don't saturate on their own. SaturationEnhancerAff can have only one affector inside of it, which will generally be either a ProductAff or SumAff. The sub-affector's value is put through a saturating S-shaped function, similar to the function in the regular transcription Affectors. If A is the value of the sub-affector than SaturatingEnhancerAff's value is:
A^nu / (K^nu + A^nu)
which is just the Phi function
SaturatingEnhancerAff should always be used inside of EnhancerRegionAff.

Formula
dnodex/dt = SubAffectorValue^nu / (K^nu + SubAffectorValue^nu)

Parameters
Half-max activation [K_nodex] The value of the sub-affector at which the mRNA is transcribed at half its maximal rate.
Cooperativity [nu_nodex] The non-linearity in transcription rates response to the sub-affectors value.

Usage
&nodex

&EnhancerRegionAff H_nodex
&SaturatingEnhancerAff nodex K_nodex nu_nodex
&SumAff
[in here are some other affectors]
&endSumAff
&endSaturatingEnhancerAff
&endEnhancerRegionAff
&endnodex */ public class SaturationEnhancerAff extends EnhancerRegionAff { int kParam, nuParam; static final String desc = "Wraps other meta-affectors with saturating function"; static final String [] paramDescriptions = {"Half-life"}; static final int [] whichSides = { -1 }; public SaturationEnhancerAff() { } protected void setLabelsAndTypes() { setDescriptions(this.desc, null, paramDescriptions); setSided(true, whichSides); this.Type[GUI_CAPABLE] = 0; this.Type[CERTIFICATION] = Affector.RETURNS_DERIV; this.Type[MATHTYPE] = Affector.FF; // ???? None really fit this.Type[TERMTYPE] = Affector.PRODUCTION; } public void setParameterNumbers(int [] param_nums) { halfLifeParam = param_nums[0]; if(param_nums.length == 3) { kParam = param_nums[1]; nuParam = param_nums[2]; } else { kParam = -1; nuParam = -1; } } /** Overrides Affector.getValue() to multiply together the values from all the subsidiary affectors. */ public float getValue(Node which_node) { float value = affectors[0].getValue(which_node); if(kParam != -1) value = Phi(value, params[kParam], params[nuParam]); else value = value / (1 + value); if(value > 1) System.out.println("Value > 1 " + Globals.time); return (Globals.characteristicTime / params[halfLifeParam]) * value; } /** Overrides Affector.getNCValue() to multiply together the values from all the subsidiary affectors. */ public float getNCValue(Node which_node) { if(containsTarget) { float value = affectors[0].getNCValue(which_node); if(kParam != -1) value = Phi(value, params[kParam], params[nuParam]); else value = value / (1 + value); return (Globals.characteristicTime / params[halfLifeParam]) * value; } else return super.getNCValue(which_node); } /* The rest of these functions are overrides of Affector functions so that they work right for this class. */ public Affector copy() { SaturationEnhancerAff element = null; try { element = (SaturationEnhancerAff)this.clone(); } catch(CloneNotSupportedException e) { System.out.println("Error cloning SaturationEnhancerAff: " + e.toString()); } element.affectors = new Affector[1]; element.affectors[0] = affectors[0].copy(); return element; } }