Reference to a wave slice
_sk
I am curious if one can create a reference to a slice of a wave, like so:
make/o/n=(10,2) w_source = gnoise(p)
wave w_slice = w_source[][1]
wave w_slice = w_source[][1]
In C-speak, can one get a pointer to a specific address of the wave without copying data? And if not, what is the best way to go about something like this?
As far as I understand, using
duplicate
and/or make
will deep copy the data and would lead, naturally, to independent changes in w_source
and w_slice
.
April 20, 2017 at 08:31 am - Permalink
I am aware of the functionality dependencies provide. Dependencies, unfortunately, are not the answer to how one references a slice of a wave without duplicating memory.
best,
_sk
April 20, 2017 at 12:36 pm - Permalink
MatrixOP/FREE w_slice = col(w_source,1)
though this has the cost of memory allocation.
April 20, 2017 at 01:00 pm - Permalink
Would changes in
w_slice
propagate tow_source
? Is the memory referenced or copied? But if there is allocation I would think it is copied...Thanks.
best,
_sk
April 20, 2017 at 01:09 pm - Permalink
It is copied. May I ask what your goal is?
April 21, 2017 at 02:16 am - Permalink
I have a 2d wave as output from an instrument (columns for channels) and was wondering if I can operate on various columns without copying/duplicating data everytime I need to operate on a particular column/channel. There is a side issue, namely, that each time when I operate on the copied column, I need to copy back the data to the 2d wave to "update". I can get around the issue by making a wave wave with each channel being a separate wave upon import in my analysis program and flattening to a 2d wave upon save for integrity with other functions already written expecting the instrument-output 2d wave. Which is the same as splitting the original 2d wave into channels and saving each wave in a datafolder; but somehow the wave/wave seems more compact.
As far as I understand, however, this pointer vs copy issue is a somewhat of a limitation in Igor. I don't quite get why Igor differentiates between a whole wave and a slice of a wave. The same way a wave header points to the beginning of the wave data it can also point to the beginning of the slice data. I don't remember off the top of my head, but there was also some checksumming going on, which can also be dealt wilth. A fat pointer scenario can also be conceived, in which case it is only the fat pointer that gets modified/ copied. I am just saying.
best,
_sk
April 22, 2017 at 12:59 am - Permalink
Igor partialy suports a wave reference poiting to the midle of a wave,see:
display aaa[][30]
However,this is not a general feature!
Wish Igor can realize this feature in the future. It is really convinient when operating on 2D waves if one can reference to the midle of the wave.
April 22, 2017 at 04:45 am - Permalink
@_sk: The pointer would only work along rows and has be limited to "well-behaved" operations. Imagine to insert data points in a slice along layers...
A useful thing -- for lazy guys like myself -- might be aliases for subranges (SubRangeAlias) on a parser level:
SRA Ch5=w_keithley[][5]
ch5+=10
where 'Ch5' is automatically replaced by 'w_keithley[][5]' and then compiled. This is not a pointer to that part of the wave. As a benefit, it would also work with fancy ranges, e.g., '[p][p]' (sic).
It might also be handy in the scope of the command window in case one uses data with long names stored in different data folders at the same time.
HJ
April 22, 2017 at 06:15 am - Permalink
You're correct that there's no concept of a wave reference that's a "slice" or some portion of a real wave. A few operations accept a subrange, specified either with /R or /RMD flags, or by a regular subrange specification like wave0[0,10][*]. We've considered the idea of adding something like a virtual slice, but doing so would be a *lot* of work. The code for pretty much every operation and function that acts on waves would need to be modified substantially.
If you're using Igor 7, be sure to check out SplitWave, which will make splitting the 2D wave into multiple 1D waves fairly quick and easy. I'd recommend using the /OREF flag so you have wave references to the 1D output waves. Then you can do your analysis on the 1D waves and then use Concatenate to combine the 1D waves back to a 2D wave. Unfortunately Concatenate still doesn't have a mode that takes a wave reference wave as the input, so unless the # of columns you'll be concatenating is fixed, you'll want to use the S_waveNames output of SplitWaves as the input to Concatenate.
April 22, 2017 at 02:33 pm - Permalink
ImageTransform putCol/putRow
is a fast way to update a slice of a wave, instead of using [p] and [q] indices. If you want to update all slicesConcatenate
might be faster, though.April 24, 2017 at 12:27 am - Permalink
Depending on the complexity of the operation, you may be able to write a helper function that takes care of the copying bits. Here's a not-very-polished and possibly slow example that uses a few of the operations previously mentioned in this thread:
wave w_source
variable q
string operation
MatrixOP/O w_slice=col(w_source,q)
operation = "w_slice=w_slice"+operation //Adapt to the application
Execute operation
ImageTransform/G=(q)/D=w_slice putCol w_source
KillWaves w_slice
end
function testSliceOperation()
make/o/n=(10,2) w_source=gnoise(p)
OperateOnSlice(w_source,1,"+100")
end
April 24, 2017 at 09:11 am - Permalink
best,
_sk
April 25, 2017 at 12:35 am - Permalink