On =: in scripts:  When I replace =. with =: for debugging purposes, I always precede it with 2 spaces:

name   =: value

Then after testing a global replace of '  =:' with '=.' removes the global assignments.

Henry Rich

On 4/18/2018 6:16 PM, Marshall Lochbaum wrote:
This is a perfectly good use of the forums in my book. At the very
least, we've had similar posts before and no one's complained.

Overall your program looks pretty good to me. It's not leveraging the
Full Power of J™, but it's a great start. You know what I. does!

There are some ways to use arrays to do more of your work for you. You
write

         'minCut maxCut' =. x
         ...
         minWanted =: (<.minCut*#srtData){srtData
         maxWanted =: (<.maxCut*#srtData){srtData

but this is the same as

         'minWanted maxWanted' =: (<.x*#srtData){srtData

since each of * <. and { has rank zero, that is, maps over arrays, on
the side of x. (Unrelatedly, these should probably use =. rather than =:
to avoid global assignment. It looks like they might have been =: for
debugging, but if so, it's good practice to look over the code again and
change them back when you're done.)

A more sophisticated example is the plane-scaling code in displayFits.
You use different code for each different number of scalings to do:

         r =.  minmax scaleT2D 0{imarray
         select. 3<.{.$imarray   NB. use up to 3 planes
           case. 3 do.
                 g =. minmax scaleT2D 1{imarray
                 b =. minmax scaleT2D 2{imarray
           case. 2 do.
                 b =. minmax scaleT2D 1{imarray
                 g =. -: r+b   NB. average of red and blue
           case. 1 do.
                 'g b'=. r;r
         end.

Instead, you could do all the scalings in one go:
((#imarray) is like ({.$imarray), but it is a scalar and not a vector.)

         numScales =. 3<.#imarray   NB. use up to 3 planes
         scaled =. minmax scaleT2D"_ _1 numScales {. imarray
         if. numScales < 3 do.
                 avg =. (+/ % #) scaled
                 scaled =. scaled , (3-numScales)#,:avg
         end.
         'r g b' =. scaled

This example first uses scaleT2D with an explicit rank to operate on
each of the first numScales planes. If you're not familiar with it, my
favorite explanation of the rank conjunction (") is
http://www.jsoftware.com/help/jforc/loopless_code_i_verbs_have_r.htm.
A rank of (_ _1), that is, infinity on the left and minus one on the
right, means to apply the function to the entire left argument and each
subarray of the right argument, effectively mapping over only the right
argument. I could have used a rank of 2 rather than _1 on the right, but
rank _1 is more flexible--it would work even if the planes were instead
three-dimensional.

After this compuation, scaled is a three-dimensional array of the first
numScales planes of imarray. The average of its planes can be found with
the standard averaging function (+/ % #), which happens to be the
canonical example of a fork. If you're interested, these are described
at http://code.jsoftware.com/wiki/Vocabulary/fork.

An exponent like (2^8) unfortunately always evaluates to a
floating-point number. I habitually use (<.@^) when I know the arguments
are integers to avoid accidentally promoting to floats.


I actually gave a talk on a task similar to the parsing you do here. My
task was to parse the header of a simple wave file. A script version
(there's no recording that I'm aware of) is at
http://code.jsoftware.com/wiki/Community/Conference2014/Talks/UsingDataAsCode
and the current script that I use based on this is
https://github.com/mlochbaum/JSound/blob/master/wav.ijs.
This is certainly difficult material for a beginning J programmer, but
the techniques discussed in the talk might be useful for you as you gain
more skill.

One neat trick similar to the one used there: rather than write

         bitpix =. hdata getHdrVal 'BITPIX'
         naxis  =. hdata getHdrVal 'NAXIS'
         naxis1 =. hdata getHdrVal 'NAXIS1'
         naxis2 =. hdata getHdrVal 'NAXIS2'
         naxis3 =. hdata getHdrVal 'NAXIS3'

you might use

         fields =. ;: 'BITPIX NAXIS NAXIS1 NAXIS2 NAXIS3'
         (fields) =. hdata&getHdrVal&.> fields

and then the fields will be defined in variables BITPIX, etc.

Another very cool trick that I found after the talk would be useful
here:

         select. bitpix
           case. _32 do. adata =. (naxis3,naxis2,naxis1)$ |. _1 fc |. rdata
           case. _64 do. adata =. (naxis3,naxis2,naxis1)$ |. _2 fc |. rdata
           case. 16  do. adata =. (naxis3,naxis2,naxis1)$ |. _1 ic |. rdata
           case. 32  do. adata =. (naxis3,naxis2,naxis1)$ |. _2 ic |. rdata
         end.

The idea is to make an adverb (mine is audioconvert in wav.ijs) which
takes a format specification like bitpix and returns a conversion
function. Something like:

rawconvert =: 1 : 0
         select. u
           case. _32 do. _1&fc
           case. _64 do. _2&fc
           case. 16  do. _1&ic
           case. 32  do. _2&ic
           case. do. 'Invalid format' assert 0
         end.
)

which can then be called with

         cvt =. bitpix rawconvert  NB. A conversion function
         adata =. (naxis3,naxis2,naxis1)$ |. cvt |. rdata

Now the really cool thing is that J knows how to invert each of these
functions. So when you want to store the data again, you just use
(cvt^:_1)! This is a J-only technique: I don't know of any other
language that has the functional capabilities and the automatic
inversion required to do it.

There's always more to say but I think that's enough for one email. Good
luck with your future J projects!

Marshall

On Wed, Apr 18, 2018 at 02:47:02PM -0400, Thomas Hickey wrote:
  As one of my first J programs, I've written a minimal viewer for FITS
files, the standard way of sharing astronomical data, especially images.

I'd appreciate it if someone could take a look at it and let me know how
the code (80 lines of J) looks.  I know I've replaced some really awkward
code in it, so I imagine there are better ways of doing lots of things.

The code is on GitHub at  https://github.com/ThomasBHickey/JFits, along
with a sample FITS file in the fitsSample folder.  Pointers on organizing J
code on GitHub would be appreciated as well.

Or is there a better way to accomplish this than the programming forum?  I
know this is longer than most of the questions that are posted here, but I
think it is an interesting application of J.

--Th
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm


---
This email has been checked for viruses by AVG.
http://www.avg.com

----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to