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-…
//
// 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 9

Learn More

Igor XOP Toolkit

Learn More

Igor NIDAQ Tools MX

Learn More