how to reverse values of every other column in a big matrix wave ?

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.

reversing everyother column values ,

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

Here is a less-quick solution:

Macro ReverseOddColumns()

    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

 

In reply to 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

Here is a more-quick solution:

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

 

 

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:

Total time: 3.31003, Time in Function code: 3.31003 (100%)
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

Total time: 1.63765, Time in Function code: 1.63765 (100%)
Top function percentages:
Function Procedure RevOddCols: 99%

Annotated Top Functions:
(Bars normalized to largest hit count)

*******************************************************************************************
Function: Procedure RevOddCols; Percent total 99%
*******************************************************************************************
[00]          	|function RevOddCols(inwave)	//	creates 'wrev'
[00]          	|	wave inwave
[04]*         	|	MatrixOP/O widx = indexCols(inwave)
[95]**********	|	MatrixOP/O wrev = inwave*equal(mod(widx,2),0) + reverseCols(inwave*mod(widx,2)) 
[00]          	|end	

 

In reply to by s.r.chinn

s.r.chinn wrote:

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:

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.

This would be my approach. I used redimension to separate odd and even columns. I didn't check the speed.

Function Test()

    //  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

 

Function TimeME()

    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

•timeme()
  elaspsed 0.427753, crc 4151104622
  elaspsed 0.19668, crc 4151104622
  elaspsed 0.12099, crc 4151104622

 

So it basically depends how many cores which solution is the best. Here I'm having 12.

In reply to by olelytken

olelytken wrote:

This would be my approach. I used redimension to separate odd and even columns. I didn't check the speed.

Function Test()

    //  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

 

A quick test on my 10-year-old computer gives 0.00014 seconds

Just to close the loop with Adam's suggesting using MultiThread (in my 4-core cpu), 1000 iterations (divide times  by 1000)

Total time: 0.996815, Time in Function code: 0.996815 (100%)
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

Total time: 0.997383, Time in Function code: 0.997383 (100%)
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.)

Forum

Support

Gallery

Igor Pro 9

Learn More

Igor XOP Toolkit

Learn More

Igor NIDAQ Tools MX

Learn More