Skip to content

Commit

Permalink
Merge branch 'master' of github.com:bentut/udaman
Browse files Browse the repository at this point in the history
  • Loading branch information
bentut committed Mar 18, 2013
2 parents 056d761 + 5e6b1eb commit 6fd60f3
Show file tree
Hide file tree
Showing 17 changed files with 3,984 additions and 198 deletions.
14 changes: 7 additions & 7 deletions Gemfile.lock
Expand Up @@ -68,7 +68,7 @@ GEM
google-spreadsheet-ruby (0.3.0)
google_drive (>= 0.3.0)
google_drive (0.3.2)
nokogiri (>= 1.4.4, != 1.5.1, != 1.5.2)
nokogiri (>= 1.4.4, != 1.5.2, != 1.5.1)
oauth (>= 0.3.6)
oauth2 (>= 0.5.0)
hoe (3.4.1)
Expand All @@ -86,13 +86,13 @@ GEM
mime-types (~> 1.16)
treetop (~> 1.4.8)
mechanize (2.5.1)
domain_name (>= 0.5.1, ~> 0.5)
mime-types (>= 1.17.2, ~> 1.17)
net-http-digest_auth (>= 1.1.1, ~> 1.1)
net-http-persistent (>= 2.5.2, ~> 2.5)
domain_name (~> 0.5, >= 0.5.1)
mime-types (~> 1.17, >= 1.17.2)
net-http-digest_auth (~> 1.1, >= 1.1.1)
net-http-persistent (~> 2.5, >= 2.5.2)
nokogiri (~> 1.4)
ntlm-http (>= 0.1.1, ~> 0.1)
webrobots (>= 0.0.9, ~> 0.0)
ntlm-http (~> 0.1, >= 0.1.1)
webrobots (~> 0.0, >= 0.0.9)
mime-types (1.19)
multi_json (1.6.1)
multipart-post (1.1.5)
Expand Down
128 changes: 16 additions & 112 deletions app/controllers/series_controller.rb
Expand Up @@ -51,41 +51,25 @@ def search
@search_results = AremosSeries.web_search(params[:search])
end

# def website_post
# @series = Series.find params[:id]
# @start_date = params[:start_date]
# @end_date = params[:end_date]
#
# start_date = @start_date.nil? ? (Time.now.to_date << (15)).to_s : @start_date.to_s
# end_date = @end_date.nil? ? Time.now.to_date.to_s : @end_date.to_s
# plot_data = @series.get_values_after(start_date,end_date)
# a_series = AremosSeries.get(@series.name)
# chart_id = @series.id.to_s+"_"+Date.today.to_s
#
# if params[:bar_type] == "yoy"
# bar_data = @series.annualized_percentage_change.data
# bar_id_label = "yoy"
# bar_color = "#AAAAAA"
# bar_label = "YOY % Change"
# render :partial => 'blog_chart_line_bar', :locals => {:plot_data => plot_data, :a_series => a_series, :chart_id => chart_id, :bar_id_label=>bar_id_label, :bar_label => bar_label, :bar_color => bar_color, :bar_data => bar_data }
# elsif params[:bar_type] == "ytd"
# bar_data = @series.ytd_percentage_change.data
# bar_id_label = "ytd"
# bar_color = "#AAAAAA"
# bar_label = "YTD % Change"
# render :partial => 'blog_chart_line_bar', :locals => {:plot_data => plot_data, :a_series => a_series, :chart_id => chart_id, :bar_id_label=>bar_id_label, :bar_label => bar_label, :bar_color => bar_color, :bar_data => bar_data }
# else
# render :partial => 'blog_chart_line', :locals => {:plot_data => plot_data, :a_series => a_series, :chart_id => chart_id}
# end
#
#
# #render :partial => "data_points", :locals => {:series => @series, :as => @as, :chg => @chg, :ytd_chg => @ytd_chg}
# end

def comparison_graph
@series = Series.find params[:id]
@comp = @series.aremos_data_side_by_side
end

def outlier_graph
@series = Series.find params[:id]
@comp = @series.ma_data_side_by_side
#residuals is actually whole range of values.
residuals = @comp.map { |date, ma_hash| ma_hash[:udaman] }
residuals.reject!{|a| a.nil?}
average = residuals.inject{ |sum, el| sum + el }.to_f / residuals.count
@std_dev = Math.sqrt((residuals.inject(0){ | sum, x | sum + (x - average) ** 2 }) / (residuals.count - 1))




#@series.backward_looking_moving_average.standard_deviation
end

def blog_graph
@series = Series.find params[:id]
Expand Down Expand Up @@ -137,85 +121,5 @@ def update_notes
render :partial => "investigation_sort.html"
end

# # GET /series
# # GET /series.xml
# def index
# @series = Series.all
#
# respond_to do |format|
# format.html # index.html.erb
# format.xml { render :xml => @series }
# end
# end
#
# # GET /series/1
# # GET /series/1.xml
# def show
# @series = Series.find(params[:id])
#
# respond_to do |format|
# format.html # show.html.erb
# format.xml { render :xml => @series }
# end
# end
#
# # GET /series/new
# # GET /series/new.xml
# def new
# @series = Series.new
#
# respond_to do |format|
# format.html # new.html.erb
# format.xml { render :xml => @series }
# end
# end
#
# # GET /series/1/edit
# def edit
# @series = Series.find(params[:id])
# end
#
# # POST /series
# # POST /series.xml
# def create
# @series = Series.new(params[:series])
#
# respond_to do |format|
# if @series.save
# format.html { redirect_to(@series, :notice => 'Series was successfully created.') }
# format.xml { render :xml => @series, :status => :created, :location => @series }
# else
# format.html { render :action => "new" }
# format.xml { render :xml => @series.errors, :status => :unprocessable_entity }
# end
# end
# end
#
# # PUT /series/1
# # PUT /series/1.xml
# def update
# @series = Series.find(params[:id])
#
# respond_to do |format|
# if @series.update_attributes(params[:series])
# format.html { redirect_to(@series, :notice => 'Series was successfully updated.') }
# format.xml { head :ok }
# else
# format.html { render :action => "edit" }
# format.xml { render :xml => @series.errors, :status => :unprocessable_entity }
# end
# end
# end
#
# # DELETE /series/1
# # DELETE /series/1.xml
# def destroy
# @series = Series.find(params[:id])
# @series.destroy
#
# respond_to do |format|
# format.html { redirect_to(series_index_url) }
# format.xml { head :ok }
# end
# end

end
224 changes: 224 additions & 0 deletions app/views/series/outlier_graph.html.erb
@@ -0,0 +1,224 @@

<script type="text/javascript" src="/javascripts/d3.v2.js"></script>
<script type="text/javascript" src="/javascripts/dat.gui.min.js"></script>



<h1><%= @series.name %></h1>
<div id= "chart_div">
<svg></svg>
</div>

<script type="text/javascript">

var gui = new dat.GUI();

var dat_gui_ranges = {
w : [0, 800],
h : [0, 1200],
udaman_width :[0,20],
aremos_width :[0,20],
mult :[0,10],

}

//put all hard coded values in this object
var params = {
scale: 1.7,
w: 555,
h: 280,
t_margin: 20,
r_margin: 20,
b_margin: 85,
l_margin: 50,

// bar_width: 50,
tick_length: 7,

x_axis_color: "gray",
x_axis_fontcolor: "gray",
x_axis_fontsize: 10,
x_axis_font_rotation: 320,

y_axis_color: "gray",
y_axis_fontcolor: "gray",
y_axis_fontsize: 10,

udaman_color: "#227893",
aremos_color: "#D84506",
aremos_width:1.5,
udaman_width:1.5,
mult: 6,
// fill_opacity: 0.2,
// point_size :2.5,
//just to store for redraw
viz_data: [],
};

function left_boundary() { return params.l_margin; }
function right_boundary() { return params.w * params.scale - params.r_margin; }
function top_boundary() { return params.t_margin; }
function bottom_boundary() { return params.h * params.scale - params.b_margin; }


function init_viz_element(svg, elem_with_class, data) {
var elem_parts = elem_with_class.split(".");
var elem = elem_parts[0];
var elem_class = elem_parts[1];

var viz_element = svg.selectAll(elem_with_class).data(data);
viz_element.enter().append(elem).attr("class", elem_class);
viz_element.exit().remove();

return viz_element;
}

function draw() {
var mult = params.mult;
var data = [
<% @comp.sort.each do |date_string, val| %>
{
date: "<%=date_string %>",
aremos: <%= val[:ma].nil? ? "null" : val[:ma] %>,
udaman: <%= val[:udaman].nil? ? "null" : val[:udaman] %>,
upper: <%= val[:ma].nil? ? "null" : val[:ma] %> <%= val[:ma].nil? ? "" : " + #{@std_dev} * mult"%>,
lower: <%= val[:ma].nil? ? "null" : val[:ma] %> <%= val[:ma].nil? ? "" : " - #{@std_dev} * mult"%>,
},
<%end%>
]
//store things for next draw iteration
params.viz_data = data;

var max_y_val = d3.max(data, function(row) {return row.upper > row.udaman && row.upper != null ? row.upper : row.udaman });// 30000; // replace with actual value from data
var min_y_val = d3.min(data, function(row) {return row.lower < row.udaman && row.lower != null ? row.lower : row.udaman });// 30000; // replace with actual value from data

//preparing SVG Area
var svg = d3.selectAll("svg");
svg.
attr("height", function(d,i) {return params.h * params.scale}).
attr("width", function(d) {return params.w * params.scale}).
attr("fill", 'green')
.data([data]);

var headers = data.map(function(elem) { return elem.date });
//var categories = headers.slice(1); //alert(categories.toSource());
var first_year = d3.min(data, function(row) {return row[headers[0]]});
var last_year = d3.max(data, function(row) {return row[headers[0]]});

var x = d3.scale.ordinal().domain(headers).rangePoints([left_boundary(), right_boundary() ]);
var y = d3.scale.linear().domain([min_y_val, max_y_val]).range([bottom_boundary(), top_boundary() ]);


// var line = init_viz_element(svg, "path.line_aremos", function(d) { return [d]; })
// .attr("d", d3.svg.line()
// .x(function(d) { return x(d.date); })
// .y(function(d) { return d.aremos === null ? y(min_y_val) : y(d.aremos); })
// )
// .attr("stroke", params.aremos_color)
// .attr("fill", "none")
// .attr("stroke-dasharray", "10,5")
// .attr("stroke-width", params.aremos_width);

var line = init_viz_element(svg, "path.line_upper", function(d) { return [d]; })
.attr("d", d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return d.upper === null ? y(min_y_val) : y(d.upper); })
)
.attr("stroke", params.aremos_color)
.attr("fill", "none")
.attr("stroke-dasharray", "10,5")
.attr("stroke-width", params.aremos_width);

var line = init_viz_element(svg, "path.line_lower", function(d) { return [d]; })
.attr("d", d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return d.lower === null ? y(min_y_val) : y(d.lower); })
)
.attr("stroke", params.aremos_color)
.attr("fill", "none")
.attr("stroke-dasharray", "10,5")
.attr("stroke-width", params.aremos_width);


var line = init_viz_element(svg, "path.line_udaman", function(d) { return [d]; })
.attr("d", d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return d.udaman === null ? y(min_y_val) : y(d.udaman); })
)
.attr("stroke", params.udaman_color)
.attr("stroke-width",params.udaman_width)
.attr("fill", "none");


//------ x Axis -------------------------------------------------------------------
var xaxis = init_viz_element(svg, "line.xaxis", ["dummy_data"])
.attr("y1", bottom_boundary())
.attr("y2", bottom_boundary())
.attr("x1", function(d) {return left_boundary()})
.attr("x2", function(d) {return right_boundary()})
.attr("stroke", params.x_axis_color);

var xticks = init_viz_element(svg, "line.xtick", headers)
.attr("y1", bottom_boundary())
.attr("y2", bottom_boundary() + params.tick_length )
.attr("x1", function(d) {return x(d)})
.attr("x2", function(d) {return x(d)})
.attr("stroke", params.x_axis_color);

var xtick_labels = init_viz_element(svg, "text.xtick_label", headers)
.attr("x", function(d) { return x(d)})
.attr("y", bottom_boundary())
.attr("fill", params.x_axis_fontcolor)
.attr("font-size", params.x_axis_fontsize+"px")
.attr("transform", function(d) {return "rotate("+params.x_axis_font_rotation +" "+ (x(d)+params.tick_length*4).toString() + "," + bottom_boundary() + ")"; })
.attr("text-anchor", "end")
.text(function(d) {return d; });

//------ x Axis End -------------------------------------------------------------------


//------ y Axis -------------------------------------------------------------------
var yaxis = init_viz_element(svg, "line.yaxis", ["dummy_data"])
.attr("x1", left_boundary())
.attr("x2", left_boundary())
.attr("y1", function(d) {return top_boundary()})
.attr("y2", function(d) {return bottom_boundary()})
.attr("stroke", params.y_axis_color);

var yticks = init_viz_element(svg, "line.ytick", y.ticks(10))
.attr("y1", function(d) {return y(d)})
.attr("y2", function(d) {return y(d)})
.attr("x1", left_boundary() - params.tick_length)
.attr("x2", left_boundary() )
.attr("stroke", params.y_axis_color);

var ytick_labels = init_viz_element(svg, "text.ytick_label", y.ticks(10))
.attr("y", function(d) { return y(d) + (params.y_axis_fontsize / 3.5)})
.attr("x", left_boundary() - params.tick_length * 1.5)
.attr("fill", params.y_axis_fontcolor)
.attr("font-size", params.y_axis_fontsize+"px")
.attr("text-anchor", "end")
.text(function(d) {return d; });

//------ y Axis End -------------------------------------------------------------------

}


//all dat.gui changes should trigger a redraw
// generate the dat.gui control for any numerical ranges
d3.entries(dat_gui_ranges).forEach(function(elem) {
var attr = elem.key;
var range = elem.value;
gui.add(params, attr, range[0], range[1]).onChange(draw);
} );

gui.addColor(params, 'udaman_color').onChange(draw);
gui.addColor(params, 'aremos_color').onChange(draw);

//add color or custom controls here

draw();
</script>


0 comments on commit 6fd60f3

Please sign in to comment.