Harry Seldon's blog

Fractals, Chaos, and Control Systems on Rails

Read

Stacked bar chart with Rails and Open Flash Chart

Posted by Harry Seldon on April 20, 2009

Consequently to questions about the stacked bar charts, I have added an example to the OFC test app. Once again this example is a translation of the original example from Teethgrinder. However, this time there are indeed a few catches.

See the live example of the stacked bar chart here

The code
in test_it_controller.rb:

  def index_stacked_bar
    @graph = open_flash_chart_object(600,300,"/test_it/graph_code_stacked_bar")     
  end

  def graph_code_stacked_bar
    title = Title.new("A stacked bar chart")
    title.set_style( "{font-size: 20px; color: #F24062; text-align: center;}" );
    bar_stack = BarStack.new

    # set_colours does not work
    # set a cycle of 3 colours:
#    colour_array =  Array.new( [ '#C4D318', '#50284A', '#7D7B6A'] )# yellow purple gray
##    bar_stack.set_colour('#C4D318', '#50284A', '#7D7B6A');
#    bar_stack.set_colour(colour_array);
#    # add 3 bars:
#    bar_stack.append_stack( Array.new( [2.5, 5, 2.5 ]) ); # 0
#    # add 4 bars, the fourth will be the same colour as the first:
#    bar_stack.append_stack( Array.new( [2.5, 5, 1.25, 1.25 ]) ); # 1 
##    debugger
#    bsv4 = BarStackValue.new(5, '#ff0000') #red
#    bsv5 = BarStackValue.new(2, '#ff00ff') # 3 pink
#   
#    bar_stack.append_stack( Array.new( [5,bsv4] ) ); # 2 red 
#    bar_stack.append_stack( Array.new( [2, 2, 2, 2,  bsv5]) ); # 3 pink 

    # Using  BarStackValue to set the colour     
    bsv1 = BarStackValue.new(2.5, '#C4D318') # yellow    
    bsv2 = BarStackValue.new(5, '#50284A')   # purple
    bsv3 = BarStackValue.new(1.25, '#7D7B6A') # gray
    bsv31 = BarStackValue.new(1.25, '#C4D318') # yellow
    bsv4 = BarStackValue.new(5, '#C4D318') # yellow
    bsv41 = BarStackValue.new(5, '#ff0000') # red
    bsv5 = BarStackValue.new(2, '#ff00ff') # pink    
    bsv6 = BarStackValue.new(2, '#C4D318') # yellow
    bsv7 = BarStackValue.new(2, '#50284A') # yellow
    bsv8 = BarStackValue.new(2, '#7D7B6A')   # purple

    bar_stack.append_stack( Array.new( [bsv1, bsv2, bsv1 ]) ); # 0
    bar_stack.append_stack( Array.new( [bsv1, bsv2, bsv3,bsv31 ]) ); # 0
    bar_stack.append_stack( Array.new( [bsv4,bsv41] ) ); # 2 red 
    bar_stack.append_stack( Array.new( [bsv6, bsv7, bsv8, bsv6,  bsv5]) ); # 3 pink 

#   Does not work    
#    bsk1 = BarStackKey.new( '#C4D318', 'Kiting', 13 )
#    bsk2 = BarStackKey.new( '#50284A', 'Work', 13 )
#    bsk3 = BarStackKey.new( '#7D7B6A', 'Drinking', 13 )
#    bsk4 = BarStackKey.new( '#ff0000', 'XXX', 13 )
#    bsk5 = BarStackKey.new( '#ff00ff', 'What rhymes with purple? Nurple?', 13 )
#    
#    bar_stack.set_keys(Array.new([bsk1, bsk2,bsk3,bsk4,bsk5]))
##    bar_stack.set_keys(Array.new([bsk1, bsk2,bsk3,bsk4,bsk5]))
    bar_stack.set_tooltip( 'X label [#x_label#], Value [#val#]<br>Total [#total#]' );

    y = YAxis.new();
    y.set_range( 0, 14, 2 );

    x = XAxis.new();
    x.set_labels_from_array( Array.new( ['Winter', 'Spring', 'Summer', 'Autmn' ]) );

    tooltip = Tooltip.new;
    tooltip.set_hover();

    chart = OpenFlashChart.new
    chart.set_title(title)
    chart.add_element(bar_stack)

    chart.x_axis =  x ;
    chart.y_axis =  y ;
    chart.set_tooltip( tooltip );

    render :text => chart.to_s   
    end
 

in index_stacked_bar.html.erb:

<script type="text/javascript" src="/javascripts/swfobject.js"></script>
<%= @graph %>

The catches
In Teethgrinder’s code there is a call to the set_colours method. For some undetermined reasons this method does not work with OFC. Instead we directly set the color using the color parameter in BarStackValue. However, the BarStackValue class constructor returned me an error about a bad number of arguments. So I needed to make the following modification:
in vendor/plugins/open_flash_chart/lib/open_flash_chart/bar_stack.rb

  
  class BarStackValue < Base
    def initialize(val,colour, args={})
      super args
      @val    = val
      @colour = colour     
    end
  end

Moreover the BarStackKey function that allows to write the legends is not implemented yet. This is something to be fixed in a future release.

A Reminder
For this example most of the code is in the controller. However, I remind you that the proper place for it would be in your model if you want to keep your code DRY.
You would use a graph like a view. Let us check this example:
In the model MyModel:

  
def make_chart_1
    title = Title.new("MY TITLE")
    bar = BarGlass.new
    bar.set_values([1,2,3,4,5,6,7,8,9])
    @chart = OpenFlashChart.new
    @chart.set_title(title)
    @chart.add_element(bar)
end

Notice you can add all the inputs you want to the graph creating function in the model.

In the controller:

  
  mymodel.make_chart_1

In the view :

 <%= mymodel.chart.js_open_flash_chart_object("my_chart_js_1", 550,300) %>

See this post for more info.

Enjoy your stacked bar chart. And by the way if you own a website using OFC leave a link so we can see it at work.

Posted in | 2 comments | Tags , , , , , | atom

How to draw Mandelbrot's fractal with Rails and Open Flash Chart?

Posted by Harry Seldon on April 18, 2009

Mandelbrot set

Let us draw the Mandelbrot set with OFC. The point is to make a new example of use of OFC and it is also to have some fun with the so interesting fractal theory. To see how fashionable it is, read this post: Good news from the combat against the crisis. This post is highly inspired from this nice French page about the Mandelbrot set. I am using the algorithm given there.

Definition of the Mandelbrot set
For each point of the complex plane we associate the sequence: zn+1=zn2+A with z0=0 and A=a+ib the point affix. Iff the sequence is bounded the point A belongs to the Mandelbrot”s set. Problem is, it is not easy for a computer to say if a sequence remains bounded. It would require an infinite number of calculations. For each point, we are simply going to make a ‘large’ number of calculation on the sequence. It can be shown analytically that if the module of zn is greater than 2 the sequence will diverge. So during nmax iterations, if the sequence goes above 2, the sequence diverges and it has diverged all the quicker as the number of iteration is low. If it is quick to diverge it is far from the set. A color will be associated to each point according to its distance from the set. If the algorithm reaches nmax the probability for the point to belong to the set is maximal with respect to our computation.

To code without complex numbers we will use the real coordinates, the sequence being written equivalently as:
xn+1=xn2-yn2+a
yn+1=2 xn yn+b

Code for Open Flash Chart
The implementation with Rails and OFC is explained hereafter. It is using a scatter chart.

in test_it_controller.rb

  def index_mandelbrot_fractal
    # from http://perso.numericable.fr/~haasjn/haasjn/AlgoMandel.txt 
    @graph = open_flash_chart_object(500,500,"/test_it/graph_code_Mandelbrot_fractal")     
  end

Also in test_it_controller.rb

  def graph_code_Mandelbrot_fractal
    #    Algorithm to draw Mandelbrot's fractal 
    #    
    #    variables a,b,x,y,xmin,ymax,cx,cy,width,step:real
    #              i,j,nx,ny,n:int
    #              r: table
    #        
    #    cx,cy    coordinates of the image center in the complex plane
    #    xmin     image left limit 
    #    ymax     image upper limit
    #    width    image width in the complex plane
    #    nx       image horizontal resolution 
    #    ny       image vertical resolution
    #    nmax     maximum number of loops to compute the convergence of the complex sequence
    #    step     step between 2 points 
    #    r        table containing the result for each point
    #
    #    in the loop 
    #    i,j  indices of the point 
    #    a,b  point coordinates
    #    x,y  values of the complex sequence
    #    x1   next value of x 
    #    n    indice of the complex sequence
    # 
    #    Algorithm beginning 
    #    cx,cy,width,nx,ny,nmax are given at start 
    cx = 0
    cy = 0
    width = 4.to_f
    nx = 100.to_f
    ny = 100.to_f
    nmax = 250.to_f

    xmin = cx-width/2
    ymax = cy+width/2*ny/nx
    step  = width/nx

    # Preparation of the chart
    chart = OpenFlashChart.new
    title = Title.new("Mandelbrot set")
    chart.set_title(title)
    r = Array.new # results 

    # The loop asks : does the point (a,b) belong to the Mandelbrot set ? 
    # The bigger n, the more probable the point belongs to  the set 
    for j in 0..ny-1
      b=ymax-j*step       
      for i in 0..nx-1
        a=i*step+xmin
        x=0
        y=0 
        n=0
        #  while x*x+y*y<4 and n<=nmax
        while x*x+y*y<4 && n<=nmax
          x1=x*x-y*y+a
          y=2*x*y+b
          x=x1
          n=n+1
        end

        # Adding the point to the chart
        # Needs to associate a color according to n 
        # that is according to the time needed to converge
        amplif = 1
        c = (16.0.+n/nmax*(255.0-16.0)*amplif).to_int
        c = [255,c].min
        col_gray = (255-c).to_int.to_s(16).to_s
        col =  "#"+col_gray+col_gray+col_gray
        scatter = Scatter.new(col, 2);
        scatter.set_values([ScatterValue.new(a,b)])
        chart.add_element( scatter )

        # if you want to store the result 
        r.push([a,b,n,c])
      end #i
    end #j

    x_axis = XAxis.new
    x_axis.set_range(xmin,-xmin)
    chart.x_axis = x_axis

    y_axis = YAxis.new
    y_axis.set_range( -ymax, ymax )
    chart.y_axis = y_axis
    render :text => chart.to_s      
  end

in index_mandelbrot_fractal.html.erb

<script type="text/javascript" src="/javascripts/swfobject.js"></script>
<%= @graph %>

Notice the code for the computation and the graph are made together in the controller code. This is just for simplicity to write this post. Technically, the computation is more a work for your model. Preparing the graph is also a work for the model. With a DRY code you would have one model method to prepare the data, one to prepare the chart. Then in the controller you call the method that prepares the chart and you sends the data to the view.

Result
Here is the Mandelbrot set chart. Beware it takes about 10 seconds to load. Indeed the algorithm is computationally intensive. The code is available in the OFC test app on github. Here is the controller code.

Thanks for having read this world first: drawing the Mandelbrot set with Ruby on Rails and OFC.

Posted in , | 2 comments | Tags , , , , , | atom

Tutorial Rails/OFC/Ajax : Alter the chart using Javascript

Posted by Harry Seldon on September 28, 2008

In a first example I showed how to load a chart using javascript. Here I will show you how to dynamically alter an OFC chart without recreating it. This example is a raw adaptation of this Teethgrinder’s example. The chart is hard coded in ajax code so it is not loaded by OFC rails plugin, this will be done in a next example. Indeed, the aim of all this is at some point to be able to create a chart and then modify it to hide one signal or to zoom in or to change the legend, or etc.

The controller code is simple. Well OK it is even void (as I said the graph is hard coded in the javascript, it gives you opportunity to see how an OFC graph is serialized in json):

class TestItController < ApplicationController
def index_js_4
end
end

Everything happens in the view (index_js_4.html.erb) through ajax code and OFC code. I assume you have installed OFC rails plugin. You need 2 more things: the json2 library available here and the ajax code from Teethgrinder available here. Put these 2 js files in your public/javascripts folder.

The view:

<html>
    <head>
        <%#= javascript_include_tag :defaults, 'swfobject' %>
        <script type="text/javascript" src="/javascripts/swfobject.js">
        </script>
        <script type="text/javascript" src="/javascripts/json2.js">
        </script>
        <script type="text/javascript" src="/javascripts/tutorial-js.js">
        </script>
        <script type="text/javascript">

            function ofc_ready(){
                alert('ofc_ready');
            }

            function open_flash_chart_data(){
                // alert( 'reading data' );
                return JSON.stringify(data);
            }

            function findSWF(movieName){
                if (navigator.appName.indexOf("Microsoft") != -1) {
                    return window[movieName];
                }
                else {
                    return document[movieName];
                }
            }

            var data = {
                "elements": [{
                    "type": "hbar",
                    "values": [{
                        "left": 0,
                        "right": 5
                    }, {
                        "left": 0,
                        "right": 3
                    }, {
                        "left": 4,
                        "right": 8
                    }, {
                        "left": 4,
                        "right": 8
                    }, {
                        "left": 4,
                        "right": 8
                    }],
                    "colour": "#AF99DF"
                }],
                "title": {
                    "text": "Sat Sep 27 2008"
                },
                "y_axis": {
                    "labels": ["Job 1", "Job 2", "Job 3", "Job 4", "Job 5"]
                },
                "x_axis": {
                    "offset": false,
                    "min": 0,
                    "max": 10
                }
            };
        </script>
        <script type="text/javascript">
            swfobject.embedSWF("/open-flash-chart.swf", "my_chart", "550", "350", "9.0.0");
        </script>
    </head>
    <body>
    Here is the chart:
    </p>
    <div id="my_chart"></div>
    <p>
        <a href="javascript:update(data)">Update</a>, <a href="javascript:save(data)">Save</a>
    </p>
    <br/><br/>
    </body>
</html>

To understand this example have a look at the js file tutorial-js.js. It contains the update and save functions. It is understandable even by someone like me who does not speak javascript fluently. You can see the live example here.

Posted in | no comments | Tags , , , , , , | atom

Search

Navigate


Recent Comments

Recent Posts

Tags

actuators aircraft atc blog chaos chaos_theory charts control controllers controls crisis economy finance flight fractals git gnc gs guidance linux mandelbrot marketing navigation ns ofc on pilot rails ruby sas scs sensors statistics systems techcrunch thinkosphere tutorial typo ubuntu wifi

Categories

Archives

Syndicate


Sponsor