var oligowt=0;
var dh=0;//deltaH. Enthalpy
var ds=0;// deltaS Entropy
var mg=0; 
var move=true
function reevaluate(form)
	{
	if (cleanseq(form.oligo.value)!="")
		{
		move=false;
		oligocalc(form);
		move=true;
		}		
	}

function magalert()
	{
	var mag_disc="We have found that most melting temperature calculations do not take into account the affects of magnesium on helix stability. Therefore, most empirical guidelines used to design experiments will not apply when the magnesium effects are included. Therefore we have included the option to take the magnesium into account if it is desirable, but have not included it as the default settings. Taking the magnesium into account will generally raise the theoretical melting temperature by about 5-8°C for oligonucleotides in a 1.5mM Mg+2 solution.";
	alert(mag_disc);
	}

function primeralert()
	{
	var primer_disc="The concentrations of the primer and the target sequence will change dramatically during a PCR reaction, but generally this will not make a significant difference to the calculated melting temperature. A standard 50µl reaction may contain 0.1µg of human genomic DNA as a template and is 0.5µM in each primer. This reaction would be approximately 2 femtomolar (2 x 10^-15M) in for each single copy target. At the end of 30 cycles, this same reaction may produce about 0.5µg of a specific 1kb amplimer which gives a final concentration of 15nM. In this case the primer concentration will not change significantly and thus will remain much greater than the target concentration.";
	alert(primer_disc);
	}

function countbase(oligo, base)//counts the number of times a specific base appears in the sequence
{
	var checkStr = oligo;
  	var number= 0;
  	var other = 0;
  	for (i = 0;  i < checkStr.length;  i++)
  	{
    	ch = checkStr.charAt(i);
    	if (ch == base)
		{
		number++;
		}
   	}
	return number;
}

function cleanseq(seq) //changes all bases to uppercase for easier manipulation and removes any nonbase characters.
{
	var newseq="";
	seq=seq.toUpperCase();
	for (i = 0; i < seq.length; i++)
		{	
		if ((seq.charAt(i)=="G")||(seq.charAt(i)== "A")||(seq.charAt(i)== "T")||(seq.charAt(i)== "C"))
			{
			newseq=newseq+seq.charAt(i);
			}
		}
	return newseq;
}

function mw (seq) //calculates the molecular weight of an oligo based on the specific weights of each nucleotide
{
	var mw=-61;// (-79 for missing phosphate (PO3) at the 5’ end, +1 for the hydrogen that replaces it & +17 for a 3’ hydroxyl)  
	for (i = 0; i < seq.length; i++)
		{	
		if (seq.charAt(i)=="G")
			{
			mw+=329.2;
			}
		if (seq.charAt(i)== "A")
			{
			mw+=313.2;
			}
		if (seq.charAt(i)== "T")
			{
			mw+=304.2;
			}
		if (seq.charAt(i)== "C")
			{
			mw+=289.2;
			}
		}
	if (phos)
		{
		mw+= 78 //79 for the phosphate (PO3), -1 for the hydrogen that is lost
		}
	return (mw)
}

	

function basic (seq,G,A,C,T)//basic melting tempurature calculations
{
	if (seq.length < 14)
	{
		td=2*(A+T)+4*(G+C);
	}
	else
	{
		td = Math.round(64.9 + 41*((G + C -16.4)/seq.length));
	}
	return td; 
}

function ion(seq,salt,GC)//salt adjusted meling temp. Please see TB254 for this formula
{

	tm=81.5 + 7.21* Math.log(salt)+ (0.41*GC)-(675/seq.length);
	return Math.round(tm);
}

function terminalcorrections(seq)//helix initiation corrections from Santalucia 1998 & Allawi & Santalucia 1997
	{
	var deltah=0;
	var deltas=0;
	if ((seq.charAt(0)=="G")||(seq.charAt(0)=="C"))
		{
		deltah+=0.1;
		deltas+=-2.8;
		}
	if((seq.charAt(0)=="A")||(seq.charAt(0)=="T"))
		{
		deltah+=2.3;
		deltas+=4.1;
		}
		
	if ((seq.charAt(seq.length-1)=="G")||(seq.charAt(seq.length-1)=="C"))
		{
		deltah+=0.1;
		deltas+=-2.8;
		}
	if((seq.charAt(seq.length-1)=="A")||(seq.charAt(seq.length-1)=="T"))
		{
		deltah+=2.3;
		deltas+=4.1;
		}
	dh+=deltah;
	ds+=deltas;
	}

function saltcorrections(seq,salt)//changes to ds dependant on the salt concentration & sequence length
	{
	salt+=(mg/1E3 * 140);//convert to moles and then adjust for greater stabilizing effects of Mg compared to Na or K. See von Ahsen et al 1999	
	var deltas=0;
	deltas+=0.368 * (seq.length-1)* Math.log(salt);//This comes from von Ahsen et al 1999
	ds+=deltas;
	}
	
function stack(seq,salt, primer)// base stacking calculations. 
{
ds=0;
dh=0;//deltaH. Enthalpy
	var R=1.987; //universal gas constant in Cal/degrees C*Mol
	saltcorrections(seq,salt);
	terminalcorrections(seq);
	K=(primer/2) * 1E-9; //converts from nanomolar to Molar. Note this ignores the contribution of the target since this is << than primer concentration.
	for (i = 0; i < seq.length; i++)//adds up dh and ds for each 2 base combination. dh is in kcal/mol. ds is in cal/Kelvin/mol
		{	
		if (seq.charAt(i)=="G")
			{
			if (seq.charAt(i+1)=="G")
				{
				dh+=-8;
				ds+=-19.9;
				}
			if (seq.charAt(i+1)=="A")
				{
				dh+=-8.2;
				ds+=-22.2;
				}
			if (seq.charAt(i+1)=="T")
				{
				dh+=-8.4;
				ds+=-22.4;
				}
			if (seq.charAt(i+1)=="C")
			//These values where fixed on 4/23/2008. They were dh = -10.6 & ds = -27.2
			//The new values have been double check against Santalucia 1998 
				{
				dh+=-9.8;
				ds+=-24.4;
				}
			}
		if (seq.charAt(i)=="A")
			{
			if (seq.charAt(i+1)=="G")
				{
				dh+=-7.8;
				ds+=-21;
				}
			if (seq.charAt(i+1)=="A")
				{
				dh+=-7.9;
				ds+=-22.2;
				}
			if (seq.charAt(i+1)=="T")
				{
				dh+=-7.2;
				ds+=-20.4;
				}
			if (seq.charAt(i+1)=="C")
				{
				dh+=-8.4;
				ds+=-22.4;
				}
			}
		if (seq.charAt(i)=="T")
			{
			if (seq.charAt(i+1)=="G")
				{
				dh+=-8.5;
				ds+=-22.7;
				}
			if (seq.charAt(i+1)=="A")
				{
				dh+=-7.2;
				ds+=-21.3;
				}
			if (seq.charAt(i+1)=="T")
				{
				dh+=-7.9;
				ds+=-22.2;
				}
			if (seq.charAt(i+1)=="C")
				{
				dh+=-8.2;
				ds+=-22.2;
				}
			}
		if (seq.charAt(i)=="C")
			{
			if (seq.charAt(i+1)=="G")
				{
				dh+=-10.6;
				ds+=-27.2;
				}
			if (seq.charAt(i+1)=="A")
				{
				dh+=-8.5;
				ds+=-22.7;
				}
			if (seq.charAt(i+1)=="T")
				{
				dh+=-7.8;
				ds+=-21;
				}
			if (seq.charAt(i+1)=="C")
				{
				dh+=-8;
				ds+=-19.9;
				}
			}
		}
	tm= ((1000* dh)/(ds+(R * Math.log(K))))-273.15;	//The actual answer!
	return tm;	
	}
	
function oligocalc(form)
{
	if (form.Primer.options[form.Primer.selectedIndex].value!="false")//check to see if they have selected a Promega primer
		{
		form.oligo.value=form.Primer.options[form.Primer.selectedIndex].value; //If they have selected a Promega primer move its sequence to the correct location
		}
	else
		{
		form.Primer.options.value="false";
		}
	seq=form.oligo.value;
	realseq=cleanseq(seq); //remove non-bases from the sequence
	form.oligo.value=realseq; //show the sequence that will actually be used for calculations
	if ((getselectedbutton(form.KitSalt)!="None")|| (isnum(form.na.value, "salt concentration", "plus")))	
		{
		if (getselectedbutton(form.KitSalt)!="None")
			{
			salt=(getselectedbutton(form.KitSalt)/1E3);
			}
		else
			{
			salt=(form.na.value/1E3);//convert to molar
			}		
		}
	if (form.magnesium.checked)
		{
		if(isnum(form.Mg.value,"Magnesium concentration", "plus"))
			{
			mg=form.Mg.value;
			}
		}
		else
			{
			mg=0;
			}
		
	if (isnum(form.primer_conc.value, "primer concentration", "plus","no"))
		{
		primer=form.primer_conc.value;
		}
	form.length.value=(realseq.length);
	phos=form.phosphate.checked;
	G=countbase (realseq, "G");
	A=countbase (realseq, "A");
	T=countbase (realseq, "T");
	C=countbase (realseq, "C");
	GC=100*((G+C)/(G+A+T+C));
	form.GC.value=(Math.round(100*GC)/100);
	form.basic.value=basic(realseq,G,A,C,T);
	form.ion.value=ion(realseq,salt,GC);
	form.stack.value=Math.round(stack(realseq,salt,primer));
	oligowt=Math.round(10*mw(realseq,phos)/10);
	form.mw.value=oligowt;
	form.deltaH.value=Math.round(dh);
	form.deltaS.value=Math.round(ds);
	form.SequenceAnalyzed.value=realseq;	
	if(move)
		{
		document.location.href="#melt_results";
		}
}
