//Sensor.cpp : implementation file
//Sensors work like Hodgkin-Huxley channels, possessing 1st order kinetics for
//activating & inactivating and a maximum value; they achieve a value which is
//compared to its target in aiming for a particular neural activity pattern

#include "stdafx.h"
#include "GlobalDefs.h"
#include "DefaultParams.h"
#include "Sensor.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CSensor

IMPLEMENT_SERIAL(CSensor, CObject, _VERSION_NUMBER)


CSensor::CSensor(int type, BOOL exists) //constructor
{
	m_type = type;  //type of sensor, e.g. _DC, _Fast, _Slow
	m_m = 0.0;
	m_h = 0.0;
	m_AveValue = 0.0;
	m_bExists = exists;
	switch (type) {
		case _DC:
			m_Target = _DC_TARGET;
			m_ValueMax = _DC_VALUEMAX;
			m_tau_m = _DC_TAU_M;
			m_tau_h = _DC_TAU_H;  //dummy--not currently used
			m_m_inf_Z = _DC_M_INF_Z; //where m_inf curve = 1/2
			m_h_inf_Z = _DC_H_INF_Z; //dummy--not currently used
			m_p = _DC_NUM_M;
			m_q = _DC_NUM_H; break;
		case _Slow:
			m_Target = _Slow_TARGET;
			m_ValueMax = _Slow_VALUEMAX;
			m_tau_m = _Slow_TAU_M;
			m_tau_h = _Slow_TAU_H;
			m_m_inf_Z = _Slow_M_INF_Z; //where m_inf curve = 1/2
			m_h_inf_Z = _Slow_H_INF_Z; //where h_inf curve = 1/2
			m_p = _Slow_NUM_M;
			m_q = _Slow_NUM_H; break;
		case _Fast:
			m_Target = _Fast_TARGET;
			m_ValueMax = _Fast_VALUEMAX;
			m_tau_m = _Fast_TAU_M;
			m_tau_h = _Fast_TAU_H;
			m_m_inf_Z = _Fast_M_INF_Z; //where m_inf curve = 1/2
			m_h_inf_Z = _Fast_H_INF_Z; //where h_inf curve = 1/2
			m_p = _Fast_NUM_M;
			m_q = _Fast_NUM_H; break;
	}
}

CSensor::~CSensor()
{
}

void CSensor::m_Update_m(double I_Ca_per_nF, double dt)
{
	m_m = ((m_m_inf(I_Ca_per_nF)*(1. - exp(-dt/m_tau_m))) + (m_m*exp(-dt/m_tau_m)));
}

void CSensor::m_Update_h(double I_Ca_per_nF, double dt)
{
	m_h = ((m_h_inf(I_Ca_per_nF)*(1. - exp(-dt/m_tau_h))) + (m_h*exp(-dt/m_tau_h)));
}

void CSensor::m_Update_AveValue(double tau_eff, double dt)
{
	m_AveValue = ((m_Value()*(1. - exp(-dt/tau_eff))) + (m_AveValue*exp(-dt/tau_eff)));
}

double CSensor::m_Value() 
{
	return (m_ValueMax * pow(m_m, m_p) * pow(m_h, m_q));
}

double CSensor::m_Error()
{ 
	return (m_Target - m_Value());
}

//next 2 functions return m_infinity, h_infinity
double CSensor::m_m_inf(double I_Ca_per_nF) 
{
	return (1.0/(1.0 + exp(m_m_inf_Z + I_Ca_per_nF)));
}

double CSensor::m_h_inf(double I_Ca_per_nF) 
{
	return (1.0/(1.0 + exp(-I_Ca_per_nF - m_h_inf_Z)));
}

/////////////////////////////////////////////////////////////////////////////
// CSensor serialization

void CSensor::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		ar << m_type;
		ar << m_m;
		ar << m_h;
		ar << m_AveValue;
		ar << m_bExists;
		ar << m_Target;
		ar << m_ValueMax;
		ar << m_tau_m;
		ar << m_tau_h;
		ar << m_m_inf_Z;
		ar << m_h_inf_Z;
		ar << m_p;
		ar << m_q;
	}
	else
	{
		ar >> m_type;
		ar >> m_m;
		ar >> m_h;
		ar >> m_AveValue;
		ar >> m_bExists;
		ar >> m_Target;
		ar >> m_ValueMax;
		ar >> m_tau_m;
		ar >> m_tau_h;
		ar >> m_m_inf_Z;
		ar >> m_h_inf_Z;
		ar >> m_p;
		ar >> m_q;
	}

}