From J Wiki
Jump to: navigation, search

trees in APL and J, placing text on a plot, evening out plot of a function, Excel add-ins in J, graphics capability


             Meeting Agenda for NYC JUG 20080108

1. Beginner's regatta: tacit for beginners - considered harmful versus
explicit adverb notation?

2. Show-and-tell: a suggestion for a tree class (from parseDir.ijs).

Placing text on a plot.

Evening output of a function.

3. Advanced topics: How best to do Excel add-ins?  Make a kit for this? See SampleSpreadsheetAddins.doc.

4. Learning and teaching J: perception of J graphics capability.

Beginner's Regatta

Tacit considered harmful? Some of us find explicit notation more natural and easier to comprehend than tacit notation. Tacit does offer advantages in efficiency of execution and avoids a certain amount of repetition in writing expressions as well.

Show and Tell


Placing Text on a Plot

In response to a question about how to place text on a plot next to chosen points, I came up with the following; the e-mail inquiry that prompted this, and my replies, are included with the code as nouns (using 0 : 0 ).

Intro=: 0 : 0
from     June Kim <>  4/9/06
reply-to Programming forum <>	
to	 Programming forum <>	
date	 Apr 9, 2006 4:25 AM	
subject	 [Jprogramming] labeling on points in plot	


Say, I have a simple plot:

  load 'plot'
  plot 0 1 2 3;1 2 3 5

I'd like to label on some data points. For example, the second data
point (1,2) should be labeled as "foo" on the plot view, and the third
point (2,3) as "bar" on the view. (It would be better if the data
point is marked, too)

Is there a convenient and easy way of doing this in general cases?


MySecondReply=: 0 : 0
from     Devon McCormick <>  1:11 pm (8 minutes ago)
to	 Programming forum <>	
date	 Dec 26, 2007 1:11 PM	
subject	 Re: [Jprogramming] Re: labeling on points in plot	

I realized my code was insufficiently general because it labels only the highest and lowest points, so here's an example of labelling a randomly-chosen point.  The magic values of "1000" are based on my understanding that the virtual size of the plot area is 1000x1000 "characters".

lblRnd=: 3 : 0
   pd 'reset'
   rr=. _100+20?201           NB. Random points to plot
   whrp=. ?#rr                NB. Location of a point at random.
   rp=. whrp{rr               NB. Value of the random point

   xrnd=. ":<.0.5+1000*(#rr)%~whrp      NB. Estimate x-position of random pt.
   span=. (>./-<./)rr
   yrnd=. ":<.0.5+1000*(rp-<./rr)%span  NB. Estimate y-position of random pt.

NB. Place text for random point:
   pd 'textfont Courier 12 Bold;textcolor BLACK'
   pd 'text ',xrnd,' ',yrnd,' Val=',":rp

   pd 'pensize 5;type point'
   pd <"1 rr,:~i.#rr
   pd 'show'

NB.EG pts=. 1 o. 8%~i:49

labelPoints=: 3 : 0
   pd 'reset'
   'rpts p2l'=. y   NB. Vector of points to plot, indexes of points to label.
   wh=. (<rpts) label1Pt&.>p2l
   pd 'pensize 5;type point'
   pd <"1 rpts,:~i.#rpts
   pd 'show'
NB.EG labelPoints (1 o. 8%~i:49);0 11 36 62 87 98  NB. Label extrema

LP=: 20 900 50 1400 10
NB.* label1Pt: allow parameter refinement to label points: use global LP:
NB. x offset, scaling, y offset, scaling, font point size.
label1Pt=: 4 : 0
   'whrp rpts'=. y;<x
   rp=. whrp{rpts
   xrnd=. ":<.(0{LP)+(1{LP)*whrp%#rpts  NB. Estimate plot-area x-position
   span=. >:(>./-<./)rpts
   yrnd=. ":<.(2{LP)+(3{LP)*(rp-<./rpts)%span     NB. Est. plot-area y-position
   pd 'textfont Courier ',(":4{LP),' Bold;textcolor BLACK'
   pd 'text ',xrnd,' ',yrnd,' ',":rp
   xrnd,' ',yrnd


Evening Out Plotted Points of a Function

I queried the J forum with the following:

from     Devon McCormick <>  12/27/07
to	 J-programming forum <>	
date	 Dec 27, 2007 11:05 AM	
subject	 Evening output	

Members of the Forum:

If I plot the points of a sine curve thusly

   'type point;pensize 5' plot 1 o. 8%~i:49

I get a nice graph but, due the nature of the sine function, points near the inflection points are more closely spaced than those further away.  How can I adjust my input points to get more evenly-spaced (for simplicity, on the Y-axis) outputs?  I'd like a method I could use for any arbitrary function.

Here's a simple attempt wherein I try to remove the point closest to the one before it and insert a point midway between the two most widely separated points:

NB.* evenOut: adjust inputs to fnc so outputs more evenly spaced.
evenOut=: 1 : 0
   diffs=. |2-~/\u y
   'whi wlo'=. diffs i. (>./,<./)diffs
   wlo=. wlo-wlo=<:#y   NB. Don't remove endpoint
   y=. (0 (>:whi)}1$~>:#y)#^:_1 y
   y=. (u -:+/y{~whi+0 2) (>:whi)}y
   y=. (<<<>:wlo){y

evenOut_test_=: 3 : 0
   tsts=. 0 1 10,0 10 11,:0 5 10
   assert. (] evenOut"1 tsts)-:(5.5 5 5) 1}&.|:tsts

If I could get a satisfactory version of this two-point substituter, it might work to apply it repeatedly until the point differences stabilize.  I'm satisfied with the result for these simple test cases:

   ]tsts=. 0 1 10,0 10 11,:0 5 10
0 1 10
0 10 11
0 5 10
   ] evenOut"1 tsts
0 5.5 10
0 5 11
0 5 10

(Testing with verb "]" for simplicity).  However, this result

    ] evenOut 0 2 4 5
0 1 2 5

isn't as good; a result like "0 2 3 5" might be better in this case.  We could define a measure of evenness:

   msrEveness=: 13 : '%:+/*:2-/\|2-/\y'

to quantify this preference (where a lower measure is better).  This shows us that of the three possibilities,

   msrEveness ] evenOut 0 2 4 5
   msrEveness 0 2 4 5
   msrEveness 0 2 3 5

the initial arrangement is best.  An arrangement like this

    msrEveness 0 5r3 10r3 5

is optimal in this case (we want to retain the endpoints unchanged).

Any ideas on how to approach this?

After some mis-communications and dead-ends, Raul Miller made the following helpful suggestion:

from     [[User:Raul Miller|Raul Miller]] <>  12/27/07
reply-to Programming forum <>	
to	 Programming forum <>	
date	 Dec 27, 2007 4:41 PM	
subject	 Re: [Jprogramming] Re: Evening output

On 12/27/07, Devon McCormick <> wrote:

> Well, something like
>   1 o. _1 o. 8%~i:49
> just gives me a straight line.

I see two problems here.

First, if you want variable x, you need to include your x axis
values in the data you send to plot.

Second, the domain of _1&o. lies between _1 and 1

  plot (;1&o.) _1 o. 8%~i:49

> In any case, I'm looking for a solution to evenly space the results
> of any function - sine is only an example function.

I think this amounts to solving for k=((dx%dt)^2)+(dy%dt)^2)
for some arbitrary function y of x so you can find the arbitrary
function x of t.

Instead of trying to approach this directly, I might try generating lots
of extra points, and then finding the distance between each point
and then doing a sum scan on them and then using I. to find points
roughly separated by an even interval and using those indices to
select from your original surplus of points.  (That said, I have not
tested this approach -- and note that ill-behaved functions could
still have unevenly spaced points, or other such issues.)

This last suggestion led me to work out the following:

egConverge=: 0 : 0
   pts0=: /:~_6.125 6.125 scaleNums ?5000$0
   cumdif=. 0,+/\|2-~/\1 o. pts0
   msrEveness 1 o. pts0{~ixs=. linkChain 0;cumdif;0.125
   msrEveness 1 o. pts0{~ixs=. linkChain 20;cumdif;0.125
   msrEveness 1 o. pts0{~ixs=. linkChain 10;cumdif;0.125
   msrEveness 1 o. pts0{~ixs=. linkChain 40;cumdif;0.125

improveEvenness=: 1 : 0
   inppts=. y
   svpts=. u fuzzAlt inppts
   msrs=. (_10 msrEveness\1 o. inppts)>:_10 msrEveness\1 o. svpts
   newpts=. ;{."1 msrs|."(0 1)(_10<\inppts),._10<\svpts

msrEveness=: 13 : '%:+/*:2-/\|2-/\y'

linkChain=: 3 : 0
NB. starting index, vector of ascending values, target difference
   'ix vav targ'=. y
   elm=. ix{vav
   ixs=. ix
   while. ix<<:#vav do.
NB. Find where closest to target diff.
       ix=. (>:ix)([+[:(]i.<./)}.)|vav-elm+targ
       elm=. ix{vav
       ixs=. ixs,ix

egWorkout1=: 0 : 0
   'grpsz targ'=: 20 0.125
   pts0=: (8*100)%~i:49*100
   cumdif=. 0,+/\|2-~/\1 o. pts0
   msrEveness 1 o. pts0{~ixs=. linkChain 0;cumdif;0.125
NB. 0...n -> local minimum, then look
   plarg plot (;1&o.)pts0{~0,ixs
NB. and further:
78 183 295 417 556 731 1193 1539 1712 1850
105 112 122 139 175 462 346 173 138
NB. So look for a second group around the midpoint:
   msrEveness 1 o. pts0{~ixs2=. linkChain 250;cumdif;0.125
   msrEveness 1 o. pts0{~ixs2=. linkChain 260;cumdif;0.125
NB. ...
   msrEveness 1 o. pts0{~ixs2=. linkChain 290;cumdif;0.125
   msrEveness 1 o. pts0{~ixs2=. linkChain 300;cumdif;0.125
NB. ...
   msrEveness 1 o. pts0{~ixs2=. linkChain 294;cumdif;0.125
NB. Compare the two:
   plarg plot ((;1&o.)ixs{pts0),:&.>(;1&o.)ixs2{pts0
   plarg plot ((;1&o.)pts0{~0,ixs),:&.>(;1&o.)pts0{~0,ixs2

NB. Compare (versus random initial):
   pts0=: /:~_6.125 6.125 scaleNums ?5000$0
   cumdif=. 0,+/\|2-~/\1 o. pts0
   msrEveness 1 o. pts0{~ixs=. linkChain 0;cumdif;0.125
NB. ...
   msrEveness 1 o. pts0{~ixs=. linkChain 38;cumdif;0.125
   msrEveness 1 o. pts0{~ixs=. linkChain 37;cumdif;0.125
   msrEveness 1 o. pts0{~ixs=. linkChain 39;cumdif;0.125

   $pts2=. 5.0612245%~i:31
   plarg plot ((;1&o.)pts0{~0,ixs),:&.>(;1&o.)pts2
   msrEveness 1 o. pts2
   msrEveness 1 o. pts0{~0,ixs

NB. Statistically, the two are very similar:
   usus pts0{~0,ixs
_6.125 6.125 0.0080577311 3.655643
   usus pts2
_6.125 6.125 2.2556912e_16 3.621713

NB. So is randomly started:
   cumdif=. 0,+/\|2-~/\1 o. ptsr=: /:~_6.125 6.125 scaleNums ?5000$0
   msrEveness 1 o. ptsr{~ixsr=. linkChain 35;cumdif;0.125
   msrEveness 1 o. ptsr{~0,ixsr
   usus ptsr{~0,ixsr
_6.125 6.125 0.0054441791 3.6309849

NB.* chTh1: find longest chain through candidates
chTh1=: 3 : 0
   'ix mat'=. y    NB. 2-row mat
   ixs=. ix
   elm=. (<0,ix){mat
   'lower hier'=. mat
   while. lower e.~ elm=. ix{hier do.
       ix=. lower i. elm
       ixs=. ixs,ix

   ppts=. ((pts0{~ixs2);1 o. pts0{~ixs2),:&.>(i:6.125j62);1 o. i:6.125j62
   ppts=. (<0 0.1+"(0 1)>0{ppts) 0}ppts  NB. Offset original a little over
   ppts=. (<0 0.05+"(0 1)>1{ppts) 1}ppts NB.  and up.
   plarg=. 'title Sine Wave Evened Out;pensize 5;type marker;'
   plarg=. plarg,keystyle m;keypos lcr;key Evened "Original (offset)"'
   plarg plot ppts
   pd 'save png C:\amisc\j\nycjug\200801\evenedOutVsNot.png'

Which results in the following picture. The red points are the original ones (offset slightly to avoid overlap); notice how they are close together at the turning points (the tips of the peaks and bottom of the valleys). The blue ones are more evenly spaced, which is the point of the exercise.


Advanced Topics: Excel Add-ins

Learning and Teaching J

Scan of Meeting Notes

NYCJUGMeetingNotes080108 40.jpg