
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

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