WAVE/Z vs /ZZ
thomas_braun
I've been playing around with the new WAVE/ZZ flag in IP9.
Example code:
Function/WAVE GetNullWave()
return $""
End
Function MakeWave()
Make/O data
End
Function Dostuff()
MakeWave()
WAVE/Z data = I_DONT_EXIST
print 1, WaveExists(data)
WaveClear data
WAVE/ZZ data = I_DONT_EXIST
print 2, WaveExists(data)
WAveClear data
WAVE/Z data
print 3, WaveExists(data)
WaveClear data
WAVE/ZZ data
print 4, WaveExists(data)
WAveClear data
WAVE/Z data = GetNullWave()
print 5, WaveExists(data)
WaveClear data
WAVE/ZZ data = GetNullWave()
print 6, WaveExists(data)
WAveClear data
End
return $""
End
Function MakeWave()
Make/O data
End
Function Dostuff()
MakeWave()
WAVE/Z data = I_DONT_EXIST
print 1, WaveExists(data)
WaveClear data
WAVE/ZZ data = I_DONT_EXIST
print 2, WaveExists(data)
WAveClear data
WAVE/Z data
print 3, WaveExists(data)
WaveClear data
WAVE/ZZ data
print 4, WaveExists(data)
WAveClear data
WAVE/Z data = GetNullWave()
print 5, WaveExists(data)
WaveClear data
WAVE/ZZ data = GetNullWave()
print 6, WaveExists(data)
WAveClear data
End
This gives:
•dostuff()
1 0
2 0
3 1
4 0
5 0
6 0
So I would say that /ZZ is always better than /Z as picking up global waves is suprising. Is that correct?
So I would say that /ZZ is always better than /Z as picking up global waves is suprising. Is that correct?
The documentation for WAVE makes it very clear that if you provide LocalName without =pathToWave Igor will "[make] the connection between the local name and the actual wave". If you consider the documented behavior to be surprising then using /ZZ might be useful but it will require more verbose WAVE statements than necessary in some situations (you might even consider that to be an advantage).
Here is an example in which you would not want to use /ZZ:
Make/O/FREE ddd=enoise(5)
WaveStats/Q/W ddd
WAVE/ZZ M_WaveStats
print M_WaveStats[0]
End
If you insist on using /ZZ, you can easily rewrite that like this:
Make/O/FREE ddd=enoise(5)
WaveStats/Q/W ddd
WAVE/ZZ results = M_WaveStats
print results[0]
End
the later is slightly more verbose and might be considered more difficult to read.
The intent when adding the /ZZ flag was to make it possible to avoid the potentially expensive cost of runtime lookup by name in code that is very performance sensitive.
May 3, 2022 at 08:40 am - Permalink
Good, point. So I have to use /Z when I want to pickup global waves as in:
Make/O/FREE ddd=enoise(5)
WaveStats/Q/W ddd
WAVE/Z M_WaveStats
if(!WaveExists(M_WaveStats))
print "WaveStats error"
return NaN
endif
print M_WaveStats[0]
End
Not really a suprise re-reading the documentation.
Thanks!
May 3, 2022 at 10:00 am - Permalink
In Igor 8 and later, the cost to look up a wave in the current data folder is not that large, especially given the inherent overhead of running user code. But there is some cost.
Well, in your example, you can be reasonably confident that WaveStats/W will create the wave, so the /Z isn't strictly necessary as the lookup is very unlikely to fail. And in fact, it would be sufficiently surprising that you might want the error that lets you know about it. If you use /Z, though, it is expected that you will follow up with a call to WaveExists() since the /Z flag indicates that there is a reasonable chance that the lookup will fail.
May 3, 2022 at 12:07 pm - Permalink