reference a wave loaded by the LoadWave operation
L.K.Chris
I am completely new to Igor and to programming in general, so my question might seem quite simple. I am dealing with large data files from FRET spectra. To start with, I would like to open all files and load waves containing specific parts of the columns. By combining some code I found in different forums this was no problem. I want to set a baseline for all the waves loaded, by running a separate function on them. this is what I have so far:
Function/S OpenMultiFileDialog()
Variable refNum
String outputPaths
String fileFilters = "All Files:.*;"
string message
Open /D /R /MULT=1 /F=fileFilters /M=message refNum
outputPaths = S_fileName
if (strlen(outputPaths) == 0)
Print "Cancelled"
else
Variable numFilesSelected = ItemsInList(outputPaths, "\r")
Variable i
for(i=0; i<numFilesSelected; i+=1)
String path = StringFromList(i, outputPaths, "\r")
LoadWave/D/J/A=wave/O/L={0,160256,511,5,1}path
if (V_flag >1) // loaded more than 1 wave
do
if (strlen (stringfromlist(i, S_waveNames)) == 0) // No more waves?
break
endif
wave testWave = $(stringFromList(i, S_waveNames))
SetBaseline (testwave)
i+=1
while(1)
endif
endfor
endif
End
function SetBaseline(wave2treat) //Function
wave wave2treat //wave reference
//store the name of the wave + the string "_base" into newWaveName
string newWaveName=NameofWave(wave2treat)+"_base"
//Duplicate the wave x as a wave named x_normalised
Duplicate/O wave2treat $newWaveName
//Reference x_normalised so that you can use it
wave newWave=$NewWaveName
newWave= wave2treat-WaveMin(wave2treat)
end
Variable refNum
String outputPaths
String fileFilters = "All Files:.*;"
string message
Open /D /R /MULT=1 /F=fileFilters /M=message refNum
outputPaths = S_fileName
if (strlen(outputPaths) == 0)
Print "Cancelled"
else
Variable numFilesSelected = ItemsInList(outputPaths, "\r")
Variable i
for(i=0; i<numFilesSelected; i+=1)
String path = StringFromList(i, outputPaths, "\r")
LoadWave/D/J/A=wave/O/L={0,160256,511,5,1}path
if (V_flag >1) // loaded more than 1 wave
do
if (strlen (stringfromlist(i, S_waveNames)) == 0) // No more waves?
break
endif
wave testWave = $(stringFromList(i, S_waveNames))
SetBaseline (testwave)
i+=1
while(1)
endif
endfor
endif
End
function SetBaseline(wave2treat) //Function
wave wave2treat //wave reference
//store the name of the wave + the string "_base" into newWaveName
string newWaveName=NameofWave(wave2treat)+"_base"
//Duplicate the wave x as a wave named x_normalised
Duplicate/O wave2treat $newWaveName
//Reference x_normalised so that you can use it
wave newWave=$NewWaveName
newWave= wave2treat-WaveMin(wave2treat)
end
This compiles but gives me an error "Attempt to use a null string variable". Any help/suggestions/explanations will be greatly appreciated!
Quick perusal doesn't show a problem, but my eyes are often blind to obvious mistakes. When the error occurs, you should get information about which line caused the error. That would be useful information for the experts looking at your posting.
Use the symbolic debugger: DisplayHelpTopic "The Debugger"
Right-click in any procedure window and select Enable Debugger. Then right-click again and select NVAR, SVAR, Wave Checking. Right-click once more and select Debug on Error.
Now run your procedure; when the error occurs the debugger should pop up stopped at the line causing the error (or the line after, because, after all, the line has already executed). The debugger will allow you to examine the values of the variables, and will show NULL for a string variable that is NULL.
Note that a NULL string variable is one that has never been assigned a value. It is different from a string variable of zero length.
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
January 30, 2013 at 08:50 am - Permalink
You will find that the string message is uninitialized.
January 30, 2013 at 10:49 am - Permalink
I followed the instructions and assigned the value to message. The function runs without errors, but it still doesn't produce the new waves through the the SetBaseline function. The waves of loadwaves operation are there though. Did I not reference them correctly, or is there a problem in the loop? should I introduce a new variable index, instead of i for the new list of waves created by LoadWaves? Or am I missing something?
January 31, 2013 at 01:50 am - Permalink
Variable i
for(i=0; i<numFilesSelected; i+=1)
String path = StringFromList(i, outputPaths, "\r")
LoadWave/D/J/A=wave/O/L={0,160256,511,5,1} path
Variable numWavesLoaded = V_flag // V_flag is set by LoadWave
String list = S_waveNames // S_waveNames is set by LoadWave
Variable j
for(j=0; j<numWavesLoaded; j+=1)
String name = StringFromList(j, list)
if (strlen(name) == 0) // No more waves?
break
endif
Wave testWave = $name
SetBaseline(testwave)
endfor
endfor
Note that I store the wave name in the local string variable name. This makes is much easier to debug than this:
break
endif
wave testWave = $(stringFromList(i, S_waveNames))
There is another problem here:
This evaluates the righthand side once for each point in newWave. Thus you are calling WaveMin once for each point in newWave. Replace it with this:
newWave= wave2treat-wMin
Or, since newWave is a clone of wave2treat, you can do this which may be slightly faster:
newWave -= wMin
January 31, 2013 at 03:08 am - Permalink
And another question while I'm at it. I want the waves to keep the name of the file when they are loaded. I've looked at some code, and I think I can manage to write it in, but the names of the files are more than 32 char. "2013 January 22 17_06_04-Frame-1.Csv" I was wondering if it was possible to delete characters from the beginning of the filename, instead of the end, since " 17_06_04-Frame-1" is the information I need?
Thanks again!
January 31, 2013 at 08:04 am - Permalink
One way to do it is this:
Wave newWave = $newWaveName
A better way is to have SetBaseline return a wave reference:
wave wave2treat //wave reference
. . . code that creates a new wave and a wave reference named newWave . . .
return newWave
End
Then change the SetBaseline call to:
<Do something with newWave>
January 31, 2013 at 06:01 pm - Permalink
With the caveat that I know only enough about regular expressions to be dangerous . . .
String fileName // e.g., "2013 January 22 17_06_04-Frame-1.Csv"
String leadingJunkMatcher = "([[:digit:]]+ [[:alpha:]]+ [[:digit:]]+ )"
String datasetNameMatcher = "([[:digit:]]{2}_[[:digit:]]{2}_[[:digit:]]{2}-[[:alpha:]]+-[[:digit:]]+)"
String trailingJunkMatcher = "(\\.[[:alpha:]]+)"
String regExp = leadingJunkMatcher + datasetNameMatcher + trailingJunkMatcher
String dataSetName, leadingJunk, trailingJunk
SplitString /E=regExp fileName, leadingJunk, dataSetName, trailingJunk
return dataSetName // e.g., "17_06_04-Frame-1"
End
You can test this like this:
January 31, 2013 at 06:04 pm - Permalink
I try to avoid regular expressions as they can be "temper-mental" for lack of a better word. I would accomplish this by treating the file name like a string list with the space character as the list separator.
string subname
subname = stringfromlist(3, filename, " ")
After this you can do further manipulation to remove the ".csv" and you'll also want to replace the hyphens with underscores. Some operations in Igor will not accept hyphens are part of the name (such as window titles) so I've gotten into the habit of always removing them.
February 1, 2013 at 06:53 am - Permalink
February 1, 2013 at 06:57 am - Permalink