/*------------------------------------------------------------------------------*
 * File Name:				 													*
 * Creation: 																	*
 * Purpose: OriginC Source C file												*
 * Copyright (c) ABCD Corp.	2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010		*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 * Jack 3/24/2008  ADD_V8_SEPARATE_HEKA_FILES_MEMBER_FUNCTIONS					*
 * 																				*
 * 																				*
 * 																				*
 * 																				*
 *------------------------------------------------------------------------------*/
 
////////////////////////////////////////////////////////////////////////////////////
// Including the system header file Origin.h should be sufficient for most Origin
// applications and is recommended. Origin.h includes many of the most common system
// header files and is automatically pre-compiled when Origin runs the first time.
// Programs including Origin.h subsequently compile much more quickly as long as
// the size and number of other included header files is minimized. All NAG header
// files are now included in Origin.h and no longer need be separately included.
//
// Right-click on the line below and select 'Open "Origin.h"' to open the Origin.h
// system header file.
#include <Origin.h>
////////////////////////////////////////////////////////////////////////////////////
#include "hekafile.h"
#include <oExtFile.h>
#include "fu_utils.h"
#include <..\originlab\theme_utils.h>
#include <xfbase.h>
////////////////////////////////////////////////////////////////////////////////////
// Include your own header files here.

void _set_x_col(Worksheet &wks, int &nCol, int nSize, double XStart, double XInc, string strXUnit)
{
	if(wks.GetNumCols()<nCol)
	wks.SetSize(-1, nCol);
						
	Column cx(wks, nCol-1);
	vector vTime;
	vTime.Data(XStart, XStart+(nSize-1)*XInc, XInc);
	vectorbase& vs = cx.GetDataObject();
	vs = vTime;
	
	cx.SetComments("Time");
	cx.SetType( OKDATAOBJ_DESIGNATION_X );
	cx.SetUnits( strXUnit );
	
	++nCol;
}



int is_x_axis_the_same_v9(TreeNode &trSeries)
{
	bool bFirst = true;
	double dX1, dX2, dInc1, dInc2;
	foreach(TreeNode trSweep in trSeries.Children)
	{
		foreach(TreeNode trTrace in trSweep.Children)
		{
			if(bFirst)
			{		
				trTrace.GetAttribute(STR_HEKA_XS, dX1);
				trTrace.GetAttribute(STR_HEKA_XI, dInc1);
				bFirst = false;
			}
			else
			{
				trTrace.GetAttribute(STR_HEKA_XS, dX2);
				trTrace.GetAttribute(STR_HEKA_XI, dInc2);			
				if( fabs(dX2-dX1)>0.000000000000000001 || fabs(dInc2-dInc1)>0.000000000000000001 )
					return false;

				dX1 = dX2;
				dInc1 = dInc2;
			}
		}
	}
	return true;
}

int is_x_axis_the_same_v8(TreeNode &trSeries)
{
	bool bFirst = true;
	int nStimCount1, nStimCount2;
	foreach(TreeNode trSweep in trSeries.Children)
	{
		if(bFirst)
		{		
			trSweep.GetAttribute(STR_HEKA_STIMCOUNT, nStimCount1);
			bFirst = false;
		}
		else
		{
			trSweep.GetAttribute(STR_HEKA_STIMCOUNT, nStimCount2);	
			if( nStimCount1 != nStimCount2 )
				return false;
			nStimCount1 = nStimCount2;
		}
	}
	return true;
}

int update_selection_tree(TreeNode &trSelection)
{
	int nStop = 0;
	foreach(TreeNode cNode in trSelection.Children){
		if (cNode.GetNodeCount() > 0){
			int val = update_selection_tree(cNode);
			cNode.SetAttribute(STR_STOP_ATTRIB, val);
			if (1 == val)
				nStop = 1;
		}
		else{
			if (1 == cNode.nVal)
				nStop = 1;
		}
	}
	return nStop;
}

int GetNumOfNodeSelected(TreeNode &tr)
{
	int nNodeSelected = -1;

    foreach(TreeNode trTmp in tr.Children){
		int nStop;
		if (trTmp.GetNodeCount() > 0)
			trTmp.GetAttribute(STR_STOP_ATTRIB, nStop);
		else
			nStop = trTmp.nVal;
	
		if(1 == nStop)
			++nNodeSelected;
	}

	return nNodeSelected;
}

void AddWorksheets(WorksheetPage &pg, int nSheetNeeded)
{
    for(int ii=0; ii<nSheetNeeded; ++ii){
		pg.AddLayer();
	}
}

string GetTraceName(TreeNode &trSeries, int nCount)
{
    string str, strName;

	trSeries.GetAttribute(STR_LABEL_ATTRIB, str);
	if(1 == nCount)
		strName = str;
	else
		strName.Format("%s_%d", str, nCount);
	
	return strName;
}


void HekaFile::HekaFile(LPCSTR lpcszFileName)
{
	m_strFileName = lpcszFileName;
}

int HekaFile::Open()
{
	if( !Open(m_strFileName, file::modeRead))
		return false;
	if( ReadHeader(m_trPul, m_trStim) <0 )
		return false;
	
	// Get version
	m_trPul.GetAttribute(STR_HEKA_VER, m_ver);
	
	return true;
}

int HekaFile::Open(string fileDAT, string filePUL, string filePGF, short nVer)
{
	Close();
	m_strDatFileName = fileDAT;
	m_strPulseFileName = filePUL;
	m_strStimuFileName = filePGF;
	
	if(!OpenPulseFile(nVer))
		return false;
	if(!OpenStimuFile(nVer))
		return false;
	if(!OpenDatFile())
		return false;
	
	// Get version
	m_trPul.GetAttribute(STR_HEKA_VER, m_ver);

	return true;
}


int HekaFile::Import(DWORD dwCtrl, TreeNode &tr, int nMode)
{
	if(tr)
	{
		update_selection_tree(tr);
	}
	
	switch(m_ver)
	{
	case 8:
		if( HEKA_MODE_SINGLE_BOOK == nMode)
			return ImportV8(dwCtrl, tr);
		else
			return ImportV8_ex(dwCtrl, tr);
		break;
	case 9:
		if( HEKA_MODE_SINGLE_BOOK == nMode)
			return ImportV9(dwCtrl, tr);
		else
			return ImportV9_ex(dwCtrl, tr);
		break;
	default:
		ASSERT(FALSE);
		break;
	}

	return -1;
}




int HekaFile::ImportTraceV9(DWORD dwCtrl, string strName, TreeNode &trTrace, Worksheet &wks, int &nSheet, int &nCol, int &nAddX)
{
	int nLeakCount, nLeakTrace;
	trTrace.GetAttribute(STR_HEKA_LC, nLeakCount);
	if(nLeakCount == 1 && !(HEKA_IMP_LEAK & dwCtrl)) return true;

	int nOffset, nDataPoints, nType, nFormat;
	double Scaler, ZeroData, XStart, XInterval;
	string strLabel, strXUnit, strYUnit, str;
	
	trTrace.GetAttribute(STR_LABEL_ATTRIB, strLabel);
	trTrace.GetAttribute(STR_HEKA_LT, nLeakTrace);
	trTrace.GetAttribute(STR_HEKA_OFFSET, nOffset);
	trTrace.GetAttribute(STR_HEKA_SIZE, nDataPoints);
	trTrace.GetAttribute(STR_HEKA_TYPE, nType);
	trTrace.GetAttribute(STR_HEKA_FORMAT, nFormat);					
	trTrace.GetAttribute(STR_HEKA_SCALER, Scaler);
	trTrace.GetAttribute(STR_HEKA_ZERO, ZeroData);
	trTrace.GetAttribute(STR_HEKA_XS, XStart);
	trTrace.GetAttribute(STR_HEKA_XI, XInterval);
	trTrace.GetAttribute(STR_HEKA_XU, strXUnit);
	trTrace.GetAttribute(STR_HEKA_UNIT, strYUnit);
	
	if((dwCtrl & HEKA_SHOW_X) && nAddX)
	{
		_set_x_col(wks, nCol, nDataPoints, XStart, XInterval, strXUnit);
		if (1 == nAddX) nAddX = 0;
	}

	if(wks.GetNumCols()<nCol)
		wks.SetSize(-1, nCol);
	str.Format("Sheet%d!%d", nSheet, nCol);

	//Subtract zero data
	ZeroData = (HEKA_SUB_ZERO & dwCtrl)? ZeroData : 0.0;
	
	if( nLeakTrace == 0 )
		heka_read_zerotrace(str, this, nOffset, nDataPoints, nFormat, nType, Scaler, ZeroData);
	else{
		if( HEKA_SUB_LEAK & dwCtrl )
			heka_read_zerotrace(str, this, nOffset, nDataPoints, nFormat, nType, Scaler, ZeroData);
		else
			heka_read_leaktrace(str, this, nOffset, nDataPoints, nFormat, nType, Scaler, ZeroData, nLeakCount);
	}

	// Set param
	Column col(wks, nCol-1);
	col.SetLongName(strName);
	col.SetType( OKDATAOBJ_DESIGNATION_Y );
	col.SetUnits(strYUnit);
	col.SetComments(strLabel);
	
	if(!(dwCtrl & HEKA_SHOW_X))
	{
		col.SetEvenSampling(XStart, XInterval);
		col.SetExtendedLabel("", RCLT_SAMPLE_RATE); 
	}
	
	++nCol;

	return true;
}



int HekaFile::ImportV9(DWORD dwCtrl, TreeNode &tr)
{
	string str, strName;

	// Allocate enough worksheet
	int nSheetNeeded;
	if(tr)
		nSheetNeeded = GetNumOfNodeSelected(tr);
	else{
		ASSERT(m_trPul.GetNodeCount() > 0);
		nSheetNeeded = m_trPul.GetNodeCount()-1;
		dwCtrl = HEKA_SUB_LEAK | HEKA_SUB_ZERO;
	}

	// Create a worksheet	
	WorksheetPage pg;
	pg.Create("Origin");
	AddWorksheets(pg, nSheetNeeded);
	
	// Set title for the worksheet page
	pg.Label = _get_file_name_heka(m_strDatFileName);
	pg.TitleShow = WIN_TITLE_SHOW_BOTH;
	
	TreeNode trGP, trSer;
	if(tr) trGP = tr.FirstNode;
		
	int nSheet = 1, nGroup = 0;	
	foreach(TreeNode trGroup in m_trPul.Children)
	{
		if(tr)
		{
			trGP = trGP.NextNode;
			
			int nStop;
			trGP.GetAttribute(STR_STOP_ATTRIB, nStop);
			
			if(0 == nStop)
			{
				++nGroup;
				continue;
			}
			else
				trSer = trGP.FirstNode;
		}
		++nGroup;

		int nCol = 1;
		Worksheet wks = pg.Layers(nSheet-1);

		foreach(TreeNode trSeries in trGroup.Children)
		{
			if(tr)
			{
				if(trSer.nVal == 0){
					trSer = trSer.NextNode;
					continue;
				}
			}
			
			int nAddX, nSweep = 1;
			if(dwCtrl & HEKA_SHOW_X)
				nAddX = is_x_axis_the_same_v9(trSeries)? 1 : 2;
			else
				nAddX = 0;
			foreach(TreeNode trSweep in trSeries.Children)
			{
				foreach(TreeNode trTrace in trSweep.Children)
				{
					ImportTraceV9(dwCtrl, GetTraceName(trSeries, nSweep), trTrace, wks, nSheet, nCol, nAddX);
				}
				++nSweep;
			}
			
			if(tr) trSer = trSer.NextNode;
		}
		// set the Group name 
		trGroup.GetAttribute(STR_LABEL_ATTRIB, str);
		/// Hong 09/13/10 FIX_DUPLICATE_NAME_IMPORT_GROUP_DATA
		//wks.SetName(str);
		wks.SetName(str, OCD_ENUM_NEXT);
		/// end FIX_DUPLICATE_NAME_IMPORT_GROUP_DATA
		if(!(dwCtrl & HEKA_SHOW_X))
			wks_set_col_label_heights(wks, RCLT_SAMPLE_RATE, 200, false);
		wks.AutoSize();

		++nSheet;
	}
	
	return true;

}


int HekaFile::ImportV9_ex(DWORD dwCtrl, TreeNode &tr)
{
	string str, strName;

	// Allocate enough worksheet
	if(!tr){
		ASSERT(m_trPul.GetNodeCount() > 0);
		dwCtrl = HEKA_SUB_LEAK | HEKA_SUB_ZERO;
	}

	TreeNode trGP, trSer;
	if(tr) trGP = tr.FirstNode;
	
	int nBook = 0, nGroup = 0;
	foreach(TreeNode trGroup in m_trPul.Children)
	{
		if(tr)
		{
			trGP = trGP.NextNode; 
			
			int nStop;
			trGP.GetAttribute(STR_STOP_ATTRIB, nStop);
			
			if(0 == nStop)
			{
				++nGroup;
				continue;
			}
			else
				trSer = trGP.FirstNode;
		}
		++nGroup;

		// Create a worksheet
		WorksheetPage pg;
		pg.Create("Origin");

		// Set title for the worksheet page
		trGroup.GetAttribute(STR_LABEL_ATTRIB, str);
		strName.Format("%d_%s", nGroup, str);
		pg.Label = strName;
		pg.TitleShow = WIN_TITLE_SHOW_BOTH;
	
		int nSheetNeeded;
		if(tr)
			nSheetNeeded = GetNumOfNodeSelected(trGP);
		else
			nSheetNeeded = trGroup.GetNodeCount()-1;
		ASSERT(nSheetNeeded != -1);
		AddWorksheets(pg, nSheetNeeded);

		int nSheet = 0, nSeries = 0;
		foreach(TreeNode trSeries in trGroup.Children)
		{
			if(tr)
			{
				if(trSer.nVal == 0){
					++nSeries;
					trSer = trSer.NextNode;
					continue;
				}
			}
			++nSeries;
			
			Worksheet wks = pg.Layers(nSheet++);

            int nAddX, nSweep = 1; 
            if(dwCtrl & HEKA_SHOW_X)
				nAddX = is_x_axis_the_same_v9(trSeries)? 1 : 2;
			else
				nAddX = 0;
			foreach(TreeNode trSweep in trSeries.Children)
			{
				foreach(TreeNode trTrace in trSweep.Children)
				{
					ImportTraceV9(dwCtrl, GetTraceName(trSeries, nSweep), trTrace, wks, nSheet, nSweep, nAddX);
				}
			}
			
			if(tr) trSer = trSer.NextNode;

			// set the Group name 
			trSeries.GetAttribute(STR_LABEL_ATTRIB, str);
			strName.Format("%d_%s", nSeries, str);
			/// Hong 09/13/10 FIX_DUPLICATE_NAME_IMPORT_GROUP_DATA
			//wks.SetName(strName);
			wks.SetName(strName, OCD_ENUM_NEXT);
			/// end FIX_DUPLICATE_NAME_IMPORT_GROUP_DATA
			if(!(dwCtrl & HEKA_SHOW_X))
				wks_set_col_label_heights(wks, RCLT_SAMPLE_RATE, 200, false);
			wks.AutoSize();
		}

		++nBook;
	}
	
	return true;

}


int HekaFile::ReadHeader(TreeNode& trPul, TreeNode& trPgf)
{
	return heka_read_bundle_header(this, &trPul, &trPgf);	
}



// Jack 3/24/2008  ADD_V8_SEPARATE_HEKA_FILES_MEMBER_FUNCTIONS
 HekaFile::HekaFile(LPCSTR lpcszDatFileName, LPCSTR lpcszPulFileName, LPCSTR lpcszStimuFileName)
{
	m_strDatFileName = lpcszDatFileName;
	m_strPulseFileName = lpcszPulFileName;
	m_strStimuFileName = lpcszStimuFileName;
}

int HekaFile::OpenPulseFile(short nVer)
{
	file  pulsefile;
	if( !pulsefile.Open(m_strPulseFileName, file::modeRead))
		return false;
	int nRet = heka_read_pulse(&pulsefile, 0, &m_trPul, nVer) ;  //set tree information
	pulsefile.Close();
	return true;
}

int HekaFile::OpenDatFile()
{
	//Close();
	if( !Open(m_strDatFileName, file::modeRead) )
		return false;
	return true;
}

int HekaFile::OpenStimuFile(short nVer)
{
	file  stimufile;
	if( !stimufile.Open(m_strStimuFileName, file::modeRead))
		return false;
	int nRet = heka_read_stim(&stimufile, 0, &m_trStim, nVer) ;  //set tree information for stimulation
	stimufile.Close();
	return true;
}

int HekaFile::GetStimuInfoV8()
{
	int nNumStimus = m_trStim.GetNodeCount();
	m_dStart.SetSize(nNumStimus);
	m_dSampleInterval.SetSize(nNumStimus);
	m_strYUnit.SetSize(nNumStimus);
	m_strYUnit2.SetSize(nNumStimus);
	m_nLeakCount.SetSize(nNumStimus);
	
	int nStimuCount=0;
	double dTempStart, dTempSampInterval;
	string strTempYUnit, strTempYUnit2;
	int nTempLeakCount;
	foreach(TreeNode trStimu in m_trStim.Children)
	{
		trStimu.GetAttribute(STR_HEKA_XS, dTempStart);
		trStimu.GetAttribute(STR_HEKA_XI, dTempSampInterval);
		trStimu.GetAttribute(STR_HEKA_UNIT, strTempYUnit); // print info for temp usage
		trStimu.GetAttribute(STR_HEKA_UNIT2, strTempYUnit2);
		trStimu.GetAttribute(STR_HEKA_LC, nTempLeakCount);
				
		m_dStart[nStimuCount] = dTempStart; 
		m_dSampleInterval[nStimuCount] = dTempSampInterval; 
		m_strYUnit[nStimuCount] = strTempYUnit;
		m_strYUnit2[nStimuCount] = strTempYUnit2;
		m_nLeakCount[nStimuCount]= nTempLeakCount;
			
		nStimuCount++;
	}
	return nNumStimus;
}

int HekaFile::ImportTraceV8(DWORD dwCtrl, string strName, TreeNode &trSweep, Worksheet &wks, int &nSheet, int &nCol, int &nAddX)
{
	///Import first trace
	int nLeakTrace;
	trSweep.GetAttribute(STR_HEKA_LT, nLeakTrace);
	
	int nOffset, nDataPoints, nFormat;
	double Scaler, Scaler2, ZeroData, XStart, XInterval;
	string strLabel, strXUnit, strYUnit, strYUnit2, str;
	int nStimCount;
	
	trSweep.GetAttribute(STR_LABEL_ATTRIB, strLabel);
	trSweep.GetAttribute(STR_HEKA_OFFSET, nOffset);
	trSweep.GetAttribute(STR_HEKA_SIZE, nDataPoints);
	trSweep.GetAttribute(STR_HEKA_FORMAT, nFormat);		
	trSweep.GetAttribute(STR_HEKA_SCALER, Scaler);
	trSweep.GetAttribute(STR_HEKA_SCALER2, Scaler2);				
	trSweep.GetAttribute(STR_HEKA_ZERO, ZeroData);
	trSweep.GetAttribute(STR_HEKA_STIMCOUNT,nStimCount);

	XStart = m_dStart[nStimCount-1];
	strXUnit = "s"; //Set the default XUnit as second
	XInterval = m_dSampleInterval[nStimCount-1]; //  use the sample-interval obtained from stimulation
	strYUnit = m_strYUnit[nStimCount-1];
	strYUnit2 = m_strYUnit2[nStimCount-1];
	
	if((dwCtrl & HEKA_SHOW_X) && nAddX)
	{
		_set_x_col(wks, nCol, nDataPoints, XStart, XInterval, strXUnit);
		if (1 == nAddX) nAddX = 0;
	}
	
	if(wks.GetNumCols()<nCol)
		wks.SetSize(-1, nCol);
	str.Format("Sheet%d!%d", nSheet, nCol);
	
	//Subtract zero data
	ZeroData = (HEKA_SUB_ZERO & dwCtrl)? ZeroData : 0.0;

	// Fisher: subtract leak trace
	if( nLeakTrace == 0 )
		heka_read_zerotrace(str, this, nOffset, nDataPoints, nFormat, 1, Scaler, ZeroData);
	else{
		if( HEKA_SUB_LEAK & dwCtrl )
			heka_read_zerotrace(str, this, nOffset, nDataPoints, nFormat, 1, Scaler, ZeroData);
		else
			heka_read_leaktrace(str, this, nOffset, nDataPoints, nFormat, 1, Scaler, ZeroData, 2);
	}
	
	// Set param
	Column col(wks, nCol-1);

	col.SetLongName(strName);
	if(strYUnit == strYUnit2)
		col.SetComments("Voltage");
	else
		col.SetComments("Current");
	col.SetType( OKDATAOBJ_DESIGNATION_Y );	
	col.SetUnits(strYUnit);
	col.SetEvenSampling(XStart, XInterval);
	col.SetExtendedLabel("", RCLT_SAMPLE_RATE); 
	
	++nCol;
	
	/////// Import Leak Trace		
	if(nLeakTrace == 1 && (HEKA_IMP_LEAK & dwCtrl))
	{
		if(wks.GetNumCols()<nCol)
		wks.SetSize(-1, nCol);
		str.Format("Sheet%d!%d", nSheet, nCol);
		
		heka_read_zerotrace(str, this, nOffset+2*nDataPoints, nDataPoints, nFormat, 1, Scaler, 0.0);
		
		Column col(wks, nCol-1);
		col.SetLongName(strName);
		col.SetComments("Leak");
		col.SetUnits(strYUnit);
		col.SetEvenSampling(XStart, XInterval);
		col.SetType( OKDATAOBJ_DESIGNATION_Y );
		
		++nCol;
	}
	
	//////// Import Second Trace
	int nSecondTrace;
	trSweep.GetAttribute(STR_HEKA_ST, nSecondTrace);
	if(nSecondTrace == 1)		//default to import second trace
	{
		
		if(wks.GetNumCols()<nCol)
		wks.SetSize(-1, nCol);
		str.Format("Sheet%d!%d", nSheet, nCol);
		
		if(nLeakTrace == 0)
			heka_read_zerotrace(str, this, nOffset+2*nDataPoints, nDataPoints, nFormat, 1, Scaler2, 0.0);
		else
			heka_read_zerotrace(str, this, nOffset+4*nDataPoints, nDataPoints, nFormat, 1, Scaler2, 0.0);
		
		Column col(wks, nCol-1);
		col.SetLongName(strName);
		col.SetComments("Voltage");
		col.SetType( OKDATAOBJ_DESIGNATION_Y );
		col.SetUnits(strYUnit2);
		col.SetEvenSampling(XStart, XInterval);
		col.SetExtendedLabel("", RCLT_SAMPLE_RATE); 
		
		++nCol;
	}

	return true;
}


int HekaFile::ImportV8(DWORD dwCtrl, TreeNode &tr)
{
	string str, strName;
	
	// Allocate enough worksheet
	int nSheetNeeded;
	if(tr)
		nSheetNeeded = GetNumOfNodeSelected(tr);
	else{
		ASSERT(m_trPul.GetNodeCount() > 0);
		nSheetNeeded = m_trPul.GetNodeCount()-1;
		dwCtrl = HEKA_SUB_LEAK | HEKA_SUB_ZERO;
	}
	
	// Create a worksheet	
	WorksheetPage pg;
	pg.Create("Origin");
	AddWorksheets(pg, nSheetNeeded);
	
	//Get stimulation info
	int nNumStimus = GetStimuInfoV8(); //the size of dSampInterval, strYUnit, nLeakCount are determined internally by nNumStimus
	
	// Set title for the worksheet page
	pg.Label = _get_file_name_heka(m_strDatFileName);
	pg.TitleShow = WIN_TITLE_SHOW_BOTH;
	
	TreeNode trGP, trSer;
	if(tr) trGP = tr.FirstNode;
	
	int nSheet = 1, nGroup = 0;
	foreach(TreeNode trGroup in m_trPul.Children)
	{
		if(tr)
		{
			trGP = trGP.NextNode;
			
			int nStop;
			trGP.GetAttribute(STR_STOP_ATTRIB, nStop);
			
			if(0 == nStop){
				++nGroup;
				continue;
			}
			else
				trSer = trGP.FirstNode;
		}
		++nGroup;
		
		Worksheet wks = pg.Layers(nSheet-1);
		int nCol = 1, nSeries = 0;
		foreach(TreeNode trSeries in trGroup.Children)
		{
			if(tr)
			{
				if(trSer.nVal == 0){
					++nSeries;
					trSer = trSer.NextNode;
					continue;
				}
			}
			++nSeries;
			
			int nAddX, nSweep=1;
			if(dwCtrl & HEKA_SHOW_X)
				nAddX = is_x_axis_the_same_v9(trSeries)? 1 : 2;
			else
				nAddX = 0;
			foreach(TreeNode trSweep in trSeries.Children)
			{
				strName.Format("%d_%d_%d", nGroup, nSeries, nSweep);
				ImportTraceV8(dwCtrl, strName, trSweep, wks, nSheet, nCol, nAddX);
				++nSweep;
			}
			
			
			if(tr) trSer = trSer.NextNode;			
		}
		// set the Group name 
		trGroup.GetAttribute(STR_LABEL_ATTRIB, str);
		/// Hong 09/13/10 FIX_DUPLICATE_NAME_IMPORT_GROUP_DATA
		//wks.SetName(str);
		wks.SetName(str, OCD_ENUM_NEXT);
		/// end FIX_DUPLICATE_NAME_IMPORT_GROUP_DATA
		if(!(dwCtrl & HEKA_SHOW_X))
			wks_set_col_label_heights(wks, RCLT_SAMPLE_RATE, 200, false);
		wks.AutoSize();
		++nSheet;
	}
	
	return true;

}
// End ADD_V8_SEPARATE_HEKA_FILES_MEMBER_FUNCTIONS

int HekaFile::ImportV8_ex(DWORD dwCtrl, TreeNode &tr)
{
	string str, strName;

	// Allocate enough worksheet
	if(!tr){
		ASSERT(m_trPul.GetNodeCount() > 0);
		dwCtrl = HEKA_SUB_LEAK | HEKA_SUB_ZERO;
	}
	
	int nNumStimus = GetStimuInfoV8();

	TreeNode trGP, trSer;
	if(tr) trGP = tr.FirstNode;
	
	int nBook = 0, nGroup = 0;
	foreach(TreeNode trGroup in m_trPul.Children)
	{
		if(tr)
		{
			trGP = trGP.NextNode; 
			
			int nStop;
			trGP.GetAttribute(STR_STOP_ATTRIB, nStop);
			
			if(0 == nStop)
			{
				++nGroup;
				continue;
			}
			else
				trSer = trGP.FirstNode;
		}
		++nGroup;

		// Create a worksheet
		WorksheetPage pg;
		pg.Create("Origin");

		// Set title for the worksheet page
		trGroup.GetAttribute(STR_LABEL_ATTRIB, str);
		strName.Format("%d_%s", nGroup, str);
		pg.Label = strName;
		pg.TitleShow = WIN_TITLE_SHOW_BOTH;
	
		int nSheetNeeded;
		if(tr)
			nSheetNeeded = GetNumOfNodeSelected(trGP);
		else
			nSheetNeeded = trGroup.GetNodeCount()-1;
		ASSERT(nSheetNeeded != -1);
		AddWorksheets(pg, nSheetNeeded);

		int nSheet = 0, nSeries = 0;
		foreach(TreeNode trSeries in trGroup.Children)
		{
			if(tr)
			{
				if(trSer.nVal == 0){
					++nSeries;
					trSer = trSer.NextNode;
					continue;
				}
			}
			++nSeries;
			
			Worksheet wks = pg.Layers(nSheet++);

            int nAddX, nSweep = 1; 
            if(dwCtrl & HEKA_SHOW_X)
				nAddX = is_x_axis_the_same_v9(trSeries)? 1 : 2;
			else
				nAddX = 0;
			foreach(TreeNode trSweep in trSeries.Children)
			{
				strName.Format("%d_%d_%d", nGroup, nSeries, nSweep);
				ImportTraceV8(dwCtrl, strName, trSweep, wks, nSheet, nSweep, nAddX);
			}
			
			if(tr) trSer = trSer.NextNode;

			// set the Group name 
			trSeries.GetAttribute(STR_LABEL_ATTRIB, str);
			strName.Format("%d_%s", nSeries, str);
			/// Hong 09/13/10 FIX_DUPLICATE_NAME_IMPORT_GROUP_DATA
			//wks.SetName(strName);
			wks.SetName(strName, OCD_ENUM_NEXT);
			/// end FIX_DUPLICATE_NAME_IMPORT_GROUP_DATA
			if(!(dwCtrl & HEKA_SHOW_X))
				wks_set_col_label_heights(wks, RCLT_SAMPLE_RATE, 200, false);
			wks.AutoSize();
		}

		++nBook;
	}
	
	return true;

}