/////////////////////////////////////////////////////////////////////////////
// Name:        gr4j.h
// Author:      Stefan Liersch
// Contact:		stefan.liersch@ufz.de stefan.liersch@gmail.com
// Created:     2007-02-28
// modified:	2008-01-22
//
/////////////////////////////////////////////////////////////////////////////

//-------------------------------------------------------------------
#include "gr4j_cal.h"
#include "convert_sl.h"

#include <time.h>	// random numbers initialization
#include <string>
//-------------------------------------------------------------------

//-------------------------------------------------------------------
//		CONSTRUCTOR
//-------------------------------------------------------------------
Cgr4j_cal::Cgr4j_cal()
{
	//-----------------------------------------------------
	// 1. Info...
	Set_Name("GR4J Calibration");

	Set_Author("copyrights (c) 2007 Stefan Liersch");

	Set_Description("The Rainfall-Runoff Model GR4J \n \n \n"
		"Reference: \n \n"
		"Perrin, C., Michel, C., Andreassian, V. (2003). \n"
		"Improvement of a parsimonious model for streamflow simulation \n"
		"Journal of Hydrology, 279, p. 275-289. \n"
	);

	///////////////////////////////////////////////////////////////////
	// FIRST MODULE DIALOG
	_CreateDialog1();
	///////////////////////////////////////////////////////////////////
}
//-------------------------------------------------------------------

//-------------------------------------------------------------------
//	DESTRUCTOR
//-------------------------------------------------------------------
Cgr4j_cal::~Cgr4j_cal()
{
}
//-------------------------------------------------------------------




///////////////////////////////////////////////////////////////////////
//
//		ON_EXECUTE
//
///////////////////////////////////////////////////////////////////////

bool Cgr4j_cal::On_Execute()
{
	//---------------------------------------------------------------
	//				PARAMETERS
	//---------------------------------------------------------------
	// efficiency
	string			nse;
	string			nse_text;
	double			NSE_temp	= 0.0;
	double			NSE_MAX		= -9999.9;

	CSG_Table		*pTable;
	// table field numbers
	int				dateField;
	int				dischargeField;
	int				pcpField;
	int				pet_tmpField;
	// used time series (0 = ETp, 1 = temperature)
	int				Choice_ETp_TMP;

	CSG_String		date1, date2;
	int				first, last;
	double			Latitude;

	// Assign Parameters from Module Dialog
	//---------------------------------------------------------
	pTable			= Parameters("TABLE")			->asTable();
	// Field numbers
	dateField		= Parameters("DATE_Field")		->asInt();
	dischargeField	= Parameters("DISCHARGE_Field")	->asInt();
	pcpField		= Parameters("PCP_Field")		->asInt();
	pet_tmpField	= Parameters("ETP_TMP_Field")	->asInt();
	// used time series
	Choice_ETp_TMP	= Parameters("ETP_TMP_TS")		->asInt();
	m_bSnowModule	= Parameters("bSNOW")			->asBool();
	m_obj_func		= Parameters("OBJ_FUNC")		->asInt();
	m_nsim			= Parameters("NSIM")			->asInt();
	m_NSE_MIN		= Parameters("MIN_NSE")			->asDouble();
	// Parameters
	X_lb.X1			= Parameters("X1_lb")			->asDouble();
	X_ub.X1			= Parameters("X1_ub")			->asDouble();
	X_lb.X2			= Parameters("X2_lb")			->asDouble();
	X_ub.X2			= Parameters("X2_ub")			->asDouble();
	X_lb.X3			= Parameters("X3_lb")			->asDouble();
	X_ub.X3			= Parameters("X3_ub")			->asDouble();
	X_lb.X4			= Parameters("X4_lb")			->asDouble();
	X_ub.X4			= Parameters("X4_ub")			->asDouble();
	//---------------------------------------------------------

	//---------------------------------------------------------
	// Create Second Dialog and assign parameters
	if ( _CreateDialog2(pTable, dateField, date1, date2, Choice_ETp_TMP, m_bSnowModule, Latitude, m_area) )
	{
		//---------------------------------------------------------

		//---------------------------------------------------------
		// searching the first and the last record of the time range
		gr4j.AssignFirstLastRec(*pTable, first, last, date1, date2, dateField);
		m_nValues = last - first + 1;
		//---------------------------------------------------------

		//---------------------------------------------------------
		m_pInput = new CInputData(m_nValues);
		// initialize struct m_pInput
		_InitInput(m_pInput, m_nValues, Choice_ETp_TMP, m_area, Latitude, pTable,
					dateField, dischargeField, pcpField, pet_tmpField,
					first, last);
		//---------------------------------------------------------


		//---------------------------------------------------------
		//		CREATE OUTPUT TABLES
		//---------------------------------------------------------
		Process_Set_Text("GR4J Simulation...");
		m_pTable_out = SG_Create_Table();
		m_pTable_sim = SG_Create_Table();
		_CreateTableCal();
		_CreateTableSim();
		m_counter = 0;
		//---------------------------------------------------------


		//---------------------------------------------------------
		//		MONTE CARLO SIMULATION
		//---------------------------------------------------------
		// initialize random function
		srand((unsigned) time(NULL)); // using time.h

		for (int sim = 0; sim < m_nsim && Set_Progress(sim, m_nsim); sim++)
		{
			_RandomParms(m_X, m_snowparms);
			_Simulate(m_X, m_snowparms);

			//		Calculate Efficiency
			m_NSE			= model_tools::CalcEfficiency(m_pInput->Q_obs_mmday, m_p_Q_sim_mmday, m_nValues);
			m_NSE_highflow	= model_tools::Calc_NSE_HighFlow(m_pInput->Q_obs_mmday, m_p_Q_sim_mmday, m_nValues);
			m_NSE_lowflow	= model_tools::Calc_NSE_LowFlow(m_pInput->Q_obs_mmday, m_p_Q_sim_mmday, m_nValues);

			// write current efficiency value to status bar
			NSE_temp = gr4j.Assign_NSE_temp(m_obj_func, m_NSE, m_NSE_highflow, m_NSE_lowflow);

			if (NSE_temp > m_NSE_MIN)
			{
				if (NSE_temp > NSE_MAX)
				{
					NSE_MAX = NSE_temp;
					nse = convert_sl::Double2String(NSE_MAX).c_str();
					nse_text = "max. NSE: " + nse;
					Process_Set_Text(nse_text.c_str());
					
					_AssignBestSettings();
				}

				_WriteOutputTable();
			}

			//---------------------------------------------------------
		} // end for (int sim...)
		//---------------------------------------------------------

		_Simulate(m_BestParms, mBestSnowParms);
		_WriteTableSim();

		m_pTable_out->Set_Name("GR4J_Cal");
		Parameters("TABLEout")->Set_Value(m_pTable_out);
		m_pTable_sim->Set_Name("GR4J_Sim");
		Parameters("TABLEsim")->Set_Value(m_pTable_sim);

		delete m_pInput;
		delete[] m_p_Q_sim_mmday;
		if (Choice_ETp_TMP == 1)
			delete[] m_pTMP;


		return(true);
	}
	return(false);
}
//-------------------------------------------------------------------



///////////////////////////////////////////////////////////////////////
//
//		INITIALIZE INPUT POINTERS / DATA
//
///////////////////////////////////////////////////////////////////////

//-------------------------------------------------------------------
void Cgr4j_cal::_InitInput(CInputData* m_pInput, int m_nValues, int Choice_ETp_TMP,
						   double area, double Latitude, CSG_Table* pTable,
						   int dateField, int dischargeField,
						   int pcpField, int pet_tmpField,
						   int first, int last)
{
	int j, k;
	m_p_Q_sim_mmday = new double[m_nValues];
	if (Choice_ETp_TMP == 1)
	{
		m_pTMP = new double[m_nValues];
	} else {
		m_pTMP = NULL;
	}
	//---------------------------------------------------------
	// assign data to struct m_pInput
	for (j = 0, k = first; j < m_nValues, k < last + 1; j++, k++)
	{
		// put the date string into the vector
		m_pInput->date[j].append(pTable->Get_Record(k)->asString(dateField));
		// convert Q_obs_mmday from m3/s to mm/day
		m_pInput->Q_obs_mmday[j] = (pTable->Get_Record(k)->asDouble(dischargeField) * 86.4 / area);
		m_pInput->precipitation[j] = (pTable->Get_Record(k)->asDouble(pcpField));
		if (Choice_ETp_TMP == 0) // if ETp data was selected
			m_pInput->ETp[j] = (pTable->Get_Record(k)->asDouble(pet_tmpField));
		else
			m_pTMP[j] = (pTable->Get_Record(k)->asDouble(pet_tmpField));
	}
	// if no ETp data available the temperature time series is used
	// to calculate ETp after Hamon (1961)
	if (Choice_ETp_TMP == 1) // if temperature data was selected
	{
		int first_year, month, day;
		convert_sl::Get_Date_Int(m_pInput->date[0], first_year, month, day);
		// calculate ETp
		m_pETp = new CpET(m_pTMP, m_nValues, Latitude, first_year);
		// assign m_pETp to m_pInput->ETp
		for (int i = 0; i < m_nValues; i++)
			m_pInput->ETp[i] = m_pETp->Get_pET_Hamon(i);

		delete m_pETp;
		if (m_pTMP) delete[] m_pTMP;
	}
}
//-------------------------------------------------------------------



///////////////////////////////////////////////////////////////////////
//
//		STREAMFLOW SIMULATION
//
///////////////////////////////////////////////////////////////////////

//-------------------------------------------------------------------
void Cgr4j_cal::_RandomParms(GR4J_Parameters& X, CSnowParms& snowparms)
{
	X.X1 = model_tools::Random_double(X_lb.X1, X_ub.X1);
	X.X2 = model_tools::Random_double(X_lb.X2, X_ub.X2);
	X.X3 = model_tools::Random_double(X_lb.X3, X_ub.X3);
	X.X4 = model_tools::Random_double(X_lb.X4, X_ub.X4);

	if (m_bSnowModule)
	{
		snowparms.T_Rain = model_tools::Random_double(mT_Rain_lb, mT_Rain_ub);
		snowparms.T_Melt = model_tools::Random_double(mT_Melt_lb, mT_Melt_ub);
		snowparms.DD_FAC = model_tools::Random_double(mDD_FAC_lb, mDD_FAC_ub);
	}
}
//-------------------------------------------------------------------

void Cgr4j_cal::_Simulate(GR4J_Parameters X, CSnowParms snowparms)
{
	if (m_bSnowModule)
	{
		m_pSnowModule = new CSnowModule(m_pTMP, m_pInput->precipitation, m_nValues,
			snowparms.T_Rain, snowparms.T_Melt, snowparms.DD_FAC);

		m_pGR4J = new Cgr4j(m_pInput, m_pTMP, m_pSnowModule);

		m_pGR4J->Simulation(m_pInput, X);

		for (int i = 0; i < m_nValues; i++)
			m_p_Q_sim_mmday[i] = m_pGR4J->Q_sim[i];

		// delete pointers that were created with 'new' in gr4j.Simulation()
		m_pGR4J->free_memory();
		delete m_pGR4J;
		delete m_pSnowModule;
	} else {

		gr4j.Simulation(m_pInput, X);
		for (int i = 0; i < m_nValues; i++)
			m_p_Q_sim_mmday[i] = gr4j.Q_sim[i];
		// delete pointers that were created with 'new' in gr4j.Simulation()
		gr4j.free_memory();
	}
}
//-------------------------------------------------------------------


//-------------------------------------------------------------------
//		STORE SETTINGS OF BEST SIMULATION
//-------------------------------------------------------------------
void Cgr4j_cal::_AssignBestSettings()
{
	m_BestParms.X1	= m_X.X1;
	m_BestParms.X2	= m_X.X2;
	m_BestParms.X3	= m_X.X3;
	m_BestParms.X4	= m_X.X4;

	if (m_bSnowModule)
	{
		mBestSnowParms.T_Rain = m_snowparms.T_Rain;
		mBestSnowParms.T_Melt = m_snowparms.T_Melt;
		mBestSnowParms.DD_FAC = m_snowparms.DD_FAC;
	}
}
//-------------------------------------------------------------------




///////////////////////////////////////////////////////////////////////
//
//		CREATE OUTPUT TABLES
//
///////////////////////////////////////////////////////////////////////

//-------------------------------------------------------------------
void Cgr4j_cal::_CreateTableCal()
{
	// creating the column titles
	m_pTable_out->Add_Field("NSE",		TABLE_FIELDTYPE_Double);
	m_pTable_out->Add_Field("NSE_high",	TABLE_FIELDTYPE_Double);
	m_pTable_out->Add_Field("NSE_low",	TABLE_FIELDTYPE_Double);
	m_pTable_out->Add_Field("X1",		TABLE_FIELDTYPE_Double);
	m_pTable_out->Add_Field("X2",		TABLE_FIELDTYPE_Double);
	m_pTable_out->Add_Field("X3",		TABLE_FIELDTYPE_Double);
	m_pTable_out->Add_Field("X4",		TABLE_FIELDTYPE_Double);

	if (m_bSnowModule)
	{
		m_pTable_out->Add_Field("T_Rain",		TABLE_FIELDTYPE_Double);
		m_pTable_out->Add_Field("T_Melt",		TABLE_FIELDTYPE_Double);
		m_pTable_out->Add_Field("DD_FAC",		TABLE_FIELDTYPE_Double);
	}
}
//-------------------------------------------------------------------

//-------------------------------------------------------------------
//	WRITE SIMULATION PARAMETER TABLE
//-------------------------------------------------------------------
void Cgr4j_cal::_WriteOutputTable()
{
	int					field = 0; // used in function Get_Record(field)
	CSG_Table_Record	*pRecord;

	m_pTable_out->Add_Record();
	pRecord = m_pTable_out->Get_Record(m_counter);

	pRecord->Set_Value(field, m_NSE); field++;
	pRecord->Set_Value(field, m_NSE_highflow); field++;
	pRecord->Set_Value(field, m_NSE_lowflow); field++;
	pRecord->Set_Value(field, m_X.X1); field++;
	pRecord->Set_Value(field, m_X.X2); field++;
	pRecord->Set_Value(field, m_X.X3); field++;
	pRecord->Set_Value(field, m_X.X4); field++;

	if (m_bSnowModule)
	{
		pRecord->Set_Value(field, m_snowparms.T_Rain); field++;
		pRecord->Set_Value(field, m_snowparms.T_Melt); field++;
		pRecord->Set_Value(field, m_snowparms.DD_FAC); field++;
	}

	m_counter++; // record counter
}
//-------------------------------------------------------------------

//-------------------------------------------------------------------
//	CREATE SIMULATION TABLE
//-------------------------------------------------------------------
void Cgr4j_cal::_CreateTableSim()
{
	// creating the column titles
	m_pTable_sim->Add_Field("DATE",		TABLE_FIELDTYPE_String);
	m_pTable_sim->Add_Field("OBS",		TABLE_FIELDTYPE_Double);
	m_pTable_sim->Add_Field("SIM",		TABLE_FIELDTYPE_Double);
}
//-------------------------------------------------------------------

//-------------------------------------------------------------------
//	WRITE BEST SIMULATION
//-------------------------------------------------------------------
void Cgr4j_cal::_WriteTableSim()
{
	CSG_Table_Record	*pRecord;

	for (int i = 0; i < m_nValues; i++)
	{
		m_pTable_sim->Add_Record();
		pRecord = m_pTable_sim->Get_Record(i);

		pRecord->Set_Value(0,m_pInput->date[i].c_str());
		pRecord->Set_Value(1,m_pInput->Q_obs_mmday[i] * m_area / 86.4);
		pRecord->Set_Value(2,m_p_Q_sim_mmday[i] * m_area / 86.4);
	}
}
//---------------------------------------------------------------------




///////////////////////////////////////////////////////////////////////
//
//		                          DIALOGS
//
///////////////////////////////////////////////////////////////////////

void Cgr4j_cal::_CreateDialog1()
{
	CSG_Parameter	*pNode;
	CSG_String s;

	//---------------------------------------------------------------
	// m_pInput Table
	pNode = Parameters.Add_Table(
		NULL	, "TABLE"	, _TL("Table"),
		"",
		PARAMETER_INPUT
	);

	Parameters.Add_Table_Field(
		pNode	, "DATE_Field"	, _TL("Date Column"),
		"Select the column containing the Date"
	);

	Parameters.Add_Table_Field(
		pNode	, "DISCHARGE_Field"	, _TL("Streamflow Column [m3/s]"),
		"Select the Column containing Discharge Values"
	);

	Parameters.Add_Table_Field(
		pNode	, "PCP_Field"	, _TL("Precipitation Column [mm]"),
		"Select the Column containing precipitation Values"
	);

	Parameters.Add_Table_Field(
		pNode	, "ETP_TMP_Field"	, _TL("ETp or Temperature Column"),
		"Select the Column containing Temperature Values"
	);

	Parameters.Add_Choice(
		pNode	, "ETP_TMP_TS"		, "Specify which time series you are using!",
		"",
		CSG_String::Format("%s|%s|",
			_TL("ETp [mm]"),			//  0
			_TL("mean air temperature [°C]")	//  1
		)
	);
	Parameters.Add_Value(
		pNode,	"bSNOW",	_TL("Use Snow Module"),
		_TL("The snow module can only be used if temperature is used"),
		PARAMETER_TYPE_Bool
	);

	//---------------------------------------------------------------
	s.Printf("Node2", 2);
		pNode = Parameters.Add_Node(NULL,s,"Number of Simulations","");
	Parameters.Add_Value(
		pNode,	"NSIM",	_TL("Number of Simulations"),
		_TL("Number of Simulations"),
		PARAMETER_TYPE_Int,
		10000, 1, true, 10000000, true
	);

	s.Printf("Node2-1", 2-1);
		pNode = Parameters.Add_Node(NULL,s,"Nash-Sutcliffe efficiency","");

	Parameters.Add_Choice(
		pNode, "OBJ_FUNC"		, "Objective Function",
		"",
		"NSE|NSE high flow|NSE low flow"
	);

	Parameters.Add_Value(
		pNode,	"MIN_NSE",	_TL("Nash-Sutcliffe Efficiency"),
		_TL("Minimum Nash-Sutcliffe Efficiency for output"),
		PARAMETER_TYPE_Double,
		0.6, 0.0, true, 1.0, true
	);
	//---------------------------------------------------------------
	// m_pInput / Calibration Parameters
	s.Printf("Node2-2", 2-2);
		pNode = Parameters.Add_Node(NULL,s,"Free Parameters","");

	Parameters.Add_Value(
		pNode,	"X1_lb",	_TL("x1: Capacity of the production store [mm] (lower bound)"),
		_TL("(x1 lower bound) Capacity of the production store [mm]"),
		PARAMETER_TYPE_Double,
		0.0, 0.0, true, 50000.0, true
	);
	Parameters.Add_Value(
		pNode,	"X1_ub",	_TL("x1: Capacity of the production store [mm] (upper bound)"),
		_TL("(x1 upper bound) Capacity of the production store [mm]"),
		PARAMETER_TYPE_Double,
		0.0, 0.0, true, 50000.0, true
	);

	Parameters.Add_Value(
		pNode,	"X2_lb",	_TL("x2: Water exchange coefficient [mm] (lower bound)"),
		_TL("(x2 lower bound) Water exchange coefficient [mm]"),
		PARAMETER_TYPE_Double,
		0.0, -100.0, true, 100.0, true
	);
	Parameters.Add_Value(
		pNode,	"X2_ub",	_TL("x2: Water exchange coefficient [mm] (upper bound)"),
		_TL("(x2 upper bound) Water exchange coefficient [mm]"),
		PARAMETER_TYPE_Double,
		0.0, -100.0, true, 100.0, true
	);

	Parameters.Add_Value(
		pNode,	"X3_lb",	_TL("x3: Capacity of the routing store [mm] (lower bound)"),
		_TL("(x3 lower bound) Capacity of the routing store [mm]"),
		PARAMETER_TYPE_Double,
		0.0, 0.0, true, 50000.0, true
	);
	Parameters.Add_Value(
		pNode,	"X3_ub",	_TL("x3: Capacity of the routing store [mm] (upper bound)"),
		_TL("(x3 upper bound) Capacity of the routing store [mm]"),
		PARAMETER_TYPE_Double,
		0.0, 0.0, true, 50000.0, true
	);

	Parameters.Add_Value(
		pNode,	"X4_lb",	_TL("x4: Time base of the unit hydrograph [days] (lower bound)"),
		_TL("(x4 lower bound) Time base of the unit hydrograph [days]"),
		PARAMETER_TYPE_Double,
		0.0, 0.0, true, 50000.0, true
	);
	Parameters.Add_Value(
		pNode,	"X4_ub",	_TL("x4: Time base of the unit hydrograph [days] (upper bound)"),
		_TL("(x4 upper bound) Time base of the unit hydrograph [days]"),
		PARAMETER_TYPE_Double,
		0.0, 0.0, true, 50000.0, true
	);
	//---------------------------------------------------------------

	// output table for calibration parameter settings
	Parameters.Add_Table_Output(
		NULL	, "TABLEout"	, _TL("Table_out"),
		""
	);
	Parameters.Add_Table_Output(
		NULL	, "TABLEsim"	, _TL("Table_sim"),
		""
	);
	//---------------------------------------------------------------
}

//-------------------------------------------------------------------
//						DIALOG 2
//-------------------------------------------------------------------

bool Cgr4j_cal::_CreateDialog2(CSG_Table* pTable, int dateField,
							  CSG_String& date1, CSG_String& date2,
							  int Choice_ETp_TMP, bool bSnowModule,
							  double& Latitude, double& area)
{
	CSG_String		s;
	CSG_Parameters	P;  // used to add Parameters in the second dialog
	CSG_Parameter	*pNode, *pNode1;

	P.Set_Name(_TL("Choose Time Range"));

	s.Printf("Node1", 1);
	pNode = P.Add_Node(NULL,s,"Time Range","");

	s.Printf("FDAY" , 1-1);
	P.Add_String(pNode,s,_TL("First Day"),_TL(""),
				 pTable->Get_Record(0)->asString(dateField));

	s.Printf("LDAY" , 1-2);
	P.Add_String(pNode,s,_TL("Last Day"),_TL(""),
				 pTable->Get_Record(pTable->Get_Record_Count()-1)->asString(dateField));

	s.Printf("Node2", 2);
	pNode = P.Add_Node(NULL,s,"Catchment Area","");

	P.Add_Value(
		pNode,	"AREA",	_TL("Catchment Area in [km2]"),
		_TL("Catchment area in square kilometers, used to convert m3/s to mm"),
		PARAMETER_TYPE_Double,
		1.0, -0.0, true, 10000.0, true
	);

	if (Choice_ETp_TMP ==1)
	{
		s.Printf("Node2-1", 2-1);
		pNode = P.Add_Node(NULL,s,"Latitude","");

		P.Add_Value(
			pNode,	"LATITUDE",	_TL("Latitude of temperature station in [degrees]"),
			_TL("Latitude of temperature station in [degrees]"),
			PARAMETER_TYPE_Double,
			50.0, -90.0, true, 90.0, true
		);
	}

	if (bSnowModule)
	{
		s.Printf("Node4", 4);
		pNode = P.Add_Node(NULL,s,"Snow Module","");
		s.Printf("Node4-1", 4-1);
		pNode1 = P.Add_Node(pNode,s,"Snow Parameters","");

		P.Add_Value(
			pNode1,	"T_RAIN_LB",	_TL("Snowfall temperature (lower bound)"),
			_TL("Mean Air Temperature at which precipitation is likely to be snow"),
			PARAMETER_TYPE_Double,
			0.0, -5.0, true, 5.0, true
		);
		P.Add_Value(
			pNode1,	"T_RAIN_UB",	_TL("Snowfall temperature (upper bound)"),
			_TL("Mean Air Temperature at which precipitation is likely to be snow"),
			PARAMETER_TYPE_Double,
			0.0, -5.0, true, 5.0, true
		);

		P.Add_Value(
			pNode1,	"T_MELT_LB",	_TL("Snowmelt temperature (lower bound)"),
			_TL("Mean Air Temperature at which snow starts to melt"),
			PARAMETER_TYPE_Double,
			0.0, -5.0, true, 10.0, true
		);
		P.Add_Value(
			pNode1,	"T_MELT_UB",	_TL("Snowmelt temperature (upper bound)"),
			_TL("Mean Air Temperature at which snow starts to melt"),
			PARAMETER_TYPE_Double,
			0.0, -5.0, true, 10.0, true
		);

		P.Add_Value(
			pNode1,	"DD_FAC_LB",	_TL("Degree-Day Factor (lower bound)"),
			_TL("The degree-day factor is used to convert the degree-days to the depth of snowmelt."),
			PARAMETER_TYPE_Double,
			0.7, 0.7, true, 9.2, true
		);
		P.Add_Value(
			pNode1,	"DD_FAC_UB",	_TL("Degree-Day Factor (upper bound)"),
			_TL("The degree-day factor is used to convert the degree-days to the depth of snowmelt."),
			PARAMETER_TYPE_Double,
			9.2, 0.7, true, 9.2, true
		);
	}

	if( SG_UI_Dlg_Parameters(&P, _TL("Choose Time Range")) )
	{
		///////////////////////////////////////////////////////////////
		//
		//                ASSIGN DATA FROM SECOND DIALOG
		//
		///////////////////////////////////////////////////////////////
		// date1 is the first day of the selected period
		date1		= P(CSG_String::Format("FDAY",dateField).c_str())
									->asString();
		// date2 is the last day of the selected period
		date2		= P(CSG_String::Format("LDAY",dateField).c_str())
									->asString();

		// the catchment area is used to convert m3/s to mm
		area		= P("AREA")			->asDouble();

		// If temperature is used instead of ETp, the latitude is needed
		// to calculate ETp from temperature time series.
		if (Choice_ETp_TMP ==1)
			Latitude = P("LATITUDE")	->asDouble();

		if (bSnowModule)
		{
			mT_Rain_lb	= P("T_RAIN_LB")		->asDouble();
			mT_Rain_ub	= P("T_RAIN_UB")		->asDouble();
			mT_Melt_lb	= P("T_MELT_LB")		->asDouble();
			mT_Melt_ub	= P("T_MELT_UB")		->asDouble();
			mDD_FAC_lb	= P("DD_FAC_LB")		->asDouble();
			mDD_FAC_ub	= P("DD_FAC_UB")		->asDouble();
		}
		return(true);
	}
	return(false);


}