Load, Process and Display Modular Programming Example
hrodstein
#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
// 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
Forum
Support
Gallery
Igor Pro 9
Learn More
Igor XOP Toolkit
Learn More
Igor NIDAQ Tools MX
Learn More
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
February 24, 2015 at 11:24 am - Permalink