#pragma rtGlobals=1		// Use modern global access method.
#pragma IgorVersion = 6.1
#pragma ModuleName = PearlOtfImport
#pragma version = 1.01

// procedures for importing on-the-fly (OTF) scans
// OTF scans are saved as ITX files
// matthias muntwiler, 2013-02-22
// $Id$

// introduction
// the latest version of the PEARL OTF server saves data in igor text (ITX)
// the files contain code which saves all data from one file into one data folder with a unique name
// multiple files can be selected in the explorer and loaded by a double click

// description
// OTF data folder names have the format otf_date_time_suffix, where only suffix is user-defined
// thus, raw data folder names are unique
// data folder names can be converted to a shorter format
// an OTF data folder contains a wave for each measured quantity (detector)
// and the IN, ID, IV, and IU waves for additional beamline parameters
// detector waves must have a wave note containing the following key=value pairs:
// PV=name of EPICS process variable
// PhysicalType=physical type of the quantity in the same way as used by pearl-optics-import
// Axis1=wave name of principal X axis

// convergence
// while the file formats may be different, data files generated by the OTF and EPICS scan tools 
// shall ultimately produce the same data structures in an Igor experiment

function otf_load_itx_all(pathname)
	// loads all OTF files from a given path
	// this function is for older files (before 2013-03-01) which do not specify a destination data folder
	// newer files can be loaded by double click from the explorer
	// without the danger of overwriting data from other files
	string pathname
	string filename
	
	if (strlen(pathname) <= 0)
		newpath /o/q otf_load_itx
		pathname = "otf_load_itx"
	endif
	string filelist = IndexedFile($pathname, -1, ".itx")
	filelist = ListMatch(filelist, "otf*.itx", ";")
	variable nfile = ItemsInList(filelist, ";")
	variable ifile
	for (ifile = 0; ifile < nfile; ifile += 1)
		filename = StringFromList(ifile, filelist, ";")
		otf_load_itx(pathname, filename)
	endfor
end

function otf_load_itx_match(pathname, matchstr)
	// loads all OTF files from a given path whose names match a given string
	// this function is for older files (before 2013-03-01) which do not specify a destination data folder
	// newer files can be loaded by double click from the explorer
	// without the danger of overwriting data from other files
	string pathname
	string matchstr
	string filename
	
	if (strlen(pathname) <= 0)
		newpath /o/q otf_load_itx
		pathname = "otf_load_itx"
	endif
	string filelist = IndexedFile($pathname, -1, ".itx")
	filelist = ListMatch(filelist, matchstr, ";")
	variable nfile = ItemsInList(filelist, ";")
	variable ifile
	for (ifile = 0; ifile < nfile; ifile += 1)
		filename = StringFromList(ifile, filelist, ";")
		otf_load_itx(pathname, filename)
	endfor
end

function otf_load_itx(pathname, filename)
	// loads a specific OTF file
	// this function is for older files (before 2013-03-01) which do not specify a destination data folder
	// newer files can be loaded by double click from the explorer
	// without the danger of overwriting data from other files
	string pathname
	string filename

	dfref savedf = GetDataFolderDFR()
	setdatafolder root:

	newdatafolder /s/o otf_load_itx_temp
	if (strlen(pathname) > 0)
		LoadWave /O/P=$pathname/Q/T filename
	else
		LoadWave /O/Q/T filename
	endif
	if (v_flag)
		string foldername
		foldername = ParseFilePath(3, s_filename, "/", 0, 0)
		foldername = foldername[0,16]
		foldername = CleanupName(foldername, 0)
		//foldername = UniqueName(foldername, 11, 0)
		renamedatafolder root:otf_load_itx_temp, $foldername
		printf "loaded otf data from file %s into folder %s\r", s_filename, foldername
	endif
	
	setdatafolder savedf
end

function otf_gather_iterator(df, sdata)
	// data folder iterator used by otf_gather_batch
	dfref df
	string &sdata // key=value list of parameters
		// xwavematch
		// ywavematch
		// destfolder

	string src_name
	string dst_name
	string src_folder
	string dst_folder
	string df_id
	string prefix, sdate, stime
	
	setdatafolder df
	src_folder = GetDataFolder(0, df)
	sscanf src_folder, "%[^_]_%[0-9]_%[0-9]", prefix, sdate, stime
	df_id = ""
	if (strlen(sdate) > 0)
		df_id += "_" + sdate
	endif
	if (strlen(stime) > 0)
		df_id += "_" + stime
	endif
	dst_folder = StringByKey("destfolder", sdata)
	
	src_name = StringByKey("xwavematch", sdata)
	src_name = WaveList(src_name, "", "")
	if (ItemsInList(src_name) >= 1)
		src_name = StringFromList(0, src_name)
		dst_name = dst_folder + src_name + df_id
		//print src_name, dst_name
		duplicate $src_name, $dst_name
	endif
	
	src_name = StringByKey("ywavematch", sdata)
	src_name = WaveList(src_name, "", "")
	if (ItemsInList(src_name) >= 1)
		src_name = StringFromList(0, src_name)
		dst_name = dst_folder + src_name + df_id
		//print src_name, dst_name
		duplicate $src_name, $dst_name
	endif
end

function otf_gather_batch(ywavematch, xwavematch, destfolder)
	// gathers (copies) OTF datasets in one data folder
	// can be used for example for the Igor batch curve fitting tool
	string ywavematch // match string identifies the y wave to be copied
	string xwavematch // match string identifies the x wave to be copied
	string destfolder // name of the destination data folder. folder does not have to exist.

	return gather_batch("otf*", ywavematch, xwavematch, destfolder)
end

function gather_batch(foldermatch, ywavematch, xwavematch, destfolder)
	// gathers (copies) OTF datasets in one data folder
	// can be used for example for the Igor batch curve fitting tool
	string foldermatch // match string to select data folders, e.g. "otf*"
	string ywavematch // match string identifies the y wave to be copied
	string xwavematch // match string identifies the x wave to be copied
	string destfolder // name of the destination data folder. folder does not have to exist.
	
	dfref savedf = GetDataFolderDFR()
	newdatafolder /o/s $destfolder
	destfolder = GetDataFolder(1)
	
	string iteratordata = ""
	iteratordata = ReplaceStringByKey("xwavematch", iteratordata, xwavematch)
	iteratordata = ReplaceStringByKey("ywavematch", iteratordata, ywavematch)
	iteratordata = ReplaceStringByKey("destfolder", iteratordata, destfolder)
	
	setdatafolder savedf
	iteratordata = IterateDataFolders(foldermatch, otf_gather_iterator, iteratordata)

	setdatafolder savedf
end

function otf_rename_folders_iterator(df, sdata)
	// data folder iterator used by otf_rename_folders
	dfref df
	string &sdata // key=value list of parameters

	string pattern = StringByKey("pattern", sdata)
	variable unique_index = NumberByKey("unique_index", sdata)
	string new_suffix = StringByKey("new_suffix", sdata)
	
	string src_folder
	string dst_folder
	string sprefix, sdate, stime, ssuffix
	
	setdatafolder df
	src_folder = GetDataFolder(0, df)
	sprefix = "otf"
	sscanf src_folder, "otf_%[0-9]_%[0-9]%s", sdate, stime, ssuffix
	// return early if folder name does not match the expected pattern
	if ((strlen(sdate) == 0) || (strlen(stime) == 0))
		return 1
	endif

	dst_folder = sprefix
	if (cmpstr(pattern[0], "0") != 0)
		dst_folder += "_" + sdate
	endif
	if (cmpstr(pattern[1], "0") != 0)
		dst_folder += "_" + stime
	endif
	if (cmpstr(pattern[2], "0") != 0)
		if (strlen(new_suffix) > 0)
			ssuffix = "_" + new_suffix
		endif
		dst_folder += ssuffix
	endif
	
	if ((unique_index > 0) || (CheckName(dst_folder, 11) != 0))
		dst_folder = UniqueName(dst_folder + "_", 11, unique_index)
	endif
	
	setdatafolder ::
	print src_folder + " -> " + dst_folder
	RenameDataFolder $src_folder, $dst_folder
	return 0
end

function otf_rename_folders(pattern, [unique_index, new_suffix, match_str])
	// renames OTF data folders by omitting parts of the file name
	string pattern // string of zeros and ones indicates which name parts to keep
		// pos 1: date
		// pos 2: time
		// pos 3: custom suffix
	variable unique_index // if you remove date and time,
		// this start index will be used to make names unique
		// if non-zero, new names will be forced to include a unique index
		// if zero (default), new names will get a unique index only in case of a conflict
		// optional, defaults to 0
	string new_suffix
		// replace old suffix by this one
		// if empty (default), the old suffix will be kept
		// optional, defaults to empty string
	string match_str // match folder name to rename
		// optional, defaults to "otf*" (matches all OTF folders)
		
	dfref savedf = GetDataFolderDFR()
	
	if (ParamIsDefault(unique_index))
		unique_index = 0
	endif
	if (ParamIsDefault(new_suffix))
		new_suffix = ""
	endif
	if (ParamIsDefault(match_str))
		match_str = "otf*"
	endif
	
	string iteratordata = ""
	iteratordata = ReplaceStringByKey("pattern", iteratordata, pattern)
	iteratordata = ReplaceNumberByKey("unique_index", iteratordata, unique_index)
	iteratordata = ReplaceStringByKey("new_suffix", iteratordata, new_suffix)
	
	iteratordata = IterateDataFolders(match_str, otf_rename_folders_iterator, iteratordata)

	setdatafolder savedf
end

function otf_interp(e1, e2, npts, smo)
	variable e1
	variable e2
	variable npts
	variable smo
	
	wave ch1 = current_ch1
	wave ch2 = current_ch2
	wave pe = photonenergy
	wave cff
	wave rc = ringcurrent
	
	duplicate /o ch1, current_ch1_int
	wave ch1i = current_ch1_int
	duplicate /o ch2, current_ch2_int
	wave ch2i = current_ch2_int
	duplicate /o pe, photonenergy_int
	wave pei = photonenergy_int
	duplicate /o cff, cff_int
	wave cffi = cff_int
	duplicate /o rc, ringcurrent_int
	wave rci = ringcurrent_int
	
	redimension /n=(npts) ch1i, ch2i, pei, cffi, rci
	setscale /i x e1, e2, "eV", ch1i, ch2i, pei, cffi, rci

	otf_smo_int(ch1, ch1i, pe, smo)	
	otf_smo_int(ch2, ch2i, pe, smo)	
	otf_smo_int(pe, pei, pe, smo)	
	otf_smo_int(cff, cffi, pe, smo)	
	otf_smo_int(rc, rci, pe, smo)	
end

function otf_smo_int(win, wout, wpe, smo)
	wave win
	wave wout
	wave wpe
	variable smo
	
	//duplicate /o win, wtmp
	duplicate /free win, wtmp
	smooth /b /e=3 smo, wtmp
	wout = interp(x, wpe, wtmp)
end