# V_maxloc with matrixop Hi. Is there a way to get the location of the maximum using matrixop command? I use "maxval" to get the value, but can't find anywhere in the help a way to get the location of this value inside the wave.

Thanks

Here, try this convoluted thing, which should give you the position of maxval in your input wave:

Function test()
Make/O/D input = {2.17,4.2543,16.4364,27.454,5.46,18.9354,1.324235}

MatrixOp/free maxloc = sum(equal(input,maxval(input))*indexRows(input))

print maxloc
End

... prints 3 in this test case.

Hi Chozo,

Your code only works for a 1D wave. One can find a convoluted way to get this, for sure. It's just surprising to me that the Igor developers did not include a direct way to find the maxloc/minlod with MatrixOP and was wondering if I am missing it in the help. If this lacks, seems quite a major omission on their part.

In my case I have a matrix of (1e6,10) which correspond (data points, states) and need to know the state with the max value, as well as the overall max. My convoluted way of doing this is:

Function test()
Make/O/N=(1e6, 10) DataW = enoise(100)

MatrixOP/O MaxRowW = maxrows(DataW)
MatrixOP/O MaxLocW = (sgn(DataW-colRepeat(maxrows(DataW),10 ))+1) //everything 0, except max, which is now 1+1
MatrixOP/O MaxLocW = maxrows(indexCols(DataW)*MaxLocW/2)

End

I broke it into 3 parts, to be easier to follow. However, this takes a lot of time, and need to do this as part of a fitting procedure, which makes things even more complicated.

Finding the location of an extrema is not a typical matrix operation; it is supported by WaveStats and ImageStats.

In general, the V_ variables are used in operations that produce unambiguous results.  A MatrixOP expression may have arbitrary complexity so the only unambiguous V_ that MatrixOP supports is V_flag which is used to indicate an error.

The case of V_maxRowLoc is a perfect example where the notion of returning a single value is inadequate.  Consider, e.g.,

Make/N=(rows,cols) ddd=sin(pi*x/M)

For some values of the constants this will produce multiple maxima and here the various stats operations have to choose one of these values to report back as the location of a maximum.

[... and for advanced users who consider multithreading such code: if two threads return the same maximum value but obviously different max location, which location do you choose?]

In some applications this approach may be good enough but as a general tool it leaves much to be desired.  A more appropriate approach consists of two steps:

1.  Determine the maximum value.

2.  Identify all the locations in the data that contain that value.

Now leave it to the user to pick any subset of these locations for further analysis.

At this point MatrixOP supports maxVal(w), minVal(w) and equal(a,b) so the example above becomes:

MatrixOP/O aa=equal(w,maxVal(w))

A.G.

Dear A.G.,

I am porting a code from Matlab, which has a function: [M,I] = max(A) returns M - the maximum elements of an array A and I is the linear index into A that corresponds to the maximum value in A. I see your point when multithreading, but I am sure you could overcome the rare case when there is more than one maximum if you decide to incorporate this in Igor 9, for example by picking the one with the lowest indexes.

Based on your suggestion, I optimized a bit the code, which now reads:

Function test()
Make/O/N=(1e6, 10) DataW = enoise(100)
MatrixOP/O MaxRowWs = colRepeat(maxrows(DataW),10)
MatrixOP/O maxCols=maxrows(equal(DataW,MaxRowWs)*indexCols(DataW))
End

I'm not a Matlab user so I looked at online documentation for this function.  I do not see where/if they specify the returned index in the case of multi-valued maxima.

I am not a fan of the way this is implemented in Igor in stats operations/functions.  The difficulty is that we have to keep old code working the same way.  In IP9 WaveStats the multi-threaded execution Igor returns the smallest index for which a min/max are found.

The problem with your code is that indexCols() can return a zero or equal() can return a zero.  Also, I'd be inclined to not use zero in this way; use NaN instead and zap them to leave only valid indices.