Dependecy and data folders

Hello,

I've written a procedure to calculate a center of mass and wanted to implement a variable dependency and a folder creation in the procedure.
I would like to be able to change the variable offset (without having to alter the procedure itself), in the command window or in the button in the graph, and for each time I do it a new folder would be created.
I would apreciate very much if my mistakes could be pointed out in my code below
Thanks in advance,
Gabriel

 <br />
#pragma rtGlobals=1     // Use modern global access method.<br />
<br />
Function COM(w)<br />
<br />
Wave w<br />
<br />
Variable pw = 1 <br />
Variable/G offset = 100<br />
Variable i, j, k<br />
String dfName<br />
sprintf dfName, "offset%d", offset<br />
<br />
NewDataFolder/O/S $dfName<br />
<br />
MAKE /N=(512,41,61) vc<br />
Wave vc<br />
<br />
MAKE /N=(41,61) Tintensity<br />
Wave Tintensity<br />
<br />
<br />
MAKE /N=(41,61) rowXintensityXpw<br />
Wave rowXintensityXpw<br />
<br />
<br />
MAKE /N=(41,61) CM<br />
Wave CM<br />
<br />
<br />
vc = w - offset //SetFormula vc, "w - offset"   => Can't get this dependency to work<br />
<br />
    for (k=0; k < 61; k += 1)<br />
        for (j=0; j < 41; j += 1)<br />
            for (i=0; i < 512; i += 1)<br />
                Tintensity[j][k] += vc[i][j][k]<br />
                rowXintensityXpw[j][k] += (i+1)*vc[i][j][k]*pw<br />
            endfor<br />
        endfor<br />
    endfor<br />
    <br />
CM = (rowXintensityXpw)/(Tintensity)<br />
<br />
Duplicate CM, CM2<br />
Duplicate Tintensity, TI<br />
<br />
Redimension/N=2501 CM2<br />
Redimension/N=2501 TI<br />
<br />
Display CM2 vs TI<br />
ControlBar 23<br />
SetVariable offset,size={120, 20}, value=offset<br />
SetVariable offset, proc=COM // Set procedure to run when value is changed<br />
SetDataFolder ::<br />
<br />
end<br />
<br />
</span>
Since I received this question at WaveMetrics support, I'll send you an answer directly.
I would just like to point out that usinga triple nested loop is really inefficient for calculating a centre of mass.
andyfaff wrote:
I would just like to point out that usinga triple nested loop is really inefficient for calculating a centre of mass.

Thank you for pointing that out, I'd apreciate if you told me how can I do it better.
gzvitiello wrote:
andyfaff wrote:
I would just like to point out that usinga triple nested loop is really inefficient for calculating a centre of mass.

Thank you for pointing that out, I'd apreciate if you told me how can I do it better.

Which Howard did in his direct response from WM support.

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
Quote:
Which Howard did in his direct response from WM support.


Not really. I pointed out that this:

Variable i, j, k
for (k=0; k < 61; k += 1)
    for (j=0; j < 41; j += 1)
        for (i=0; i < 512; i += 1)
            vc[i][j][k] = w[i][j][k] - offset
        endfor
    endfor
endfor


can be written as this:

vc = w - offset


That still leaves a triple-nested loop. I don't know how to simplify that. Perhaps someone else does.

My advice on the structure of the function, which I will send directly, is to avoid the use of dependencies, and to separate calculation from graphics and user-interface.
hrodstein wrote:
Since I received this question at WaveMetrics support, I'll send you an answer directly.


johnweeks wrote:
Which Howard did in his direct response from WM support.


So how about adding the solutions here for the benefit of everyone else? Others could be interested as well.
741 wrote:
So how about adding the solutions here for the benefit of everyone else? Others could be interested as well.


They're in my post above. I beat your post by 1 minute :)
This code assumes all your pixels have equal weighting. It's not simpler than the triple loop, but I'm thinking it should be faster. Of course, I could've opened my mouth too early.

Function test()
    make/n=(100,100, 100)/free w
    w = gauss(x, 10, 3, y, 20, 3, z, 30, 3)
    wave temp = com3D(w)
    print temp
End
 
Function/wave com3D(w)
    Wave w
    variable ii, t1, t2, t3
    make/n=(wavedims(w))/free/d COM
    switch(wavedims(w))
        case 1:
            COM[0] = Pla_peakcentroid(w)
            break
        case 2:
            imagetransform sumallrows w
            COM[0] = Pla_peakcentroid(W_sumrows)
            imagetransform sumallcols w
            COM[1] = Pla_peakcentroid(W_sumcols)
            break
        case 3:
            imagetransform sumplanes w
            Wave temp = com3D(M_SumPlanes)
            COM[0] = temp[0]
            COM[1] = temp[1]
            imagetransform/g = 2 transposeVol w
            imagetransform sumplanes M_volumetranspose
                        imagetransform sumallrows M_sumplanes
            COM[2] = Pla_peakcentroid(W_sumrows)
            break
        default:
            break
    endswitch
    return COM
End
 
Threadsafe Function Pla_peakCentroid(ywave)
    Wave ywave
    variable retval
 
    duplicate/free ywave, W_integrate
    W_integrate = 0
 
    multithread W_integrate[] = Area(tempy, 0, p)
 
    W_integrate /= W_integrate[numpnts(W_tempy)-1]
    variable centroid = binarysearchinterp(W_integrate,0.5)
    if(numtype(centroid))
        retval = NaN
    else
        retval = centroid
    endif
 
    return retval
End