how to reverse values of every other column in a big matrix wave ?
Amo
Hello forum,
I want to reverse values of every other column in waveA, a matrix with 298 columns and 200 rows. Something like in attached image
I know for a single wave, I can use reverse command or use sort /R, but for 298x200 matrix and doing it manually for each column takes forever. So I was wondering if there is an easy way to solve this problem?
Thank you for your help.
Forum
Support
Gallery
Igor Pro 9
Learn More
Igor XOP Toolkit
Learn More
Igor NIDAQ Tools MX
Learn More
Here is a quick solution based on 200 rows, i.e. p goes from 0 to 199.
Duplicate oldwave, newwave
NewWave = mod(q,2)? oldwave[199-p][q] : oldwave[p][q]
Logic: checks to see if column is odd, modulus=1. and then reverses the row assignment. If even, modulus = 0, then just copies.
Andy
April 22, 2019 at 04:32 pm - Permalink
Here is a less-quick solution:
String tables= WinList("*",";","WIN:2")
String tableName= StringFromList(0,tables) // top table
if( strlen(tableName) == 0 )
DoAlert 0, "Expected table window"
return
endif
String tblwaves= WaveList("*", ";", "MINCOLS:2,WIN:"+tableName)
String twoDWave= StringFromList(0,tblwaves)
if( strlen(tableName) == 0 )
DoAlert 0, "Expected two-dimensional wave in table"
return
endif
ReverseColumns($twoDWave, 1, 2)
End
Function ReverseColumns(w, firstColToReverse, skipToNextCol)
Wave w
Variable firstColToReverse // 0 is the first column
Variable skipToNextCol // 1 to reverse all columns starting from the first, 2 to do every other one, etc.
// Note: no input checking
Variable ncols = DimSize(w,1)
Variable nrows= DimSize(w,0)
Variable wtype = WaveType(w) // 0 if text
Make/O/N=(nrows)/Y=(wtype)/FREE columnCopy
Variable col
for(col=firstColToReverse; col<ncols; col+=skipToNextCol)
columnCopy= w[p][col]
Reverse columnCopy
w[][col] = columnCopy[p]
endfor
End
April 22, 2019 at 04:46 pm - Permalink
In reply to Here is a quick solution… by hegedus
this is cool thanks, what does "?" mark in command mean?
April 23, 2019 at 10:10 am - Permalink
In reply to Here is a less-quick… by JimProuty
Really cool , thanks a lot
April 23, 2019 at 10:10 am - Permalink
In reply to this is cool thanks, what… by Amo
From manual
? :
? : is the conditional operator, which is a shorthand form of an if-else-endif statement. It is of the form:
<expression> ? <TRUE> : <FALSE>
When expression is nonzero, it evaluates the TRUE part, otherwise it evaluates the FALSE part. The ":" character in the conditional operator must always be separated with spaces from the two adjacent operands. The operands must be numeric; for strings, you must use the SelectString function.
See Operators for a list of all operators in order of precedence.
Examples
Replace zero values with blanks:
Wave w = wave0
w = w[p]==0 ? NaN : w[p]
Andy
April 23, 2019 at 10:20 am - Permalink
Here is a more-quick solution:
wave inwave
MatrixOP/O widx = indexCols(inwave)
MatrixOP/O wrev = inwave*equal(mod(widx,2),0) + reverseCols(inwave*mod(widx,2))
end
April 25, 2019 at 05:02 am - Permalink
Wow, Steve- you're getting to be almost as creative with MatrixOP as AG is!
April 25, 2019 at 09:17 am - Permalink
Thanks, John. I am but Grasshopper at the feet of the Master :)
Sometimes the effort of Parsing MatrixOP pays off. For the (200 row, 298 col) case cited above, the point-index method gives Profiling result for 1000 iterations:
Top function percentages:
Function Procedure RevOddColsP: 100%
Annotated Top Functions:
(Bars normalized to largest hit count)
*******************************************************************************************
Function: Procedure RevOddColsP; Percent total 100%
*******************************************************************************************
[00] |function RevOddColsP(inwave)
[00] | wave inwave
[00] |
[00] | variable nrows = dimsize(inwave,0)
[01]* | Duplicate/O inwave, newwave
[99]********** | newWave = mod(q,2)? inwave[nrows-1-p][q] : inwave[p][q]
[00] |end
and identically-looped MatrixOP method gives
April 25, 2019 at 10:06 am - Permalink
In reply to Thanks, John. I am but… by s.r.chinn
Try adding the MultiThread keyword in front of the wave assignment statement in RevOddColsP. Depending on your processor, you might find that to be faster than the MatrixOP version. I did, with a 4 core/8 thread processor.
April 25, 2019 at 11:24 am - Permalink
This would be my approach. I used redimension to separate odd and even columns. I didn't check the speed.
// Creates a dummy wave
Variable NumRows=200
Variable NumCols=298
Make/O/N=(NumRows, NumCols) root:WaveA/WAVE=WaveA
WaveA[][]=p
// Adds every second column to the bottom of the previous column
Redimension/N=(NumRows*NumCols) WaveA
Redimension/N=(NumRows*2, NumCols/2) WaveA
// Makes a copy of the bottom half of the wave corresponding to the odd columns
Duplicate/O/R=[NumRows, *][] WaveA, root:OddColumns/WAVE=OddColumns
// Reverses the odd columns
Reverse /DIM=0 OddColumns
// Adds the odd columns back into the wave
ImageTransform /INSI=OddColumns /INSX=(NumRows) /INSY=0 insertImage WaveA
// Restores the original number of columns and rows
Redimension/N=(NumRows*NumCols) WaveA
Redimension/N=(NumRows, NumCols) WaveA
// Looks at the result
Edit WaveA
end
April 25, 2019 at 12:16 pm - Permalink
variable now, i, numRuns = 100
Make/FREE/R/N=(200,298) data
data = p + q
now = stopmstimer(-2)
for(i = 0; i < numRuns; i += 1)
ReverseColumns(data, 1, 2)
endfor
printf "elaspsed %g, crc %d\r", (stopmstimer(-2) - now) / 1e6, wavecrc(0, data)
data = p + q
now = stopmstimer(-2)
for(i = 0; i < numRuns; i += 1)
RevOddCols(data)
endfor
printf "elaspsed %g, crc %d\r", (stopmstimer(-2) - now) / 1e6, wavecrc(0, data)
data = p + q
now = stopmstimer(-2)
for(i = 0; i < numRuns; i += 1)
ReverseColumnsNew(data)
endfor
printf "elaspsed %g, crc %d\r", (stopmstimer(-2) - now) / 1e6, wavecrc(0, data)
End
Function ReverseColumnsNew(wv)
WAVE wv
MAKe/N=0/FREE dest
Reverse/DIM=1 wv/D=dest
multithread dest[][] = mod(q, 2) == 0 ? wv[p][q] : dest[p][q]
End
Function ReverseColumns(w, firstColToReverse, skipToNextCol)
Wave w
Variable firstColToReverse // 0 is the first column
Variable skipToNextCol // 1 to reverse all columns starting from the first, 2 to do every other one, etc.
// Note: no input checking
Variable ncols = DimSize(w,1)
Variable nrows= DimSize(w,0)
Variable wtype = WaveType(w) // 0 if text
Make/FREE/N=(nrows)/Y=(wtype)/FREE columnCopy
Variable col
for(col=firstColToReverse; col<ncols; col+=skipToNextCol)
columnCopy= w[p][col]
Reverse columnCopy
multithread/NT=4 w[][col] = columnCopy[p]
endfor
End
function RevOddCols(inwave) // creates 'wrev'
wave inwave
MatrixOP/O widx = indexCols(inwave)
MatrixOP/O wrev = inwave*equal(mod(widx,2),0) + reverseCols(inwave*mod(widx,2))
end
gives
So it basically depends how many cores which solution is the best. Here I'm having 12.
April 25, 2019 at 02:25 pm - Permalink
In reply to This would be my approach. I… by olelytken
A quick test on my 10-year-old computer gives 0.00014 seconds
April 25, 2019 at 11:29 pm - Permalink
Just to close the loop with Adam's suggesting using MultiThread (in my 4-core cpu), 1000 iterations (divide times by 1000)
Top function percentages:
Function Procedure RevOddColsP: 100%
Annotated Top Functions:
(Bars normalized to largest hit count)
*******************************************************************************************
Function: Procedure RevOddColsP; Percent total 100%
*******************************************************************************************
[00] |ThreadSafe function RevOddColsP(inwave)
[00] | wave inwave
[00] |
[00] | variable nrows = dimsize(inwave,0)
[05]* | Duplicate/O inwave, newwave
[95]********** | MultiThread newWave = mod(q,2)? inwave[nrows-1-p][q] : inwave[p][q]
[00] |end
and with a more efficient MatrixOp modification
Top function percentages:
Function Procedure RevOddCols: 100%
Annotated Top Functions:
(Bars normalized to largest hit count)
*******************************************************************************************
Function: Procedure RevOddCols; Percent total 100%
*******************************************************************************************
[00] |function RevOddCols(inwave) // creates 'wrev'
[00] | wave inwave
[52]********** | MatrixOP/O widx = mod(indexCols(inwave),2)
[48]********* | MatrixOP/O wrev = inwave*equal(widx,0) + reverseCols(inwave*widx)
[00] |end
Your mileage may vary (with number of cores, matrix dimensions, etc.)
April 30, 2019 at 03:21 am - Permalink