extracting open and close times for a valve from a continuous sequence

Hi, I'm not sure how to handle this problem in IGOR, or if it can even be done.

Here is my setup:
I have an instrument that whose inlet is controlled by a valve. This valve opens at irregular intervals, but usually about once every ten minutes. Once open, the valve then closes after a certain interior pressure is reached - so the "valve open time" is also not regular. The raw data feed that we get is recorded every second, and the valve status is indicated by a 0 or a 1, where 0 is closed and 1 is open. What I'd like to do is to extract all of the times where the valve is open.

basically, I have a data set that is all "0"'s, with randomly sized sets of "1"'s scattered throughout. I'd like to pick out time for the first and last "1" in each set, and I'm not sure how to do that. I'd appreciate any help!
Here is an example that illustrates something like what you are describing:
// FindOnes(wIn, outputWaveName)
// Example:
//  Make/O sampleData = {0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1}
//  SetScale/P x 0, 1, "s" sampleData       // 1 second per point
//  Edit sampleData.id
//  FindOnes(sampleData, "whereTheOnesAre")
//  AppendToTable whereTheOnesAre
Function FindOnes(wIn, outputWaveName)
    Wave wIn                    // Input wave
    String outputWaveName       // Desired name for output wave
   
    Variable numPoints = numpnts(wIn)
    Extract /INDX /O wIn, $outputWaveName, wIn==1       // Output wave now contains the X values where wIn contains 1
    Wave wOut = $outputWaveName             // Create wave reference to output wave
    Variable numOutputPoints = numpnts(wOut)
    Printf "Found %d points containing 1\r", numOutputPoints
End

jschroed wrote:
basically, I have a data set that is all "0"'s, with randomly sized sets of "1"'s scattered throughout. I'd like to pick out time for the first and last "1" in each set, and I'm not sure how to do that. I'd appreciate any help!


FindLevels should do what you want. From help...

The FindLevels operation searches the named wave to find one or more X values at which the specified Y level is crossed.


This will find all locations where a level of 0.5 was crossed in the wave wValveWave.

 FindLevels /Edge=0  wValveWave, 0.5

The location of the crossing will be halfway between the delta x of your wave scaling. If needed, you can add half delta x to the start of the valve on time and subtract the same from the end of the time to place the start/stop times at the "1" value. Also watch out for the possibility that the data wave begins or ends with a value of "1".

Thank you, FindLevels seems like a great place to start. Do you know if there is any way of only selecting times where the level (0.5 in this case) was crossed in the positive from the times it was crossed in the negative direction (i.e. to separate when it went 0 -> 1 from when it went 1 -> 0)?
jschroed wrote:
Thank you, FindLevels seems like a great place to start. Do you know if there is any way of only selecting times where the level (0.5 in this case) was crossed in the positive from the times it was crossed in the negative direction (i.e. to separate when it went 0 -> 1 from when it went 1 -> 0)?


/Edge=1 finds crossings where Y is increasing
/Edge=2 finds crossings whee Y is decreasing.

This is explained in the help file.

I find the Help Browser (Help Menu > Command Help) to be a most wonderful source of info.

Also if you set the crossing level to something like, say, 0.9. Then x value reported by FindLevels will be much closer to x value where y = 1 at the crossing. If your x values are integers, then round will return the exact x value that you seek.