MathGroup Archive 2011

[Date Index] [Thread Index] [Author Index]

Search the Archive

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

  • To: mathgroup at smc.vnet.net
  • Subject: [mg115296] Re: Using Extract where some indices are out of bounds (efficiently)
  • From: Ray Koopman <koopman at sfu.ca>
  • Date: Fri, 7 Jan 2011 04:07:15 -0500 (EST)
  • References: <iev2kf$4mq$1@smc.vnet.net> <ifup7d$cog$1@smc.vnet.net> <ig3pco$ja9$1@smc.vnet.net>

On Jan 5, 11:01 pm, Ray Koopman <koop... at sfu.ca> wrote:
> 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]] ]]]

To remove the restriction on myExtract2 to two-dimensional square
arrays, just change Length@array to Dimensions@array. This will make
it as general as myExtract, without slowing it for two-dimensional
square arrays.


  • Prev by Date: Re: How to change the directory for the docs?
  • Next by Date: Re: check if a square matrix is diagonal
  • 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)