On 8/27/2010 2:49 PM, P Kishor wrote:
> On Fri, Aug 27, 2010 at 3:08 PM, Derek Lamb<[email protected]> wrote:
>
>> On Fri, 2010-08-27 at 14:35 -0500, P Kishor wrote:
>>
>>> I am enjoying all the fine tools that the masters have created. Like
>>> magic, with one command, I can apply the same function to millions of
>>> values.
>>>
>>> Now, I am itching to hit my head against the wall. I want to write my
>>> own function that can be applied to all the values in a piddle. So,
>>> following the convention, I envision
>>>
>>> $pdl->func to apply to the elements in the entire piddle and
>>> $pdl->function to apply to all the elements in the specified
>>> dimension. These are not necessarily grouping functions that result in
>>> an (n-1) D piddle, but they are more like sqrt that applies to every
>>> element.
>>>
>>> Where do I begin? Do I have write this in C? Or can I write a function
>>> in Perl and PDL-ify it?
>>>
>>>
>> Hi Puneet,
>>
>> If you want to do $pdl->func, you just need to write a sub func{}, and
>> then export that into the PDL namespace. So, yes, you can do it in
>> perl/PDL. To see how to do this, look in the PDL source for some
>> function that you already do it with. For example, I use $pdl->wfits to
>> write a FITS file, and in FITS.pm there's a line
>>
>> *wfits = \&PDL::wfits;
>> and then
>> sub PDL::wfits { #code}
>>
>> I think you can also do it the other way:
>> *PDL::func = \&func;
>> sub func { #code}
>>
>>
> When you say "the other way" above, I am guessing you mean without
> having to write my own PDL::MyModule, correct? The "other way" would
> be to just do it my own program, no?
>
>
I guess that's the distinction. You'll find it both ways in the PDL
source tree. You probably want the latter version, though.
>> I think you should think more about your desire for $pdl->function, and
>> what it will do for you. If you're not grouping or reducing
>> dimensionality, could the same thing be accomplished with
>> $pdl->slice(#something)->func ? Saves you from having to write two subs.
>> "to apply to all elements in the specified dimension" doesn't really
>> make any sense--can you show us what you mean with an example like
>> sequence(3,4)? For example, what if func() was just a shortcut for
>> squaring each element, what would function do?
>>
>>
>>
> Your explanation and questions above are brilliant. They made me think
> through my problem. Many thanks. Here goes --
>
> sub add3 { return $_[0] * 3; }
>
> $a = sequence 3, 4;
> print $a;
> [
> [ 0 1 2]
> [ 3 4 5]
> [ 6 7 8]
> [ 9 10 11]
> ]
>
> print add3( $a->at(1, 2);
> 21
>
> print add3( $a)
> [
> [ 0 3 6]
> [ 9 12 15]
> [18 21 24]
> [27 30 33]
> ]
>
> print add3($a->slice(':,2'))
>
> [
> [18 21 24]
> ]
>
> A style note -- how do I make chaining possible? I would like
> $a->at(1, 2)->add3 or $a->add3, which, currently gives me "Can't
> locate object method "add3" via package 'PDL'". I guess I have to
> "export it into the PDL namespace" as you state above. I will look at
> the source of FITS.pm and see if I can copy that.
>
well, first you need to make sure that whatever your chaining returns a
piddle, and not a perl scalar. The '->' only works on piddles. So
basically that means never using 'at'. Then if you have
sub PDL::add3 {#stuff}
then you could do $a->add3->some_other_func, because add3 is now in the
PDL namespace.
> However, I might want to do a grouping function, such as the avg and
> sum functions, which create an (N-1) D piddle.
>
As an example, I believe the way avg and average are implemented is that
$pdl->avg is synonymous with $pdl->clump(-1)->average, so really all the
work is in the dimension-reducing function average.
> Actually, here are a few concrete things that I want to do.
>
> 1. Create a frequency distribution of my piddle values. So, given
>
> print $a
> [
> [ 67.099513 41.056771 58.605799]
> [ 36.449405 17.962021 42.484533]
> [ 57.186859 6.542282 6.1037422]
> [ 58.814063 58.77334 12.803835]
> ]
>
> and a range, say, 0 .. 99, and a class interval of 10 like so
> 0: 0-19
> 1: 20-39
> 2: 40-59
> 3: 60-79
> 4: 80-99
>
> I want
>
> print $a->myRangeFunc(range => [0, 99], interval => 20)
> [
> [ 3 2 2]
> [ 1 0 2]
> [ 2 0 0]
> [ 2 2 0]
> ]
>
floor($a/20) ?
> and
>
> print $a->myFreqDistrib(range => [0, 99], interval => 20)
> [4 1 6 1 0]
>
>
hist(floor($a/20),0,100/20,1) ?
> and so on...
>
>
> --
> Puneet Kishor
>
Derek
_______________________________________________
Perldl mailing list
[email protected]
http://mailman.jach.hawaii.edu/mailman/listinfo/perldl