Re: Using Extract where some indices are out of bounds (efficiently)

• To: mathgroup at smc.vnet.net
• Subject: [mg115263] Re: Using Extract where some indices are out of bounds (efficiently)
• From: Ray Koopman <koopman at sfu.ca>
• Date: Thu, 6 Jan 2011 02:01:49 -0500 (EST)
• References: <iev2kf\$4mq\$1@smc.vnet.net> <ifup7d\$cog\$1@smc.vnet.net>

```On Jan 4, 1:28 am, Ray Koopman <koop... at sfu.ca> wrote:
> On Dec 23 2010, 12:52 am, Julian Francis <julian.w.fran... at gmail.com>
> wrote:
>> Dear all,
>>
>> How can I arrange to use Extract to extract values from an array; but
>> where some of the indices may be out of bounds, in which case they
>> should be simply ignored?
>>
>> I wrote a simple arrayInBounds function, and then did a Select on that
>> to retrieve only the indices which are in bounds, which are then fed
>> into Extract. Whilst this works it seems to lead to a 150* reduction
>> in speed.
>>
>> FYI:
>> My arrayInBounds function looks like this:
>>
>> arrayInBounds[array_, index_] :=
>>  If[index == {}, True,
>>   First[index] > 0 && First[index] < Length[array] &&
>>    arrayInBounds[array[[1]], Rest[index]]]
>>
>> My support functions for the test are:
>>
>> disks = Table[
>>    Transpose[Position[DiskMatrix[r, 2*(r + 1) + 1], 1]], {r, 1, 30}];
>>
>> positions[x_, y_, r_] := Transpose[{
>>    disks[[r, 1]] + y - (r + 2),
>>    disks[[r, 2]] + x - (r + 2)}]
>>
>> My timing tests are:
>>
>> In[291]:= Timing[lists=Table[Extract[image,Select[positions[x,y,
>> 10],arrayInBounds[image,#]&]],
>> {y,11,64-11},
>> {x,11,64-11}];]
>> Out[291]= {17.175,Null}
>> In[292]:= Timing[lists2=Table[Extract[image,positions[x,y,10]],
>> {y,11,64-11},
>> {x,11,64-11}];]
>> Out[292]= {0.094,Null}
>> In[293]:= lists==lists2
>> Out[293]= True
>>
>> image is assumed to be an array of at least 64*64.
>>
>> In this particular case, the bounds are setup so that the checking
>> serves no purpose and can be eliminated, but I've only done this to
>> show the speed comparison with the no bounds checking comparison. The
>> speed difference is a factor of over 150! This seems surprising to me.
>> Is there a better way?
>>
>> I don't think I can reformulate it using partitions, or the standard
>> imagefilter functions, because in general the functions positions will
>> be giving a complicated list of coordinates which doesn't naturally
>> fit into a square kernel.
>>
>> Any help greatly appreciated.
>>
>> Thanks,
>> Julian.
>
> Is this the sort of thing you're looking for?
>
> myExtract[array_,indices_] := With[{m = Dimensions@array}, Extract[
>   array, Select[indices, And@@Positive@# && And@@Thread[# <= m]&]]]
>
> a = Array[FromDigits@{##}&,{2,3,4}]
>
> {{{111,112,113,114},{121,122,123,124},{131,132,133,134}},
>  {{211,212,213,214},{221,222,223,224},{231,232,233,234}}}
>
> myExtract[a,{{0,1,2},{1,2,3},{2,3,4},{3,4,5}}]
>
> {123,234}
>
> myExtract[a[[2,2]],Transpose@{Range[0,5]}]
>
> {221,222,223,224}

If the array from which you are extracting elements is two-dimensional
and square then this will be much faster than my previous suggestion:

myExtract2[array_,indices_] := With[{m = Length@array},
Extract[array, Part[indices,
SparseArray[Times@@UnitStep[(#-1)*(m-#)&@Transpose@indices]] /.
SparseArray[_,_,_,d_] :> Flatten@d[[2,2]] ]]]

```

• Prev by Date: Re: Aborting execution on first message
• Next by Date: Re: Session Privacy in Mathematica 8 w/ Wolfram|Alpha free-form input?
• Previous by thread: Re: Using Extract where some indices are out of bounds (efficiently)
• Next by thread: Re: Using Extract where some indices are out of bounds (efficiently)