comp.lang.idl-pvwave archive
Messages from Usenet group comp.lang.idl-pvwave, compiled by Paulo Penteado

Home » Public Forums » archive » Re: Expensive loops... can they be avoided?
Show: Today's Messages :: Show Polls :: Message Navigator
E-mail to friend 
Switch to threaded view of this topic Create a new topic Submit Reply
Re: Expensive loops... can they be avoided? [message #58891] Tue, 26 February 2008 08:15 Go to next message
Rainer is currently offline  Rainer
Messages: 5
Registered: November 2007
Junior Member
Thank you Allan. The TRIGRID solution works, and is amazingly fast,
but unfortunately not quite what I want.

> not be suitable. You can also save xp, yp and tr between calls if your
> "a" data is changing but everything else is staying the same which will
> also speed things up a bit.

Saving the grid indices in my algorithm (nearestr and nearestchi) into
an array and re-using
them already helps a lot but occasionally they need to be re-
calculated.

> I've only ever used triangulate and friends for display purposes so
> can't claim to be an expert on how accurate "b" will end up - since you
> were just picking the nearest point before I guess you're not overly
> concerned with accuracy.

Also my problem is "only" a displaying issue. The nearest neighbor
search was intended, though. I'm visualizing data from numerical
simulations and the points in "A" lie at the center of grid cells with
the value being representative for the whole cell. An interpolation
would give a wrong impression. If the grid is coarse, it should be
visible.


Thanks again,
Rainer
Re: Expensive loops... can they be avoided? [message #58904 is a reply to message #58891] Tue, 26 February 2008 06:15 Go to previous messageGo to next message
Allan Whiteford is currently offline  Allan Whiteford
Messages: 117
Registered: June 2006
Senior Member
Rainer,

Not using even a remotely similar algorithm (and one which might be
inadequate for your purposes) but how about:

xp=transpose(rebin(r,n_elements(r),n_elements(chi))) * $
rebin(cos(chi),n_elements(chi),n_elements(r))
yp=transpose(rebin(r,n_elements(r),n_elements(chi))) *
rebin(sin(chi),n_elements(chi),n_elements(r)) $
triangulate,xp,yp,tr
b=trigrid(xp,yp,transpose(a),tr,xout=x,yout=y)

this should be faster than your previous solution but, as I said, might
not be suitable. You can also save xp, yp and tr between calls if your
"a" data is changing but everything else is staying the same which will
also speed things up a bit.

Also, this solution might not work. I've only really checked it for
syntax errors not for accuracy or it even being the correct thing to do.
I've only ever used triangulate and friends for display purposes so
can't claim to be an expert on how accurate "b" will end up - since you
were just picking the nearest point before I guess you're not overly
concerned with accuracy.

The "missing" keyword to TRIGRID might handle your environment_value case.

Sorry for not answering your question as such but I hope this helps or
at least points you in a helpful direction.

Thanks,

Allan

Rainer wrote:
> Hi!
>
> I need to render 2D slices cut from 3D spherical grid data. So far, I
> am using a brute force method which, using two FOR loops, is
> unfortunately rather slow (although working just fine). The problem
> and my approach boil down to this:
>
> -- A[i,j] is the input array, with r[i] and chi[j] being curvilinear
> coordinates (not necessarily uniformly spaced)
> -- B[k,l] is the output array with x[l] and y[l] being uniformly
> spaced Cartesian coordinates (to be plotted with TVSCALE)
>
> for k=0,nx-1 do begin
> for l=0,ny-1 do begin
>
> curr = sqrt(x[k]^2+y[l]^2)
> curchi = atan(x[k],y[l])
>
> if "curchi or curr are out of bounds" then begin
> B[k,l] = environment_value
> continue
> endif
>
> foo = min( r - curr ,nearestr,/absolute)
> foo = min( chi - curchi ,nearestchi,/absolute)
>
> B[k,l] = A[nearestr,nearestchi]
>
> endfor
> endfor
>
>
> The calculation of "curr" and "curchi" can easily be done outside the
> loops of course. But what can I do with the rest?
>
>
> Thanks,
> Rainer
Re: Expensive loops... can they be avoided? [message #59023 is a reply to message #58891] Tue, 04 March 2008 14:02 Go to previous message
Spon is currently offline  Spon
Messages: 178
Registered: September 2007
Senior Member
On Feb 26, 4:15 pm, Rainer <ren...@arcor.de> wrote:
> Thank you Allan. The TRIGRID solution works, and is amazingly fast,
> but unfortunately not quite what I want.
>
> Thanks again,
> Rainer

Rainer,

here's my version, I'd be interested to hear if it works. The keys are
to use WHERE in place of the IF statement (predictably), and the
combination of the DIMENSION keyword to MIN with the use of MOD to
bring the subscripts generated back to meaningful values.

Sorry it's been so long in coming, hopefully it'll make up for it by
being that much faster to run! :-)
Let me know how you get on please,

Good luck!
Chris

; --- Start of code ---

NX = N_ELEMENTS(X)
NY = N_ELEMENTS(Y)
NR = N_ELEMENTS(R)
NC = N_ELEMENTS(Chi)

XX = REBIN(X, NX, NY)
YY = TRANSPOSE(REBIN(Y, NY, NX))

RVals = SQRT(XX^2 + YY^2)
RIndex = WHERE(RVals GT RMax, RCount, $
NCOMPLEMENT = RCompCount)

ChiVals = ATAN(XX, YY)
ChiIndex = WHERE(ChiVals GT ChiMax, $
ChiCount, NCOMPLEMENT = ChiCompCount)

; No good data? Get out now!
IF (RCompCount + ChiCompCount) EQ 0 THEN $
RETURN, REPLICATE(Environment_Value, NX, NY)

; Locate bad data:
IF (RCount + ChiCount) NE 0 THEN BEGIN
IF RCount NE 0 THEN BEGIN
IF ChiCount NE 0 THEN BEGIN
BadIndex = [RIndex, ChiIndex]
BadIndex = BadIndex[UNIQ(BadIndex, $
SORT(BadIndex))] ; If bad R and Chi
ENDIF ELSE BadIndex = RIndex ; If only bad R
ENDIF ELSE BadIndex = ChiIndex ; If only bad Chi
ENDIF

RVals = REBIN(RVals, NX, NY, NR, /SAMPLE)
RVals = TRANSPOSE(RVals, [2, 0, 1])

ChiVals = REBIN(ChiVals, NX, NY, NC, /SAMPLE)
ChiVals = TRANSPOSE(ChiVals, [2, 0, 1])

RR = REBIN(R, NR, NX, NY, /SAMPLE)
CC = REBIN(Chi, NC, NX, NY, /SAMPLE)

RDiff = RVals - RR
RFoo = MIN(RDiff, LeastR, /ABSOLUTE, $
DIMENSION = 1) ; Calculate R subscripts.
LeastR = LeastR MOD NR ; Bring subscripts back
; to 0:(nr)-1 range.

CDiff = ChiVals - CC
ChiFoo = MIN(CDiff, LeastChi, /ABS, DIM = 1)
LeastChi = LeastChi MOD NC

; Define B array:
B = A[LeastR, LeastChi]

; Replace any out-of-bound subscripts:
IF N_ELEMENTS(BadIndex) NE 0 THEN $
B[BadIndex] = Environment_Value

; --- End of code ---
  Switch to threaded view of this topic Create a new topic Submit Reply
Previous Topic: Re: Convenient IGRF in IDL
Next Topic: Re: using the WHERE function on a portion of an array

-=] Back to Top [=-
[ Syndicate this forum (XML) ] [ RSS ] [ PDF ]

Current Time: Wed Oct 08 20:04:15 PDT 2025

Total time taken to generate the page: 0.00656 seconds