self-descriptive-chart


Information

Created with NetLogo version NetLogo 4.0.4
Running with NetLogoLite.jar version 404.


WHAT IS IT?


-------
Inspired by this XKCD cartoon by Randall Munroe:
http://xkcd.com/688/
This is a chart that describes itself.
This is a chart that shows information about the number of white pixels in this chart.
The pie chart shows the proportion of white pixels to black pixels.
The bar chart shows the relative quantity of white pixels in the three sub-charts.
The xy chart shows the location of pixels in this chart that are white

COPYRIGHT


-----
This model is free to use with attribution for any legal non-commercial purpose.

Procedures

NetLogo Version: NetLogo 4.0.4

globals
[ page-color
  ink-color
  margin
  scale
  ink-patches
  piechart
  barchart
  mapchart
  line-width
]

breed [ charts chart ]
charts-own
[ !top      ;; top(max-y) of the chart region
  !bottom   ;; bottom (min-y) of the chart
  !left     ;; left (min-x) of the chart
  !right    ;; right (max-x) of the chart
  .top      ;; top of the CANVAS
  .bottom   ;; and so on
  .left
  .right
  .centerx
  .centery
  !width
  .width
  .height
  region ;; all the patches in the subchart
  border ;; the patches that surround the canvas
  canvas ;; the patches inside the border
  axis   ;; part of the graph ink that never changes, 
         ;; eg the circle around the pie, the lines under the bars
  field  ;; part of the graph ink that changes
  
  rad
]

patches-own 
[ a
]
to startup
   reset
   repeat 20 [ go ]
end

to reset
   initialize
   
end

to initialize
   ca
   set page-color white
   set ink-color black
   set margin int ( .5 + world-height * .05)
   set scale .8
   set line-width floor (.5 + world-height * .025)
     
   set piechart new-chart 3 1 "pie" 
   set barchart new-chart 3 2 "bar"
   set mapchart new-chart 3 3 "map"
   
   
   step0
end    

to step0
   ask patches [ set pcolor page-color ]
   ask charts
   [ draw-border
     draw-axis
   ]
end

to clear-region
   ask region [ set pcolor page-color ]
end

to draw-border
   ask border [ set pcolor ink-color ]
end

to draw-axis
   ask axis [ set pcolor ink-color ]
end
   
to clear-canvas
   ask canvas [ set pcolor page-color ]
end
      
to-report new-chart [ #charts #chart #type]
   ;; charts is number of charts overall
   ;; chart is the number of this chart

   let me nobody

   output-print (word "creating chart " #chart ) 

   create-charts 1
   [ set me self
     set heading 0
     set color black 
     set size 0
     hide-turtle
     
     let chart-width floor (world-width / #charts) 
     
     
     set !top max-pycor
     set !bottom min-pycor
     set !left chart-width * (#chart - 1)
     set !right chart-width * #chart

     set .top !top - (margin + line-width) 
     set .bottom !bottom + (margin + line-width)
     set .left !left + (margin + line-width)
     set .right !right - (margin + line-width)
     
     set .centerx .5 * (.left + .right)
     set .centery .5 * (.top + .bottom)
     
     set !width  ( !right - !left   )
     set .width  ( .right - .left   )
     set .height ( .top   - .bottom )
     
     setxy .centerx .centery
     
     d "---creating region"

     let !left! !left
     let !right! !right
     let !top! !top
     let !bottom! !bottom
     
     let .left. .left
     let .right. .right
     let .top. .top
     let .bottom. .bottom
     
     set region patches with 
         [ !left!  <= pxcor and pxcor <= !right!
             and 
           !bottom! <= pycor and pycor <= !top!
         ]

     paint region 135
     
     d "---creating canvas"

     set canvas region with
         [ .left.  <= pxcor and pxcor <= .right.
             and 
           .bottom. <= pycor and pycor <= .top.
         ]

     paint canvas 125

     d "---creating border"

     set border region with
         [ ;; left and right side
           ( !bottom! + margin < pycor and pycor < !top! - margin
             and
             ( (!left! + margin)  < pxcor and pxcor < .left.
                 or
               .right. < pxcor and pxcor < (!right! - margin) 
             )
           )
           or
           ;; top and bottom side
           ( !left! + margin < pxcor and pxcor < !right! - margin
               and
             ( !bottom! + margin < pycor and pycor < .bottom.
                 or
               .top.    < pycor and pycor < (!top! - margin)
             )
           )
         ]

     paint border 115

     d "---creating axis"

     set axis no-patches
     if #type = "pie"
     [ let $cx xcor
       let $cy ycor
       set rad (.right - .left) * scale * .5
       let $canvas canvas
       let $rad rad
       let $rad1 rad - (line-width / 2)
       let $rad2 rad + (line-width / 2) 
       let $rad3 rad - line-width
       set axis canvas with [ in-ring $rad1 $rad2 ]
       set field canvas with [ distance myself <= $rad3 ] 
     ]
     if #type = "bar"
     [ let margin2 margin + margin
       set axis (patch-set
         canvas with
           [ .left. + margin2 < pxcor and pxcor < .right. - margin2
             and
             .bottom. + margin2 < pycor and pycor < .bottom. + margin2 + line-width
           ]
         canvas with 
           [ .bottom. + margin2 < pycor and pycor < .top. - margin2
             and
             .left. + margin2 < pxcor and pxcor < .left. + margin2 + line-width
           ]               
         )
       set field 
         canvas with
           [ .left. + margin2 + line-width < pxcor and pxcor < .right. - margin2 - line-width
             and 
             .bottom. + margin2 + line-width < pycor and pycor < .top. - margin2 - line-width
           ]
            
     ]

     paint axis 95

  ]
  report me
end

to-report quick-distance [ agent ]
   let x  pxcor - [ pxcor ] of agent
   let y  pycor - [ pycor ] of agent
   report ( x * x + y * y )
end
   
to-report safe-patch-towards-turtle [ a-turtle ]
   ifelse pxcor != [ xcor ] of a-turtle
          or
          pycor != [ ycor ] of a-turtle
  [ report towards a-turtle ]
  [ report 0 ]
end
        
to go
   let allpix count patches
   let inked count patches with [ pcolor = ink-color ]
   let blank allpix - inked
   let inkratio inked / allpix

   ;; update PIE CHART of PROPORTION OF PIXELS that are WHITE
   
   ask piechart
   [ let inkangle 360 * inkratio
     ask field
     [ ifelse safe-patch-towards-turtle myself < inkangle
       [ set pcolor ink-color ]
       [ set pcolor page-color ]
     ]
   ]
  
   ;; update BAR CHART of RELATIVE AMOUT OF WHITE PIXELS

   ask barchart
   [ let $base .bottom + 4

     let max-ratio 0
     
     let $bar-shift ( .width / 16 )
     let $bar-width $bar-shift * 2 + 1
     let $bar-hscale 2
     
     ask field [ set pcolor page-color ]
     let field.left min [ pxcor ] of field
     let field.right max [ pxcor ] of field
     let field.span field.right - field.left
     let bars count charts
     let bar.width field.span / bars
     let bar.top max [ pycor ] of field
     let bar.bottom min [ pycor ] of field + line-width
     let bar.height bar.top - bar.bottom 
     
     let ink-ratios map [ (count [ region  with [ pcolor = ink-color ] ] of ? ) / (count [ region ] of ? ) ](sort charts)
     let max-ink max ink-ratios
     
     let bar.scale bar.height / max-ink
     
     (foreach (sort charts) (n-values bars [ 1 + ? ]) (ink-ratios)
     [ let $chart ?1
       let $index ?2
       let $ink-ratio ?3
       
       let bar.left field.left + bar.width * ($index - 1) + line-width * 2
       let bar.right bar.left + bar.width - line-width * 2
       
       let bar.adj.height bar.scale * $ink-ratio
              
       ask field with [ bar.left <= pxcor and pxcor <= bar.right 
                        and
                        pycor < bar.bottom + bar.adj.height
                        and
                        pycor > bar.bottom
                      ]
       [ set pcolor ink-color ]
     ])
   ]   

   ;; update GRAPH of PIXELS in IMAGE that are ink color

   ask patches [ set a 0 ]
   
   let .scale [((.width ) / !width) ] of mapchart
   
   ;; map all the patches into the field
   
   ask patches
   [ if pcolor = ink-color
     [ let mapx ([.left] of mapchart + .scale * pxcor / 3)
       let mapy ([.centery - .centery / 5 ] of mapchart + .scale * pycor / 3)
       ask patch mapx mapy
       [ set a a + 1 ]
     ]
   ]
   
   ask mapchart
   [ ask canvas
     [ ifelse a > 0
       [ set pcolor ink-color ]
       [ set pcolor page-color ]
     ]
   ] 
   
   tick

end
    
to d [ string ]
   output-print string
end   

to paint [ #patches #pcolor ]
   ;; used during debugging
   ;ask #patches [ set pcolor #pcolor ]
   ;display
end   

to-report in-ring [ d1 d2 ]
   let dd distance myself
   report (d1 <= dd and dd <= d2)
end

                    


Download Link

View or download the complete model file (to download: right-click, save-link-as):
-- Download self-descriptive-chart --