Load, Process and Display Modular Programming Example

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

// This is an answer to the question:
//  How do I load a delimited text file, do a histogram of each loaded wave,
//  and create a graph showing the histograms?
// Or more generally:
//  How do I load waves from a file, process them, and display the results.
//
// To illustrate modular programming, the procedures are organized into the following steps:
//  Load Waves                  // Load waves from a file
//  Process Waves               // Create histograms of loaded waves
//  Display Processed Waves     // Create a graph showing histograms
// This modularity makes it possible to test and use the modules separately which
// makes development easier, results in more comprehensible code and increases reusability.
//
// The LoadProcessAndDisplay function does everything (loads, processes and displays).
//
// The best way to understand the procedures is to read the highest level
// (LoadProcessAndDisplay, at the bottom of the file) first.
// Then read the subroutines (LoadDelimitedFile, ProcessWaves and DisplayProcessedWaves).
//
// To try the routine, choose Macros->Load, Process and Display.
// Then select a delimited text file.

// Allow comma, tab or spaces as the delimiter in the delimited text file.
static StrConstant kDelimitersStr = ",\t "

Menu "Macros"
    "Load, Process, and Display...", LoadProcessAndDisplay()
End

// LoadDelimitedFile(pathName, fileName)
// Returns a semicolon-separated list of waves loaded or "" if cancel.
Function/S LoadDelimitedFile(pathName, fileName)
    String pathName     // Name of an Igor symbolic path or "".
    String fileName     // Name of file or full path to file.

    // First get a valid reference to a file.
    if ((strlen(pathName)==0) || (strlen(fileName)==0))
        // Display dialog looking for file.
        Variable refNum
        Open/D/R/P=$pathName refNum as fileName
        fileName = S_fileName           // S_fileName is set by Open/D
        if (strlen(fileName) == 0)          // User cancelled?
            return ""
        endif
    endif
   
    // Now load the data. The /V flag specifies the accepted delimiters in the data file.
    // Add the /A flag if you don't want the "Loading Delimited Text" dialog.
    // Add the /O flag if you want to overwrite existing waves with the same names.
    LoadWave /J /D /E=1 /K=0 /W /V={kDelimitersStr,"",0,0} /P=$pathName fileName
    Variable numWavesLoaded = V_flag            // V_flag is set by LoadWave
    if (numWavesLoaded == 0)
        return ""
    endif
   
    String listOfWavesLoaded = S_waveNames  // S_waveNames is set by LoadWave
   
    return listOfWavesLoaded
End

// ProcessWave(w, index)
// Processes a single input wave creating an output wave.
// Returns name of output wave.
Function/S ProcessWave(wIn, index)
    Wave wIn
    Variable index                      // Currently not used
   
    Variable numHistBins = 10       // Desired number of bins
   
    String destWaveName = NameOfWave(wIn) + "_hist"
    Make /O /N=(numHistBins) $destWaveName
    Histogram /B=1 wIn, $destWaveName
   
    return destWaveName
End

// ProcessWaves(listIn)
// Processes a list of waves.
// list is a semicolon-separated list of input waves.
// The function result is a semicolon-separated list of output waves.
Function/S ProcessWaves(listIn)
    String listIn                                           // Semicolon-separated list
   
    Variable numItems = ItemsInList(listIn)
    String listOut = ""                                 // Semicolon-separated list
   
    Variable i
    for(i=0; i<numItems; i+=1)
        String nameIn = StringFromList(i, listIn)
        Wave wIn = $nameIn                          // Create wave reference
        String nameOut = ProcessWave(wIn, i)
        listOut += nameOut + ";"
    endfor
   
    return listOut
End

// GetIndexedRGBColor(colorIndex, red, green, blue)
// Returns distinct RGB colors for different traces.
// colorIndex is 0..15 and selects the color that is returned.
// red, green and blue are outputs.
// See below for an example.
Function GetIndexedRGBColor(colorIndex, red, green, blue)
    Variable colorIndex
    Variable &red, &green, &blue                // Outputs

    Variable numColors = 16                 // Number of colors in the following switch
   
    colorIndex = mod(colorIndex, numColors)         // Wrap around if necessary
    switch(colorIndex)
        case 0:     // Time wave
            red = 0; green = 0; blue = 0;                               // Black
            break
           
        case 1:
            red = 65535; green = 16385; blue = 16385;           // Red
            break
           
        case 2:
            red = 2; green = 39321; blue = 1;                       // Green
            break
           
        case 3:
            red = 0; green = 0; blue = 65535;                       // Blue
            break
           
        case 4:
            red = 39321; green = 1; blue = 31457;                   // Purple
            break
           
        case 5:
            red = 39321; green = 39321; blue = 39321;           // Gray
            break
           
        case 6:
            red = 65535; green = 32768; blue = 32768;           // Salmon
            break
           
        case 7:
            red = 0; green = 65535; blue = 0;                       // Lime
            break
           
        case 8:
            red = 16385; green = 65535; blue = 65535;           // Turquoise
            break
           
        case 9:
            red = 65535; green = 32768; blue = 58981;           // Light purple
            break
           
        case 10:
            red = 39321; green = 26208; blue = 1;                   // Brown
            break
           
        case 11:
            red = 52428; green = 34958; blue = 1;                   // Light brown
            break

        case 12:
            red = 65535; green = 32764; blue = 16385;           // Orange
            break

        case 13:
            red = 1; green = 52428; blue = 26586;                   // Teal
            break

        case 14:
            red = 1; green = 3; blue = 39321;                       // Dark blue
            break

        case 15:
            red = 65535; green = 49151; blue = 55704;           // Pink
            break
    endswitch
End

// DisplayProcessedWave(w, index)
// Displays a single wave in a new graph, if index is zero, or in the top graph, if index is non-zero.
Function DisplayProcessedWave(w, index)
    Wave w
    Variable index
   
    if (index == 0)
        Display w
    else
        AppendToGraph w
    endif
   
    ModifyGraph mode=5      // Bars display mode
   
    // Get name of last trace added
    String traceList = TraceNameList("", ";", 1)
    Variable numTraces = ItemsInList(traceList)
    String traceName = StringFromList(numTraces-1, traceList)

    Variable red, green, blue
    GetIndexedRGBColor(index, red, green, blue)
    ModifyGraph rgb($traceName) = (red, green, blue)
End

// DisplayProcessedWaves(processedWaveList)
// Displays a list of waves.
// processedWaveList is a semicolon-separated list of waves to be displayed.
Function DisplayProcessedWaves(processedWaveList)
    String processedWaveList        // Semicolon-separated list

    Variable numItems = ItemsInList(processedWaveList)
   
    Variable i
    for(i=0; i<numItems; i+=1)
        String name = StringFromList(i, processedWaveList)
        Wave w = $name                      // Create wave reference
        DisplayProcessedWave(w, i)
    endfor
End

// LoadProcessAndDisplay()
// Loads data from a delimited text file, processes the data and displays the processed result.
Function LoadProcessAndDisplay()
    String loadedWavesList = LoadDelimitedFile("", ",")
    if (strlen(loadedWavesList) == 0)
        return -1               // Load cancelled
    endif
   
    String processedWaveList = ProcessWaves(loadedWavesList)
    if (strlen(loadedWavesList) == 0)
        return -1               // Should not happen
    endif

    DisplayProcessedWaves(processedWaveList)
End

Hi Mr Rodstein,

I am new with IgorPro and I am struggling a little
I have tried to break up your LoadProcessAndDisplay(). I would like to use the already loaded data to ProcessAndDisplay.
I attempted to break up your Procedure by changing the Menu "Macros" into

Menu "Macros"
"Load, Process, and Display...", LoadProcessAndDisplay()
"Load", LoadDelimitedFile("", "")
"Process", ProcessWaves("")
"Display", DisplayProcessedWaves("")

The Loading part, off course, runs on its own. The Process and Display miss their input. I would like to have ProccessWaves and DisplayProccessedWaves run on a variable amount of waves that are already plotted. Could you please help me out? Thanks


Forum

Support

Gallery

Igor Pro 9

Learn More

Igor XOP Toolkit

Learn More

Igor NIDAQ Tools MX

Learn More