Help: Is there ways to make parallel shifts for curves

I am an electrophysiologist and I am new to Igor in term of data analysis.

The data (waveforms, voltage vs. time) I collected from my physiological experiments not always have the same baseline. Many times, the baseline was shifted vertically due to recording noise, etc. Is there a Igor function to zero the baseline for all waveforms? Thanks.
You wouldn't really want Igor to just blindly zero all of your recorded traces, because it wouldn't know how to do so correctly. However, it's pretty easy in Igor to do what you want to accomplish.

What I typically do is that I calculate the average voltage or current of a wave before a stimulus was applied (current/voltage step, light flash, drug application, etc.). I then subtract that average pre-stimulus value from the entire trace.

Writing a function to do this for you in Igor is easy, but the function you write would depend some on how you store this kind of metadata (stimulus information), assuming you want your zeroing function to be "smart".

For now, we can probably just tell the function the time range over which we want to calculate the baseline, since if you have several waves recorded under the same conditions you probably want to use the same time range to calculate the baseline.

The other tricky thing is how do we tell the function what waves need to be zeroed? We could zero all waves in the current data folder, or zero the wave that is the basis for all traces on a given graph. Or we could pass a list of waves to the function in a string parameter and zero all of those waves. Which one of these is best depends on how you have organized your data. For my experiments, I usually zero all waves in a given data folder. Since you said you are new to Igor, if you want more background on what data folders are and how to use them, execute the following command from the Igor command line:
DisplayHelpTopic "Data Folders"



I've written two simple functions you can use to subtract the baseline from all numeric waves in the current data folder. Using these functions will overwrite the waves in place. If instead you want to create a copy of the data waves and zero the copy, you'll want to add in a call to the Duplicate operation within the For..EndFor loop and then pass the wave reference for the *duplicated* wave to ZeroAWave(). To use this code just copy it and paste it into an Igor procedure window. You can call it from the Igor command line like so:
ZeroWavesInCurrentDF("*", 0, 1)


This would calculate the baseline by averaging over the first second of the wave. For this to work as you expect it, you will need to have set the x scaling of your waves properly. To do that, you'll want to use the SetScale command. Depending on how you are acquiring your data, this might already have been done for you.

Here's the code:

//**
// Subtract the baseline from numeric waves in the current data folder.
//
// @param matchStr
//  A string that is passed to the Igor WaveList() function.  To
//  get all waves in the current data folder, use "*".  If, for example,
//  your data waves are named sweep0, sweep1, etc. then use
//  "sweep*".
// @param startX
//  The X value (time) which should be used as the beginning
//  of the window for calculating the baseline.
// @param endX
//  The X value (time) which should be used as the end
//  of the window for calculating the baseline.
//*
Function ZeroWavesInCurrentDF(matchStr, startX, endX)
    String matchStr
    Variable startX
    Variable endX
   
    // Get a list of numeric waves in the current data folder
    // that match the parameter matchStr.  The "TEXT:0"
    // part in the options string excludes text waves.  Look at
    // the command help for the WaveList() function as there
    // may be additional options that would be useful in your
    // situation.
    String listOfWaves = WaveList(matchStr, ";", "TEXT:0")

    String currentWaveName
    Variable n
    Variable numWaves = ItemsInList(listOfWaves, ";")
   
    // Iterate through the waves in listOfWaves and zero
    // each of them.
    For (n=0; n<numWaves; n+=1)
        currentWaveName = StringFromList(n, listOfWaves, ";")
        WAVE/Z currentWave = $(currentWaveName)
        if (!WaveExists(currentWave))
            continue
        endif
       
        // Call the function to actually zero this wave.
        ZeroAWave(currentWave, startX, endX)
    EndFor
End


//**
// Subtract the baseline from a wave.
//
// @param dataWave
//  A wave reference to the wave that should be zeroed.
// @param startX
//  The X value (time) which should be used as the beginning
//  of the window for calculating the baseline.
// @param endX
//  The X value (time) which should be used as the end
//  of the window for calculating the baseline.
//*
Function ZeroAWave(dataWave, startX, endX)
    WAVE dataWave
    Variable startX
    Variable endX
   
    WaveStats/Q/R=(startX, endX) dataWave
    dataWave -= V_avg
End


Thank you very much, aclight.




aclight wrote:
You wouldn't really want Igor to just blindly zero all of your recorded traces, because it wouldn't know how to do so correctly. However, it's pretty easy in Igor to do what you want to accomplish.

What I typically do is that I calculate the average voltage or current of a wave before a stimulus was applied (current/voltage step, light flash, drug application, etc.). I then subtract that average pre-stimulus value from the entire trace.

Writing a function to do this for you in Igor is easy, but the function you write would depend some on how you store this kind of metadata (stimulus information), assuming you want your zeroing function to be "smart".

For now, we can probably just tell the function the time range over which we want to calculate the baseline, since if you have several waves recorded under the same conditions you probably want to use the same time range to calculate the baseline.

The other tricky thing is how do we tell the function what waves need to be zeroed? We could zero all waves in the current data folder, or zero the wave that is the basis for all traces on a given graph. Or we could pass a list of waves to the function in a string parameter and zero all of those waves. Which one of these is best depends on how you have organized your data. For my experiments, I usually zero all waves in a given data folder. Since you said you are new to Igor, if you want more background on what data folders are and how to use them, execute the following command from the Igor command line:
DisplayHelpTopic "Data Folders"



I've written two simple functions you can use to subtract the baseline from all numeric waves in the current data folder. Using these functions will overwrite the waves in place. If instead you want to create a copy of the data waves and zero the copy, you'll want to add in a call to the Duplicate operation within the For..EndFor loop and then pass the wave reference for the *duplicated* wave to ZeroAWave(). To use this code just copy it and paste it into an Igor procedure window. You can call it from the Igor command line like so:
ZeroWavesInCurrentDF("*", 0, 1)


This would calculate the baseline by averaging over the first second of the wave. For this to work as you expect it, you will need to have set the x scaling of your waves properly. To do that, you'll want to use the SetScale command. Depending on how you are acquiring your data, this might already have been done for you.

Here's the code:

//**
// Subtract the baseline from numeric waves in the current data folder.
//
// @param matchStr
//  A string that is passed to the Igor WaveList() function.  To
//  get all waves in the current data folder, use "*".  If, for example,
//  your data waves are named sweep0, sweep1, etc. then use
//  "sweep*".
// @param startX
//  The X value (time) which should be used as the beginning
//  of the window for calculating the baseline.
// @param endX
//  The X value (time) which should be used as the end
//  of the window for calculating the baseline.
//*
Function ZeroWavesInCurrentDF(matchStr, startX, endX)
    String matchStr
    Variable startX
    Variable endX
   
    // Get a list of numeric waves in the current data folder
    // that match the parameter matchStr.  The "TEXT:0"
    // part in the options string excludes text waves.  Look at
    // the command help for the WaveList() function as there
    // may be additional options that would be useful in your
    // situation.
    String listOfWaves = WaveList(matchStr, ";", "TEXT:0")

    String currentWaveName
    Variable n
    Variable numWaves = ItemsInList(listOfWaves, ";")
   
    // Iterate through the waves in listOfWaves and zero
    // each of them.
    For (n=0; n<numWaves; n+=1)
        currentWaveName = StringFromList(n, listOfWaves, ";")
        WAVE/Z currentWave = $(currentWaveName)
        if (!WaveExists(currentWave))
            continue
        endif
       
        // Call the function to actually zero this wave.
        ZeroAWave(currentWave, startX, endX)
    EndFor
End


//**
// Subtract the baseline from a wave.
//
// @param dataWave
//  A wave reference to the wave that should be zeroed.
// @param startX
//  The X value (time) which should be used as the beginning
//  of the window for calculating the baseline.
// @param endX
//  The X value (time) which should be used as the end
//  of the window for calculating the baseline.
//*
Function ZeroAWave(dataWave, startX, endX)
    WAVE dataWave
    Variable startX
    Variable endX
   
    WaveStats/Q/R=(startX, endX) dataWave
    dataWave -= V_avg
End