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
*/
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;
	}
}
&nodex
&EnhancerRegionAff	H_nodex
&endnodex    &SaturatingEnhancerAff  nodex  K_nodex	nu_nodex
		&endEnhancerRegionAff		&SumAff
				&endSaturatingEnhancerAff			[in here are some other affectors]
					&endSumAff