Load JCAMP File With Titles As Wave Names

// Loads JCAMP-DX files containing one or multiple XY spectra and names output
// waves base on spectra titles. This procedure was written as a solution
// to the following IgorExchange post:
//	https://www.wavemetrics.com/forum/general/how-can-you-get-general-text-load-protocol-read-0th-line-name-instead-auto
//
// The file must contain the following labels for each spectrum:
//	##TITLE, ##FIRSTX, ##DELTAX, ##XYDATA, ##END
// Each spectrum must consist of two columns, X and Y.
// The X column is ignored and the output wave X scaling is set based on FIRSTX and DELTAX.
//
// To use the procedure, choose Data->Load Waves->Load JCAMP File With Title As Wave Name
// or execute the LoadJCAMPWithTitleAsWaveName function.

Menu "Load Waves"
	"Load JCAMP File With Title As Wave Name", LoadJCAMPWithTitleAsWaveName("", "")
End

Function PrepareJCAMPCatalogForNewRow(jcampCatalog)
	WAVE/T jcampCatalog

	int numRows = DimSize(jcampCatalog,0)
	if (numRows == 0)
		Redimension/N=(1,5) jcampCatalog
		SetDimLabel 1,0,title,jcampCatalog
		SetDimLabel 1,1,startLine,jcampCatalog
		SetDimLabel 1,2,endLine,jcampCatalog
		SetDimLabel 1,3,x0,jcampCatalog
		SetDimLabel 1,4,dx,jcampCatalog
	else
		InsertPoints /M=0 numRows, 1, jcampCatalog
	endif
End

Function AddToCatalog(title, dataStartLine, dataEndLine, x0, dx, jcampCatalog)
	String title
	int dataStartLine, dataEndLine
	double x0, dx
	WAVE/T jcampCatalog
	
	if (strlen(title) == 0)
		Print "Spectrum missing ##TITLE label"
		return -1
	endif
	if (numtype(dataStartLine) != 0)
		Print "Spectrum missing ##XYDATA label"
		return -1
	endif
	if (numtype(dataEndLine) != 0)
		Print "Spectrum missing ##END label"
		return -1
	endif
	if (numtype(x0) != 0)
		Print "Spectrum missing ##FIRSTX label"
		return -1
	endif
	if (numtype(dx) != 0)
		Print "Spectrum missing ##DELTAX label"
		return -1
	endif

	int row = DimSize(jcampCatalog,0)
	
	PrepareJCAMPCatalogForNewRow(jcampCatalog)
	
	jcampCatalog[row][%title] = title
	jcampCatalog[row][%startLine] = num2istr(dataStartLine)
	jcampCatalog[row][%endLine] = num2istr(dataEndLine)
	jcampCatalog[row][%x0] = num2str(x0)
	jcampCatalog[row][%dx] = num2str(dx)
	
	return 0
End

Function/WAVE MakeJCAMPCatalog(pathName, filePath)
	String pathName		// Name of symbolic path or "" to display dialog.
	String filePath		// Name of file or "" to display dialog. Can also be full or partial path relative to symbolic path.
 
	Variable refNum
 
	Open/R/P=$pathName refNum as filePath
	
	String title=""
	int dataStartLine=-1, dataEndLine=-1
	double x0=NaN, dx=NaN
	
	Make/FREE/T/N=0 jcampCatalog
	
	int spectrumNumber = 0
	int lineNum = 0
	do
		String text
		FReadLine refNum, text
		if (strlen(text) == 0)
			break
		endif
		
		String format
		
		if (strsearch(text,"##TITLE",0) == 0)
			format = "##TITLE= %s"
			sscanf text, format, title
		endif
		
		if (strsearch(text,"##FIRSTX",0) == 0)
			format = "##FIRSTX= %g"
			sscanf text, format, x0
		endif
		
		if (strsearch(text,"##DELTAX",0) == 0)
			format = "##DELTAX= %g"
			sscanf text, format, dx
		endif
		
		if (strsearch(text,"##XYDATA",0) == 0)
			dataStartLine = lineNum + 1
		endif
		
		if (strsearch(text,"##END",0) == 0)
			dataEndLine = lineNum - 1
			if (AddToCatalog(title, dataStartLine, dataEndLine, x0, dx, jcampCatalog) != 0)
				break
			endif
			spectrumNumber += 1
			title=""
			dataStartLine=-1; dataEndLine=-1
			x0=NaN; dx=NaN
		endif
		
		lineNum += 1
	while(1)
	
	Close refNum
	
	return jcampCatalog
End

Function/WAVE LoadJCAMPSpectrum(pathName, filePath, title, dataStartLine, dataEndLine, x0, dx)
	String pathName		// Name of symbolic path or "" to display dialog.
	String filePath		// Name of file or "" to display dialog. Can also be full or partial path relative to symbolic path.
	String title
	int dataStartLine, dataEndLine
	double x0, dx
	
	
	String name = title
	name = CleanupName(name, 0)
	String columnInfoStr
	sprintf columnInfoStr, "N='_skip_';N='%s';", name	// Skip X wave because we use wave scaling
	int numDataLines = dataEndLine - dataStartLine + 1
	LoadWave/G/D/A/B=columnInfoStr/P=$pathName/O/Q/L={0,dataStartLine,numDataLines,0,0} filePath
	
	WAVE w = $name		// Create wave reference
	SetScale/P x, x0, dx, "", w
	
	return w
End

static Function AddWaveToList(jcampWaves, w)
	WAVE/WAVE jcampWaves
	WAVE w
	
	int index = DimSize(jcampWaves,0)
	Redimension/N=(index+1) jcampWaves
	jcampWaves[index] = w
End

static Function DisplayInTable(jcampWaves)
	WAVE/WAVE jcampWaves
	
	int numWaves = DimSize(jcampWaves, 0)
	int i
	for(i=0; i<numWaves; i+=1)
		WAVE w = jcampWaves[i]
		if (i == 0)
			Edit w
		else
			AppendToTable w
		endif
	endfor
End

static Function DisplayInGraph(jcampWaves)
	WAVE/WAVE jcampWaves
	
	int numWaves = DimSize(jcampWaves, 0)
	int i
	for(i=0; i<numWaves; i+=1)
		WAVE w = jcampWaves[i]
		if (i == 0)
			Display w
		else
			AppendToGraph w
		endif
	endfor
End

Function LoadJCAMPWithTitleAsWaveName(pathName, filePath)
	String pathName		// Name of symbolic path or "" to display dialog.
	String filePath		// Name of file or "" to display dialog. Can also be full or partial path relative to symbolic path.
 
	Variable refNum
 
	// Possibly display Open File dialog.
	if ((strlen(pathName)==0) || (strlen(filePath)==0))
		String fileFilters = "JCAMP Files (*.dx,*.jdx):.dx,.jdx;"
		fileFilters += "Text Files (*.txt,*.dat):.txt,.dat;"
		fileFilters += "All Files:.*;"
		Open /D /R /P=$pathName /F=fileFilters refNum as filePath
		filePath = S_fileName			// S_fileName is set by Open/D
		if (strlen(filePath) == 0)		// User cancelled?
			return -1
		endif
		// filePath is now a full path to the file.
	endif
	
	WAVE/T jcampCatalog = MakeJCAMPCatalog(pathName, filePath)	// Returns a free wave
	
	Make/WAVE/FREE/N=0 jcampWaves
	
	int numSpectra = DimSize(jcampCatalog,0)
	int spectrumNumber = 0
	do
		String title = jcampCatalog[spectrumNumber][%title]
		int dataStartLine = str2num(jcampCatalog[spectrumNumber][%startLine])
		int dataEndLine = str2num(jcampCatalog[spectrumNumber][%endLine])
		double x0 = str2num(jcampCatalog[spectrumNumber][%x0])
		double dx = str2num(jcampCatalog[spectrumNumber][%dx])
		WAVE w = LoadJCAMPSpectrum(pathName, filePath, title, dataStartLine, dataEndLine, x0, dx)
		AddWaveToList(jcampWaves, w)
		spectrumNumber += 1
	while(spectrumNumber < numSpectra)
	
	DisplayInTable(jcampWaves)
	DisplayInGraph(jcampWaves)
 
	return 0
End

 

Forum

Support

Gallery

Igor Pro 10

Learn More

Igor XOP Toolkit

Learn More

Igor NIDAQ Tools MX

Learn More