//"OpenHSDC" function written by Ben Ohler at Veeco Metrology Inc. 06/07/2006
//
// Use: 				Opens Nanoscope High Speed Data Capture (HSDC) files in IGOR and loads data into waves with appropriate scaling
//
// Compatibility:	Developed and tested using HSDC files from NanoScope v7r2 and Igor Pro v 4 running under Windows XP.
//					Import code should be tolerant of additions and re-ordering of parms in data header.
//					The header text strings are declared and assigned at the beginning of the function. These could be changed as needed to update compatibility with future file formats.
//
// Syntax:			OpenHSDC("prefix",scale,owr)
//
//					where:
//					"prefix": Optional text sting containing characters to be used as prefixes for the wave names.
//							"prefix_" :  Text must be enclosed in double quotes and should begin with a letter. An trailing underscore is recommended.
//							"" : If no prefix is desired an empty string must still be entered
//
//					scale: controls whether or not the "hard" scale (Volts) or "soft" scale (typically nm) is used in the wave scaling
//							0: Use hard scale
//							1: Use soft scale (for data channels where a soft scale is given)
//
//					owr: controls whether or not existing waves get overwritten or if numerical suffix is incremented instead
//							0: Do not overwrite existing waves, use next available numerical suffix.
//							1: Overwrite existing waves, if any. This will always result in wave names ending in zero.
//
// Notes:
//					Waves are named automatically according to their data type (i.e.- VerticalDeflection, Input3, etc.) followed by a numerical suffix that enables unique wave names
//					and with the prefix described above.
//
//					The following global waves are created by this function: 
//							
//							HSDC, HSDC_offset, HSDC_datatype, HSDC_rate, HSDC_samples, HSDC_hard, HSDC_hardlabel, HSDC_soft, HSDC_softlabel
//
//					!!!Any existing waves by the same name will be overwritten!!!
//
//
// Example:
//
//					HSDC("titin_",1,1)
//
//					-This will prompt for a data file, load the data into waves prefixed by "titin_" with the soft scaling enabled where available.
//
// Typical Output:
//
//					C:Documents and Settings:ohler:Desktop:4chan
//					File contains: 4 HSDC channels
//  
//					Parsing data files header...
//  
//					 Channel  1 (VerticalDeflection  ): Offset=    40960 bytes; Rate=   6.25 MHz; Samples=   626688 pts; Hard scale=  -4.000 V; Soft scale=  -4.000 V
//					 Channel  2 (LateralDeflection   ): Offset=  1294336 bytes; Rate=   6.25 MHz; Samples=   626688 pts; Hard scale=  -4.000 V; Soft scale=  -4.000 V
//					 Channel  3 (SignalSum           ): Offset=  2547712 bytes; Rate= 500.00 kHz; Samples=    50016 pts; Hard scale=  24.576 V; Soft scale=  24.576 V
//					 Channel  4 (Height              ): Offset=  2647744 bytes; Rate= 500.00 kHz; Samples=    50016 pts; Hard scale= 440.000 V; Soft scale=  12.260 nm/V
//
//
//					Loading data into waves...
//  
//					 Channel  1 (VerticalDeflection  ) has been imported with the wave name: "titin_VerticalDeflection0" and has been scaled to use units of V
//					 Channel  2 (LateralDeflection   ) has been imported with the wave name: "titin_LateralDeflection0" and has been scaled to use units of V
//					 Channel  3 (SignalSum           ) has been imported with the wave name: "titin_SignalSum0" and has been scaled to use units of V
//					 Channel  4 (Height              ) has been imported with the wave name: "titin_Height0" and has been scaled to use units of nm
















#pragma rtGlobals=1		// Use modern global access method.



Function OpenHSDC(prefix,scale,owr)

	String prefix
	Variable scale
	Variable owr
	Variable refNum
	Variable i
	String str
	
	// Search strings used for parsing data file
	String sOL1HSDC = "\Start context: OL1HSDC"
	String sOL2HSDC = "\Start context: OL2HSDC"
	String sHSDCCiao = "\*Ciao HSDC list"
	String sHSDC_offset = "\Data offset:"
	String sHSDC_datalength = "\Data length:"
	String sHSDC_bytesperpixel = "\Bytes/pixel:"
	String sHSDC_datatype = "\High Speed Data Type:"
	String sHSDC_rate = "\High Speed Data Channel Rate:"
	String sHSDC_samples = "\Number of samples:"
	String sHSDC_hard = "\High Speed Data Hard Scale:"
	String sHSDC_soft = "\High Speed Data Soft Scale:"
	String sEOF = "\*File list end"
	
	Variable HSDC_count = 0
	Make/O/N=5/D HSDC = 0
	Make/O/N=5/D HSDC_offset = 0
	Make/O/N=5/T HSDC_datatype = "null"
	Make/O/N=5/D HSDC_rate = 0
	Make/O/N=5/D HSDC_samples= 0
	Make/O/N=5/D HSDC_hard = 0
	Make/O/N=5/T HSDC_hardlabel = "null"
	Make/O/N=5/D HSDC_soft = 0
	Make/O/N=5/T HSDC_softlabel = "null"
	
	

	// Open file for read.
	Open/R/Z=2 refNum
	
	// Store results from Open in a safe place, report any errors
	Variable err = V_flag
	String sHSDCfilename = S_fileName

	if (err == -1)
		Print "HSDC file open cancelled by user."
		return -1
	endif

	if (err != 0)
		DoAlert 0, "Unknown error opening HSDC file."
		return err
	endif
	
	// Look in the first 10 lines to see if it's really a HSDC file
	for (i=0;i<10;i+=1)
		
		FReadLine refNum, str		// Read line into string variable
		if(strsearch(str,sOL1HSDC,0)!=-1)
			Break
		elseif(strsearch(str,sOL2HSDC,0)!=-1)
			Break
		endif
	endfor
	
	if(i==10)
		DoAlert 0, "Not a valid Nanoscope HSDC file."
		return err
	endif
	
	//Start parsing header to find HSDC ciao data
	
	do
		FReadLine refNum, str		// Read line into string variable
	
		if(strsearch(str,sHSDCCiao,0)!=-1)
			HSDC_count+=1
			HSDC[HSDC_count]=1 //HSDC channel found
			
			variable looptimer = 0
			
			do
				
				FReadLine refNum, str		// Read line into string variable
				looptimer+=1
				
				if(strsearch(str,sHSDC_offset,0)!=-1)
					HSDC[HSDC_count]+=1 		//HSDC offset for channel found
					variable offset=0
					sscanf str, sHSDC_offset+" %f", offset	//parse ciao line for offset
					
					HSDC_offset[HSDC_count]=offset		//store offset in offset wave
				endif

				if(strsearch(str,sHSDC_datalength,0)!=-1)
					HSDC[HSDC_count]+=1 		//HSDC data length for channel found
					variable datalength=0
					sscanf str, sHSDC_datalength+" %f", datalength	//parse ciao line for data length
				endif

				if(strsearch(str,sHSDC_bytesperpixel,0)!=-1)
					HSDC[HSDC_count]+=1 		//HSDC bytes per pixel for channel found
					variable bytesperpixel=0
					sscanf str, sHSDC_bytesperpixel+" %f", bytesperpixel	//parse ciao line for bytes per pixel
				endif

				if(strsearch(str,sHSDC_datatype,0)!=-1)
					HSDC[HSDC_count]+=1 		//HSDC data type for channel found
					string datatype = "null"
					string datatype2 = "null"
					sscanf str, sHSDC_datatype+" %s%s", datatype, datatype2	//parse ciao line for data type
					datatype=datatype+datatype2
					
					HSDC_datatype[HSDC_count]=datatype		//store data type in wave
					
				endif			
			
				if(strsearch(str,sHSDC_rate,0)!=-1)
					HSDC[HSDC_count]+=1 		//HSDC rate for channel found
					variable rate=0
					sscanf str, sHSDC_rate+" %f", rate	//parse ciao line for rate
					
					HSDC_rate[HSDC_count]=rate		//store rate in rate wave
				endif			
			
				//if(strsearch(str,sHSDC_samples,0)!=-1)
				//	HSDC[HSDC_count]+=1 		//HSDC samples for channel found
				//	variable samples=0
				//	sscanf str, sHSDC_samples+" %f", samples	//parse ciao line for samples	//samples parm in data file is bogus
				//	//printf "samples=  %d ;", samples
				//	HSDC_samples[HSDC_count]=samples		//store samples in samples wave
				//endif						
			
				if(strsearch(str,sHSDC_hard,0)!=-1)
					HSDC[HSDC_count]+=1 		//HSDC hard scale for channel found
					variable hard=0
					string hardlabel="null"
					sscanf str, sHSDC_hard+" %f %s", hard, hardlabel	//parse ciao line for hard scale
					
					HSDC_hard[HSDC_count]=hard		//store hard scale in hard scale wave
					HSDC_hardlabel[HSDC_count]=hardlabel
				endif						
			
				if(strsearch(str,sHSDC_soft,0)!=-1)
					HSDC[HSDC_count]+=1 		//HSDC soft scale for channel found
					variable soft=0
					string softlabel = "null"
					sscanf str, sHSDC_soft+" %f %s", soft, softlabel	//parse ciao line for soft scale
					
					HSDC_soft[HSDC_count]=soft		//store soft scale in soft scale wave
					HSDC_softlabel[HSDC_count]=softlabel
				endif							
			
				if(looptimer>50)
					DoAlert 0, "Failed to find one or more HSDC parameters. Aborting Load."
					return err
				endif
				
				
		
			while(HSDC[HSDC_count]!=8)  //continues to read lines until all 7 parms are found for channel
		
			HSDC_samples[HSDC_count]=datalength/bytesperpixel		//calculate number of samples from data length and bytes per pixel because the sample parm is bogus
			
		endif		
		
	while(strsearch(str,sEOF,0)==-1)
	
	printf "\r%s" sHSDCfilename
	printf "\rFile contains: %d HSDC channels\r",HSDC_count
	
	printf "\rParsing data files header...\r"
	
	variable n
	for(n=1;n<HSDC_count+1;n+=1)
	printf "\r Channel %2d (%-20s): Offset= %8d bytes; Rate= %6.2W1PHz; Samples= %8d pts; Hard scale= %7.3f %s; Soft scale= %7.3f %s",n,HSDC_datatype[n],HSDC_offset[n],HSDC_rate[n],HSDC_samples[n],HSDC_hard[n],HSDC_hardlabel[n],HSDC_soft[n],HSDC_softlabel[n]
	endfor
				
	Close refNum	// Close file
	
	
	variable b
	
	printf "\r\r\rLoading data into waves...\r"
	
	for(b=1;b<HSDC_count+1;b+=1)
	
		String sHSDCwavename=prefix+HSDC_datatype[b] //appends optional prefix to waves name
		String cmd
		
		if(owr!=1)		//use function overwrite parm to determine whether waves should be overwritten
			sprintf cmd, "GBLoadWave/Q/B/A=%s/T={16,4}/S=%d/W=1/U=%d \"%s\"", sHSDCwavename,HSDC_offset[b],HSDC_samples[b],sHSDCfilename
		else
			sprintf cmd, "GBLoadWave/Q/O/B/A=%s/T={16,4}/S=%d/W=1/U=%d \"%s\"", sHSDCwavename,HSDC_offset[b],HSDC_samples[b],sHSDCfilename
		endif
		
		
		Execute cmd  //can't execute GBLoadWave direct from function
		
		SVAR S_waveNames
		variable l
		l=strlen(S_waveNames)
		S_waveNames=S_waveNames[0,l-2] //strips the trailing semicolon from wave string
				
		Wave w=$S_waveNames
		w=w/(2^16)*HSDC_hard[b] //Scale waves by hard scale
		SetScale/P x 0,1/HSDC_rate[b],"s", w;DelayUpdate //Scales time axis
		SetScale d 0,0,HSDC_hardlabel[b], w //Applies data units
		
		if(scale!=0&&HSDC_soft[b]!=HSDC_hard[b])  //check function scale parm to see if soft scale should be applied: 0: use hard scale , !=0: use soft scale
		
			w=w*HSDC_soft[b] //scales by soft scale
			String newunits
			newunits=HSDC_softlabel[b]
			l=strlen(newunits)
			newunits=newunits[0,l-3]
			SetScale d 0,0,newunits, w //Applies soft data units
		endif
		
				
		if(scale!=0&&HSDC_soft[b]!=HSDC_hard[b])  //check function scale parm to see if soft scale should be applied: 0: use hard scale , !=0: use soft scale
				printf "\r Channel %2d (%-20s) has been imported with the wave name: \"%s\" and has been scaled to use units of %s", b, HSDC_datatype[b],S_waveNames,newunits
		else
				printf "\r Channel %2d (%-20s) has been imported with the wave name: \"%s\" and has been scaled to use units of %s", b, HSDC_datatype[b],S_waveNames,HSDC_hardlabel[b]	
		endif
	
	
	endfor
	
	
	printf "\r"
	
	
	
End