def getLineGraph(data,line1color,line2color): # Set the vertical range based on data values tweets = [d[0] for d in data] retweets = [d[1] for d in data] ratio = [str(int(d[1]/d[0]*100))+'%' for d in data] hours = [d[2] for d in data] mx = max(tweets) mn = min(retweets) buffer = (mx - mn)/100 # average retweets have consitently been less min_y = mn - buffer max_y = mx + buffer # Chart size of 750x400 pixels and specifying the range for the Y axis chart = SimpleLineChart(750, 400, y_range=[min_y, max_y]) chart.set_legend(['Tweets','Retweets']) chart.set_legend_position('t') # Add the chart data chart.add_data(tweets) chart.add_data(retweets) # Set the line colour to blue chart.set_colours([line1color,line2color]) # Set the horizontal dotted lines chart.set_grid(0, 25, 5, 5) #set left axis to values range left_axis = range(min_y, max_y, (max_y-min_y)/10) chart.set_axis_labels(Axis.BOTTOM, hours) chart.set_axis_labels(Axis.BOTTOM, ratio) chart.set_axis_labels(Axis.LEFT, left_axis) return chart.get_url()
def velocity_chart(self): graph_width = 600 graph_height = 300 x_max = self.total_iterations y_max = max(max(self.estimate_stories_data()), max(self.estimate_tasks_data()), max(self.work_data())) chart = SimpleLineChart(graph_width, graph_height, x_range=(1, x_max + 1), y_range=(0, y_max + 1)) chart.add_data(self.estimate_stories_data()) chart.add_data(self.estimate_tasks_data()) chart.add_data(self.work_data()) chart.set_grid(0, 100.0 / y_max + 1, 5, 5) chart.set_colours(['FF0000', '00FF00', '0000FF']) chart.set_legend([_('rough story estimates'), _('task estimates'), _('worked')]) chart.set_legend_position('b') chart.set_axis_labels(Axis.LEFT, ['', '', _('days')]) chart.set_axis_labels(Axis.BOTTOM, range(1, x_max + 1)) chart.set_axis_range(Axis.LEFT, 0, y_max + 1) return chart.get_url(data_class=ExtendedData)
def velocity_chart(self): graph_width = 600 graph_height = 300 x_max = self.total_iterations y_max = max(max(self.estimate_stories_data()), max(self.estimate_tasks_data()), max(self.work_data())) chart = SimpleLineChart(graph_width, graph_height, x_range=(1, x_max + 1), y_range=(0, y_max + 1)) chart.add_data(self.estimate_stories_data()) chart.add_data(self.estimate_tasks_data()) chart.add_data(self.work_data()) chart.set_grid(0, 100.0 / y_max + 1, 5, 5) chart.set_colours(['FF0000', '00FF00', '0000FF']) chart.set_legend( [_('rough story estimates'), _('task estimates'), _('worked')]) chart.set_legend_position('b') chart.set_axis_labels(Axis.LEFT, ['', '', _('days')]) chart.set_axis_labels(Axis.BOTTOM, list(range(1, x_max + 1))) chart.set_axis_range(Axis.LEFT, 0, y_max + 1) return chart.get_url(data_class=ExtendedData)
def _line_strip_graph(data, legends, axis_labels, size, steps, type=SimpleLineChart, multiline=False): if multiline: max_values = [] min_values = [] for row in data: max_values.append(max(row)) min_values.append(min(row)) max_y = max(max_values) min_y = min(min_values) else: max_y = max(data) min_y = min(data) #validando si hay datos para hacer grafico if max_y == 0: return None chart = SimpleLineChart(size[0], size[1], y_range=[0, max_y * 1.05]) if multiline: for row in data: chart.add_data(row) else: chart.add_data(data) step = ((max_y * 1.05) - (min_y * 0.95)) / steps #validando en caso de el paso sea menor que uno y de cero en la conversion if step < 1: step = 1 tope = int(round(max_value * 1.05)) if tope < max_value: tope += 2 else: tope += 1 try: left_axis = range(int(round(min_y * 0.95)), tope, int(step)) except ValueError: #error por que los range no soportan decimales left_axis = range(0, 2) left_axis[0] = '' chart.set_axis_labels(Axis.LEFT, left_axis) chart.set_colours( ['FFBC13', '22A410', 'E6EC23', '2B2133', 'BD0915', '3D43BD']) chart.set_axis_labels(Axis.BOTTOM, axis_labels) chart.set_legend(legends) chart.set_legend_position('b') return chart
def group_post_activity(request, group_slug): group = get_object_or_404(BaseGroup, slug=group_slug) postcount = [] replycount = [] allcount = [] listdate = [] thedate = date(date.today().year - 1, date.today().month, 1) skip = False while thedate.year != date.today().year or thedate.month != date.today( ).month: if thedate.month == 12: enddate = date(year=thedate.year + 1, month=1, day=1) else: enddate = date(year=thedate.year, month=thedate.month + 1, day=1) posts = GroupTopic.objects.filter(parent_group=group, created__range=(thedate, enddate)).count() #replies = ThreadedComment.objects.filter(content_object__parent_group=group, # date_submitted__range=(thedate, enddate)).count() replies = 0 postcount.append(posts) replycount.append(replies) allcount.append(posts + replies) if not skip: listdate.append(thedate.strftime("%B %y")) else: listdate.append("") skip = not skip thedate = enddate postactivity = SimpleLineChart( 600, 450, y_range=(min(min(postcount), min(replycount)), max(max(postcount), max(replycount)) + 1)) postactivity.add_data(postcount) postactivity.add_data(replycount) postactivity.add_data(allcount) yaxis = range(min(min(postcount), min(replycount)), max(max(postcount), max(replycount)) + 1, 1) if len(yaxis) < 2: yaxis.append(1) yaxis[0] = '' postactivity.set_axis_labels(Axis.LEFT, yaxis) postactivity.set_axis_labels(Axis.BOTTOM, listdate) postactivity.set_colours(['ff0000', '0000ff', '00ff00']) postactivity.set_legend(['posts', 'replies', 'total']) postactivity.set_legend_position('b') return postactivity.get_url()
def _line_strip_graph(data, legends, axis_labels, size, steps, type=SimpleLineChart, multiline=False): if multiline: max_values = [] min_values = [] for row in data: max_values.append(max(row)) min_values.append(min(row)) max_y = max(max_values) min_y = min(min_values) else: max_y = max(data) min_y = min(data) #validando si hay datos para hacer grafico if max_y==0: return None chart = SimpleLineChart(size[0], size[1], y_range=[0, max_y*1.05]) if multiline: for row in data: chart.add_data(row) else: chart.add_data(data) step = ((max_y*1.05)-(min_y*0.95))/steps #validando en caso de el paso sea menor que uno y de cero en la conversion if step<1: step = 1 tope = int(round(max_value*1.05)) if tope < max_value: tope+=2 else: tope+=1 try: left_axis = range(int(round(min_y*0.95)), tope, int(step)) except ValueError: #error por que los range no soportan decimales left_axis = range(0, 2) left_axis[0]='' chart.set_axis_labels(Axis.LEFT, left_axis) chart.set_colours([ 'FFBC13','22A410','E6EC23','2B2133','BD0915','3D43BD']) chart.set_axis_labels(Axis.BOTTOM, axis_labels) chart.set_legend(legends) chart.set_legend_position('b') return chart
def group_post_activity(request, group_slug): group = get_object_or_404(BaseGroup, slug=group_slug) postcount = [] replycount = [] allcount = [] listdate = [] thedate = date(date.today().year - 1, date.today().month, 1) skip = False while thedate.year != date.today().year or thedate.month != date.today().month: if thedate.month == 12: enddate = date(year=thedate.year + 1, month=1, day=1) else: enddate = date(year=thedate.year, month=thedate.month + 1, day=1) posts = GroupTopic.objects.filter(parent_group=group, created__range=(thedate, enddate)).count() #replies = ThreadedComment.objects.filter(content_object__parent_group=group, # date_submitted__range=(thedate, enddate)).count() replies = 0 postcount.append(posts) replycount.append(replies) allcount.append(posts + replies) if not skip: listdate.append(thedate.strftime("%B %y")) else: listdate.append("") skip = not skip thedate = enddate postactivity = SimpleLineChart(600, 450, y_range=(min(min(postcount), min(replycount)), max(max(postcount), max(replycount)) + 1)) postactivity.add_data(postcount) postactivity.add_data(replycount) postactivity.add_data(allcount) yaxis = range(min(min(postcount), min(replycount)), max(max(postcount), max(replycount)) + 1, 1) if len(yaxis) < 2: yaxis.append(1) yaxis[0] = '' postactivity.set_axis_labels(Axis.LEFT, yaxis) postactivity.set_axis_labels(Axis.BOTTOM, listdate) postactivity.set_colours(['ff0000', '0000ff', '00ff00']) postactivity.set_legend(['posts', 'replies', 'total']) postactivity.set_legend_position('b') return postactivity.get_url()
def __line_strip_graphic__(data, legends, axis_labels, size, steps, type=SimpleLineChart, multiline=False): if multiline: max_values = [] min_values = [] for row in data: max_values.append(max(row)) min_values.append(min(row)) max_y = max(max_values) min_y = min(min_values) else: max_y = max(data) min_y = min(data) chart = SimpleLineChart(size[0], size[1], y_range=[0, max_y * 1.05]) if multiline: for row in data: chart.add_data(row) else: chart.add_data(data) step = ((max_y * 1.05) - (min_y * 0.95)) / steps try: left_axis = range(int(min_y * 0.95), int(max_y * 1.05), int(step)) except ValueError: #error por que los range no soportan decimales left_axis = range(0, 2) left_axis[0] = '' chart.set_axis_labels(Axis.LEFT, left_axis) chart.set_colours( ['FFBC13', '22A410', 'E6EC23', '2B2133', 'BD0915', '3D43BD']) chart.set_axis_labels(Axis.BOTTOM, axis_labels) chart.set_legend(legends) chart.set_legend_position('b') return chart
def __line_strip_graphic__(data, legends, axis_labels, size, steps, type=SimpleLineChart, multiline=False): if multiline: max_values = [] min_values = [] for row in data: max_values.append(max(row)) min_values.append(min(row)) max_y = max(max_values) min_y = min(min_values) else: max_y = max(data) min_y = min(data) chart = SimpleLineChart(size[0], size[1], y_range=[0, max_y*1.05]) if multiline: for row in data: chart.add_data(row) else: chart.add_data(data) step = ((max_y*1.05)-(min_y*0.95))/steps try: left_axis = range(int(min_y*0.95), int(max_y*1.05), int(step)) except ValueError: #error por que los range no soportan decimales left_axis = range(0, 2) left_axis[0]='' chart.set_axis_labels(Axis.LEFT, left_axis) chart.set_colours([ 'FFBC13','22A410','E6EC23','2B2133','BD0915','3D43BD']) chart.set_axis_labels(Axis.BOTTOM, axis_labels) chart.set_legend(legends) chart.set_legend_position('b') return chart
def _line_strip_graph(data, legends, axis_labels, size, steps, type=SimpleLineChart, multiline=False, **kwargs): if multiline: max_values = [] min_values = [] for row in data: max_values.append(max(row)) min_values.append(min(row)) max_y = max(max_values) min_y = min(min_values) else: max_y = max(data) min_y = min(data) #validando si hay datos para hacer grafico if max_y==0: return None chart = SimpleLineChart(size[0], size[1], y_range=[0, max_y*1.05]) if multiline: for row in data: chart.add_data(row) else: chart.add_data(data) step = ((max_y*1.05)-(min_y*0.95))/steps #validando en caso de el paso sea menor que uno y de cero en la conversion if step<1: step = 1 max_value = max_y tope = int(round(max_value*1.05)) if tope < max_value: tope+=2 else: tope+=1 try: left_axis = range(int(round(min_y*0.95)), tope, int(step)) except ValueError: #error por que los range no soportan decimales left_axis = range(0, 2) left_axis[0]='' chart.set_axis_range(Axis.LEFT, min_y, tope) if 'units' in kwargs: chart.set_axis_labels(Axis.LEFT, kwargs['units']) if 'time' in kwargs: chart.set_axis_labels(Axis.BOTTOM, kwargs['time']) chart.set_grid(0, 25, 4, 4,) chart.chls=4|4 #chart.fill_linear_stripes(Chart.CHART, 0, 'FFFFEF', 0.2, 'FFFFFF', 0.2) chart.set_colours(COLORS) if axis_labels: chart.set_axis_labels(Axis.BOTTOM, axis_labels) chart.set_legend(legends) chart.set_legend_position('b') if 'thickness' in kwargs: if multiline: for i in range(len(data)): chart.set_line_style(index = i, thickness=kwargs['thickness']) else: chart.set_line_style(index=0, thickness=kwargs['thickness']) return chart
def main_dashboard(request): today, created = DailyStats.objects.get_or_create(day=date.today()) if today.users == 0: today.users = 1 # ---- Daily usage ---- enddate = date.today() #startdate = enddate - timedelta(weeks=60) startdate = enddate - timedelta(weeks=4) averageusage = DailyStats.objects.filter(day__range=(startdate, enddate)).order_by('day') days = [] signins = [] posts = [] replies = [] whiteboards = [] signups = [] listsignups = [] listupgrades = [] deletions = [] numUsers = [] numRegularMembers = [] regupgrades = [] renewals = [] regdowngrades = [] for s in averageusage: days.append(s.day.strftime("%B %y")) signins.append(s.signins) posts.append(s.posts) replies.append(s.replies) whiteboards.append(s.whiteboardEdits) signups.append(s.signups) listsignups.append(s.mailinglistsignups) listupgrades.append(s.mailinglistupgrades) deletions.append(s.deletions) numUsers.append(s.users) numRegularMembers.append(s.regularmembers) regupgrades.append(s.regupgrades) renewals.append(s.renewals) regdowngrades.append(s.regdowngrades) xaxis = [] #for i in range(0, len(days), 1): # this will make limited test data look better for i in range(0, len(days), len(days)/8): xaxis.append(days[i]) # ---- Daily usage ---- dailyUsageChart = SimpleLineChart(600, 450, y_range=(0, max(signins))) #chart.add_data(avgsignins) dailyUsageChart.add_data(posts) dailyUsageChart.add_data(replies) dailyUsageChart.add_data(signins) dailyUsageChart.add_data(whiteboards) dailyUsageChart.set_colours(['ff0000', 'ffff00', '00ff00', '0000ff']) dailyUsageChart.set_legend(['posts', 'replies', 'signins', 'whiteboards']) dailyUsageChart.set_legend_position('b') #yaxis = range(0, max_signins + 1, 2) # this will make limited test data look better yaxis = range(0, max(signins), max(signins)/10) yaxis[0] = '' dailyUsageChart.set_axis_labels(Axis.LEFT, yaxis) dailyUsageChart.set_axis_labels(Axis.BOTTOM, xaxis) dailyUsage = dailyUsageChart.get_url() # ---- Account changes ---- accountChangesChart = SimpleLineChart(600, 450, y_range=(0, 25)) accountChangesChart.add_data(signups) accountChangesChart.add_data(listsignups) accountChangesChart.add_data(listupgrades) accountChangesChart.add_data(deletions) accountChangesChart.set_colours(['ff0000', 'ffff00', '00ff00', '0000ff']) accountChangesChart.set_legend(['account signups', 'email signups', 'email upgrades', 'deletions']) accountChangesChart.set_legend_position('b') #yaxis = range(0, 25, 2) # this will make limited test data look better yaxis = range(0, min(max(listsignups), 10), max(max(listsignups)/10, 1)) yaxis[0] = '' accountChangesChart.set_axis_labels(Axis.LEFT, yaxis) accountChangesChart.set_axis_labels(Axis.BOTTOM, xaxis) accountChanges = accountChangesChart.get_url() # ---- Membership ---- membershipChart = SimpleLineChart(600, 450, y_range=(42000, 52000)) membershipChart.add_data(numUsers) membershipChart.add_data(numRegularMembers) membershipChart.set_colours(['ff0000', '0000ff']) membershipChart.set_legend(['total users', 'regular members']) membershipChart.set_legend_position('b') yaxis = range(42000, 52000, 1000) yaxis[0] = '' yaxis2 = range(0, 1500, 50) yaxis2[0] = '' membershipChart.set_axis_labels(Axis.LEFT, yaxis) membershipChart.set_axis_labels(Axis.RIGHT, yaxis2) membershipChart.set_axis_labels(Axis.BOTTOM, xaxis) membershipChart = membershipChart.get_url() # ---- Account changes ---- membershipChangesChart = SimpleLineChart(600, 450, y_range=(0, 10)) membershipChangesChart.add_data(regupgrades) membershipChangesChart.add_data(renewals) membershipChangesChart.add_data(regdowngrades) membershipChangesChart.set_colours(['ff0000', 'ffff00', '00ff00']) membershipChangesChart.set_legend(['regular upgrades', 'renewals', 'regular downgrades']) membershipChangesChart.set_legend_position('b') #yaxis = range(0, 25, 2) # the same. yaxis = range(0, max(max(regupgrades), max(regdowngrades), max(renewals)), max(max(max(regupgrades), max(regdowngrades), max(renewals))/10, 1)) yaxis[0] = '' membershipChangesChart.set_axis_labels(Axis.LEFT, yaxis) membershipChangesChart.set_axis_labels(Axis.BOTTOM, xaxis) membershipChanges = membershipChangesChart.get_url() # ---- Status breakdown ---- statusBreakdownChart = PieChart3D(600, 240) mlistmembers = today.users - today.regularmembers - today.associatemembers statusBreakdownChart.add_data([mlistmembers + 1, # FIXME: the +1 is needed so pygoogle doesn't crash (it doesn't handle zeroes well) today.associatemembers + 1, today.regularmembers + 1]) statusBreakdownChart.set_colours(['ff0000', 'ffff00', '00ff00']) statusBreakdownChart.set_pie_labels(["mailing list members", "associate members", "regular members"]) statusBreakdown = statusBreakdownChart.get_url() # ---- Membership breakdown ---- chapters = Network.objects.filter(chapter_info__isnull=False, is_active=True) chapternames = [] chaptermembers = [] for chapter in chapters: chapternames.append(chapter.slug) chaptermembers.append(chapter.members.all().count()) membershipBreakdownChart = StackedHorizontalBarChart(500, 500, x_range=(0, max(chaptermembers))) membershipBreakdownChart.add_data(chaptermembers) yaxis = range(0, max(chaptermembers), 10) yaxis[0] = '' membershipBreakdownChart.set_axis_labels(Axis.BOTTOM, yaxis) membershipBreakdownChart.set_axis_labels(Axis.LEFT, chapternames) membershipBreakdownChart.set_bar_width(330 / len(chapternames)) membershipBreakdown = membershipBreakdownChart.get_url() # ---- Province breakdown ---- profiletype = ContentType.objects.get_for_model(MemberProfile) addresses = Address.objects.filter(content_type=profiletype) totalprov = Address.objects.filter(content_type=profiletype).count() + 1 # FIXME provinces = [] provincecount = [] provincelist = list(pycountry.subdivisions.get(country_code='CA')) for p in provincelist: pcode = p.code.split('-')[1] provincecount2 = Address.objects.filter(content_type=profiletype, province=pcode).count() if provincecount2 == 0: provincecount2 = 1 provincecount.append(provincecount2) provinces.append(pcode + " (%d%%)" % (provincecount2*100/totalprov)) #provinces = sorted(provinces) provinceBreakdownChart = PieChart3D(600, 240) provinceBreakdownChart.add_data(provincecount) #provinceBreakdownChart.set_colours(['ff0000', 'ffff00', '00ff00']) provinceBreakdownChart.set_pie_labels(provinces) provinceBreakdown = provinceBreakdownChart.get_url() # ---- Gender breakdown ---- males = MemberProfile.objects.filter(gender='M').count() + 1 females = MemberProfile.objects.filter(gender='F').count() + 1 genderunknown = MemberProfile.objects.filter(gender__isnull=True).count() + 1 #FIXME gendertotal = males + females + genderunknown genderBreakdownChart = PieChart3D(600, 240) genderBreakdownChart.add_data([males, females, genderunknown]) genderBreakdownChart.set_colours(['ff0000', 'ffff00', '00ff00']) genderBreakdownChart.set_pie_labels(['Male (%d%%)' % (males*100/gendertotal), 'Female (%d%%)' % (females*100/gendertotal), 'Unspecified (%d%%)' % (genderunknown*100/gendertotal)]) genderBreakdown = genderBreakdownChart.get_url() # ---- Student breakdown ---- students = User.objects.filter(studentrecord__graduation_date__isnull=True).count() + 1 nonstudents = User.objects.filter(workrecord__end_date__isnull=True).count() + 1 # yeah, i know, not 100% accurate since a student can have a part-time job studentBreakdownChart = PieChart3D(600, 240) studentBreakdownChart.add_data([students, nonstudents]) studentBreakdownChart.set_colours(['ff0000', '00ff00']) studentBreakdownChart.set_pie_labels(['Students', 'Non-students']) studentBreakdown = studentBreakdownChart.get_url() # ---- Language breakdown ---- preferen = MemberProfile.objects.filter(language='E').count() + 1 preferfr = MemberProfile.objects.filter(language='F').count() + 1 prefernone = MemberProfile.objects.filter(language__isnull=True).count() + 1 languageBreakdownChart = PieChart3D(600, 240) languageBreakdownChart.add_data([preferen, preferfr, prefernone]) languageBreakdownChart.set_colours(['ff0000', 'ffff00', '00ff00']) languageBreakdownChart.set_pie_labels(['english', 'french', 'not specified']) languageBreakdown = languageBreakdownChart.get_url() # ---- Post breakdown ---- postspublic = GroupTopic.objects.filter(parent_group__visibility='E', parent_group__parent__isnull=True).count() + 1 postsprivate = GroupTopic.objects.filter(parent_group__parent__isnull=True ).exclude(parent_group__visibility='E').count() + 1 postspublicchapter = GroupTopic.objects.filter(parent_group__visibility='E', parent_group__parent__isnull=False).count() + 1 postsprivatechapter = GroupTopic.objects.filter(parent_group__parent__isnull=False ).exclude(parent_group__visibility='E').count() + 1 postcount = postspublic + postsprivate + postspublicchapter + postsprivatechapter postBreakdownChart = PieChart3D(600, 240) postBreakdownChart.add_data([postspublic, postspublicchapter, postsprivatechapter, postsprivate]) #postBreakdownChart.set_colours(['ff0000', 'ffff00', '00ff00']) postBreakdownChart.set_pie_labels(['public', 'public chapter', 'private chapter', 'private']) postBreakdown = postBreakdownChart.get_url() # ---- Login distribution ---- logincount = [] malelogins = [] femalelogins = [] for i in range(0,30): logincount.append(MemberProfile.objects.filter(login_count__gte=i).count()) malelogins.append(MemberProfile.objects.filter(login_count__gte=i, gender='M').count()) femalelogins.append(MemberProfile.objects.filter(login_count__gte=i, gender='F').count()) loginDistribution = SimpleLineChart(600, 450, y_range=(0, 9000)) loginDistribution.add_data(logincount) loginDistribution.add_data(malelogins) loginDistribution.add_data(femalelogins) loginDistribution.set_colours(['ff0000', '0000ff', '00ff00']) loginDistribution.set_legend(['logins', 'male', 'female']) loginDistribution.set_legend_position('b') yaxis = range(0, 9000, 500) # that last number should be 25 or 50. but for testing... yaxis[0] = '' loginDistribution.set_axis_labels(Axis.LEFT, yaxis) loginDistribution.set_axis_labels(Axis.BOTTOM, range(0, 30)) loginDistribution = loginDistribution.get_url() # ---- Login recency ---- loginrecent = [] loginrecentdate = [] thedate = date(date.today().year - 1, date.today().month, 1) skip = False while thedate.year != date.today().year or thedate.month != date.today().month: if thedate.month == 12: enddate = date(year=thedate.year + 1, month=1, day=1) else: enddate = date(year=thedate.year, month=thedate.month + 1, day=1) loginrecent.append(MemberProfile.objects.filter(previous_login__range=(thedate, enddate)).count()) if not skip: loginrecentdate.append(thedate.strftime("%B %y")) else: loginrecentdate.append("") skip = not skip thedate = enddate loginRecency = SimpleLineChart(600, 450, y_range=(0, max(loginrecent)+1)) loginRecency.add_data(loginrecent) yaxis = range(0, max(loginrecent), max(max(loginrecent)/10, 1)) # that last number should be 25 or 50. but for testing... if len(yaxis) == 0: yaxis.append(10) yaxis.append(10) yaxis[0] = '' loginRecency.set_axis_labels(Axis.LEFT, yaxis) loginRecency.set_axis_labels(Axis.BOTTOM, loginrecentdate) loginRecency = loginRecency.get_url() # ---- Age distribution ---- ages = [] for age in range(15, 75): year = date.today().year - age ages.append(MemberProfile.objects.filter(date_of_birth__year=year).count()) ageDistribution = SimpleLineChart(600, 450, y_range=(0, max(ages)+1)) ageDistribution.add_data(ages) yaxis = range(0, max(ages)+1, 50) yaxis[0] = '' ageDistribution.set_axis_labels(Axis.LEFT, yaxis) ageDistribution.set_axis_labels(Axis.BOTTOM, range(15, 75, 5)) ageDistribution = ageDistribution.get_url() # ---- Finally! ---- return render_to_response("stats/dashboard.html", {"signins": today.signins, "posts": today.posts, "replies": today.replies, "signups": today.signups, "listsignups": today.mailinglistsignups, "listupgrades": today.mailinglistupgrades, "deletions": today.deletions, "regupgrades": today.regupgrades, "regdowngrades": today.regdowngrades, "renewals": today.renewals, "totalusers": today.users, "dailyUsage": dailyUsage, "accountChanges": accountChanges, "membershipChart": membershipChart, "membershipChanges": membershipChanges, "statusBreakdown": statusBreakdown, "mlistmembers": mlistmembers, "mlistmemberspercent": mlistmembers * 100 / today.users, "associatemembers": today.associatemembers, "associatememberspercent": today.associatemembers * 100 / today.users, "regularmembers": today.regularmembers, "regularmemberspercent": today.regularmembers * 100 / today.users, "membershipBreakdown": membershipBreakdown, "provinceBreakdown": provinceBreakdown, "provincecount": totalprov, "genderBreakdown": genderBreakdown, "studentBreakdown": studentBreakdown, "languageBreakdown": languageBreakdown, "postBreakdown": postBreakdown, "loginDistribution": loginDistribution, "loginRecency": loginRecency, "ageDistribution": ageDistribution }, context_instance=RequestContext(request))
def main_dashboard(request): today, created = DailyStats.objects.get_or_create(day=date.today()) if today.users == 0: today.users = 1 # ---- Daily usage ---- enddate = date.today() #startdate = enddate - timedelta(weeks=60) startdate = enddate - timedelta(weeks=4) averageusage = DailyStats.objects.filter( day__range=(startdate, enddate)).order_by('day') days = [] signins = [] posts = [] replies = [] whiteboards = [] signups = [] listsignups = [] listupgrades = [] deletions = [] numUsers = [] numRegularMembers = [] regupgrades = [] renewals = [] regdowngrades = [] for s in averageusage: days.append(s.day.strftime("%B %y")) signins.append(s.signins) posts.append(s.posts) replies.append(s.replies) whiteboards.append(s.whiteboardEdits) signups.append(s.signups) listsignups.append(s.mailinglistsignups) listupgrades.append(s.mailinglistupgrades) deletions.append(s.deletions) numUsers.append(s.users) numRegularMembers.append(s.regularmembers) regupgrades.append(s.regupgrades) renewals.append(s.renewals) regdowngrades.append(s.regdowngrades) xaxis = [] #for i in range(0, len(days), 1): # this will make limited test data look better for i in range(0, len(days), len(days) / 8): xaxis.append(days[i]) # ---- Daily usage ---- dailyUsageChart = SimpleLineChart(600, 450, y_range=(0, max(signins))) #chart.add_data(avgsignins) dailyUsageChart.add_data(posts) dailyUsageChart.add_data(replies) dailyUsageChart.add_data(signins) dailyUsageChart.add_data(whiteboards) dailyUsageChart.set_colours(['ff0000', 'ffff00', '00ff00', '0000ff']) dailyUsageChart.set_legend(['posts', 'replies', 'signins', 'whiteboards']) dailyUsageChart.set_legend_position('b') #yaxis = range(0, max_signins + 1, 2) # this will make limited test data look better yaxis = range(0, max(signins), max(signins) / 10) yaxis[0] = '' dailyUsageChart.set_axis_labels(Axis.LEFT, yaxis) dailyUsageChart.set_axis_labels(Axis.BOTTOM, xaxis) dailyUsage = dailyUsageChart.get_url() # ---- Account changes ---- accountChangesChart = SimpleLineChart(600, 450, y_range=(0, 25)) accountChangesChart.add_data(signups) accountChangesChart.add_data(listsignups) accountChangesChart.add_data(listupgrades) accountChangesChart.add_data(deletions) accountChangesChart.set_colours(['ff0000', 'ffff00', '00ff00', '0000ff']) accountChangesChart.set_legend( ['account signups', 'email signups', 'email upgrades', 'deletions']) accountChangesChart.set_legend_position('b') #yaxis = range(0, 25, 2) # this will make limited test data look better yaxis = range(0, min(max(listsignups), 10), max(max(listsignups) / 10, 1)) yaxis[0] = '' accountChangesChart.set_axis_labels(Axis.LEFT, yaxis) accountChangesChart.set_axis_labels(Axis.BOTTOM, xaxis) accountChanges = accountChangesChart.get_url() # ---- Membership ---- membershipChart = SimpleLineChart(600, 450, y_range=(42000, 52000)) membershipChart.add_data(numUsers) membershipChart.add_data(numRegularMembers) membershipChart.set_colours(['ff0000', '0000ff']) membershipChart.set_legend(['total users', 'regular members']) membershipChart.set_legend_position('b') yaxis = range(42000, 52000, 1000) yaxis[0] = '' yaxis2 = range(0, 1500, 50) yaxis2[0] = '' membershipChart.set_axis_labels(Axis.LEFT, yaxis) membershipChart.set_axis_labels(Axis.RIGHT, yaxis2) membershipChart.set_axis_labels(Axis.BOTTOM, xaxis) membershipChart = membershipChart.get_url() # ---- Account changes ---- membershipChangesChart = SimpleLineChart(600, 450, y_range=(0, 10)) membershipChangesChart.add_data(regupgrades) membershipChangesChart.add_data(renewals) membershipChangesChart.add_data(regdowngrades) membershipChangesChart.set_colours(['ff0000', 'ffff00', '00ff00']) membershipChangesChart.set_legend( ['regular upgrades', 'renewals', 'regular downgrades']) membershipChangesChart.set_legend_position('b') #yaxis = range(0, 25, 2) # the same. yaxis = range( 0, max(max(regupgrades), max(regdowngrades), max(renewals)), max(max(max(regupgrades), max(regdowngrades), max(renewals)) / 10, 1)) yaxis[0] = '' membershipChangesChart.set_axis_labels(Axis.LEFT, yaxis) membershipChangesChart.set_axis_labels(Axis.BOTTOM, xaxis) membershipChanges = membershipChangesChart.get_url() # ---- Status breakdown ---- statusBreakdownChart = PieChart3D(600, 240) mlistmembers = today.users - today.regularmembers - today.associatemembers statusBreakdownChart.add_data([ mlistmembers + 1, # FIXME: the +1 is needed so pygoogle doesn't crash (it doesn't handle zeroes well) today.associatemembers + 1, today.regularmembers + 1 ]) statusBreakdownChart.set_colours(['ff0000', 'ffff00', '00ff00']) statusBreakdownChart.set_pie_labels( ["mailing list members", "associate members", "regular members"]) statusBreakdown = statusBreakdownChart.get_url() # ---- Membership breakdown ---- chapters = Network.objects.filter(chapter_info__isnull=False, is_active=True) chapternames = [] chaptermembers = [] for chapter in chapters: chapternames.append(chapter.slug) chaptermembers.append(chapter.members.all().count()) membershipBreakdownChart = StackedHorizontalBarChart( 500, 500, x_range=(0, max(chaptermembers))) membershipBreakdownChart.add_data(chaptermembers) yaxis = range(0, max(chaptermembers), 10) yaxis[0] = '' membershipBreakdownChart.set_axis_labels(Axis.BOTTOM, yaxis) membershipBreakdownChart.set_axis_labels(Axis.LEFT, chapternames) membershipBreakdownChart.set_bar_width(330 / len(chapternames)) membershipBreakdown = membershipBreakdownChart.get_url() # ---- Province breakdown ---- profiletype = ContentType.objects.get_for_model(MemberProfile) addresses = Address.objects.filter(content_type=profiletype) totalprov = Address.objects.filter( content_type=profiletype).count() + 1 # FIXME provinces = [] provincecount = [] provincelist = list(pycountry.subdivisions.get(country_code='CA')) for p in provincelist: pcode = p.code.split('-')[1] provincecount2 = Address.objects.filter(content_type=profiletype, province=pcode).count() if provincecount2 == 0: provincecount2 = 1 provincecount.append(provincecount2) provinces.append(pcode + " (%d%%)" % (provincecount2 * 100 / totalprov)) #provinces = sorted(provinces) provinceBreakdownChart = PieChart3D(600, 240) provinceBreakdownChart.add_data(provincecount) #provinceBreakdownChart.set_colours(['ff0000', 'ffff00', '00ff00']) provinceBreakdownChart.set_pie_labels(provinces) provinceBreakdown = provinceBreakdownChart.get_url() # ---- Gender breakdown ---- males = MemberProfile.objects.filter(gender='M').count() + 1 females = MemberProfile.objects.filter(gender='F').count() + 1 genderunknown = MemberProfile.objects.filter( gender__isnull=True).count() + 1 #FIXME gendertotal = males + females + genderunknown genderBreakdownChart = PieChart3D(600, 240) genderBreakdownChart.add_data([males, females, genderunknown]) genderBreakdownChart.set_colours(['ff0000', 'ffff00', '00ff00']) genderBreakdownChart.set_pie_labels([ 'Male (%d%%)' % (males * 100 / gendertotal), 'Female (%d%%)' % (females * 100 / gendertotal), 'Unspecified (%d%%)' % (genderunknown * 100 / gendertotal) ]) genderBreakdown = genderBreakdownChart.get_url() # ---- Student breakdown ---- students = User.objects.filter( studentrecord__graduation_date__isnull=True).count() + 1 nonstudents = User.objects.filter( workrecord__end_date__isnull=True).count() + 1 # yeah, i know, not 100% accurate since a student can have a part-time job studentBreakdownChart = PieChart3D(600, 240) studentBreakdownChart.add_data([students, nonstudents]) studentBreakdownChart.set_colours(['ff0000', '00ff00']) studentBreakdownChart.set_pie_labels(['Students', 'Non-students']) studentBreakdown = studentBreakdownChart.get_url() # ---- Language breakdown ---- preferen = MemberProfile.objects.filter(language='E').count() + 1 preferfr = MemberProfile.objects.filter(language='F').count() + 1 prefernone = MemberProfile.objects.filter( language__isnull=True).count() + 1 languageBreakdownChart = PieChart3D(600, 240) languageBreakdownChart.add_data([preferen, preferfr, prefernone]) languageBreakdownChart.set_colours(['ff0000', 'ffff00', '00ff00']) languageBreakdownChart.set_pie_labels( ['english', 'french', 'not specified']) languageBreakdown = languageBreakdownChart.get_url() # ---- Post breakdown ---- postspublic = GroupTopic.objects.filter( parent_group__visibility='E', parent_group__parent__isnull=True).count() + 1 postsprivate = GroupTopic.objects.filter( parent_group__parent__isnull=True).exclude( parent_group__visibility='E').count() + 1 postspublicchapter = GroupTopic.objects.filter( parent_group__visibility='E', parent_group__parent__isnull=False).count() + 1 postsprivatechapter = GroupTopic.objects.filter( parent_group__parent__isnull=False).exclude( parent_group__visibility='E').count() + 1 postcount = postspublic + postsprivate + postspublicchapter + postsprivatechapter postBreakdownChart = PieChart3D(600, 240) postBreakdownChart.add_data( [postspublic, postspublicchapter, postsprivatechapter, postsprivate]) #postBreakdownChart.set_colours(['ff0000', 'ffff00', '00ff00']) postBreakdownChart.set_pie_labels( ['public', 'public chapter', 'private chapter', 'private']) postBreakdown = postBreakdownChart.get_url() # ---- Login distribution ---- logincount = [] malelogins = [] femalelogins = [] for i in range(0, 30): logincount.append( MemberProfile.objects.filter(login_count__gte=i).count()) malelogins.append( MemberProfile.objects.filter(login_count__gte=i, gender='M').count()) femalelogins.append( MemberProfile.objects.filter(login_count__gte=i, gender='F').count()) loginDistribution = SimpleLineChart(600, 450, y_range=(0, 9000)) loginDistribution.add_data(logincount) loginDistribution.add_data(malelogins) loginDistribution.add_data(femalelogins) loginDistribution.set_colours(['ff0000', '0000ff', '00ff00']) loginDistribution.set_legend(['logins', 'male', 'female']) loginDistribution.set_legend_position('b') yaxis = range( 0, 9000, 500) # that last number should be 25 or 50. but for testing... yaxis[0] = '' loginDistribution.set_axis_labels(Axis.LEFT, yaxis) loginDistribution.set_axis_labels(Axis.BOTTOM, range(0, 30)) loginDistribution = loginDistribution.get_url() # ---- Login recency ---- loginrecent = [] loginrecentdate = [] thedate = date(date.today().year - 1, date.today().month, 1) skip = False while thedate.year != date.today().year or thedate.month != date.today( ).month: if thedate.month == 12: enddate = date(year=thedate.year + 1, month=1, day=1) else: enddate = date(year=thedate.year, month=thedate.month + 1, day=1) loginrecent.append( MemberProfile.objects.filter( previous_login__range=(thedate, enddate)).count()) if not skip: loginrecentdate.append(thedate.strftime("%B %y")) else: loginrecentdate.append("") skip = not skip thedate = enddate loginRecency = SimpleLineChart(600, 450, y_range=(0, max(loginrecent) + 1)) loginRecency.add_data(loginrecent) yaxis = range(0, max(loginrecent), max( max(loginrecent) / 10, 1)) # that last number should be 25 or 50. but for testing... if len(yaxis) == 0: yaxis.append(10) yaxis.append(10) yaxis[0] = '' loginRecency.set_axis_labels(Axis.LEFT, yaxis) loginRecency.set_axis_labels(Axis.BOTTOM, loginrecentdate) loginRecency = loginRecency.get_url() # ---- Age distribution ---- ages = [] for age in range(15, 75): year = date.today().year - age ages.append( MemberProfile.objects.filter(date_of_birth__year=year).count()) ageDistribution = SimpleLineChart(600, 450, y_range=(0, max(ages) + 1)) ageDistribution.add_data(ages) yaxis = range(0, max(ages) + 1, 50) yaxis[0] = '' ageDistribution.set_axis_labels(Axis.LEFT, yaxis) ageDistribution.set_axis_labels(Axis.BOTTOM, range(15, 75, 5)) ageDistribution = ageDistribution.get_url() # ---- Finally! ---- return render_to_response( "stats/dashboard.html", { "signins": today.signins, "posts": today.posts, "replies": today.replies, "signups": today.signups, "listsignups": today.mailinglistsignups, "listupgrades": today.mailinglistupgrades, "deletions": today.deletions, "regupgrades": today.regupgrades, "regdowngrades": today.regdowngrades, "renewals": today.renewals, "totalusers": today.users, "dailyUsage": dailyUsage, "accountChanges": accountChanges, "membershipChart": membershipChart, "membershipChanges": membershipChanges, "statusBreakdown": statusBreakdown, "mlistmembers": mlistmembers, "mlistmemberspercent": mlistmembers * 100 / today.users, "associatemembers": today.associatemembers, "associatememberspercent": today.associatemembers * 100 / today.users, "regularmembers": today.regularmembers, "regularmemberspercent": today.regularmembers * 100 / today.users, "membershipBreakdown": membershipBreakdown, "provinceBreakdown": provinceBreakdown, "provincecount": totalprov, "genderBreakdown": genderBreakdown, "studentBreakdown": studentBreakdown, "languageBreakdown": languageBreakdown, "postBreakdown": postBreakdown, "loginDistribution": loginDistribution, "loginRecency": loginRecency, "ageDistribution": ageDistribution }, context_instance=RequestContext(request))
def render(self,data={}, context={}): assert self.series is not None, "'chart.series' must be set" converter = wfcommon.units.Converter(context["units"]) # merge builtin defaults, context and renderer config config = ChartConfig() if context.has_key('chart'): config.__dict__.update(context['chart']) config.__dict__.update(self.__dict__) # create the chart chart = SimpleLineChart(config.width, config.height) colors = [] legend_set = False legend = [] chart_min = sys.maxint chart_max = -sys.maxint # Prepare series config ordered_series = [] for key, serie in self.series.iteritems(): serie_config = ChartConfig() serie_config.__dict__.update(config.__dict__) serie_config.__dict__.update(serie) ordered_series.append( (serie_config.order, key, serie) ) ordered_series.sort( cmp=lambda x,y: cmp(x[0],y[0]) ) ordered_keys = [] for order, key, serie in ordered_series: ordered_keys.append(key) # Draws for each serie index=0 for order, key, serie in ordered_series: serie_config = ChartConfig() serie_config.__dict__.update(config.__dict__) serie_config.__dict__.update(serie) serie_data = copy.copy(data[key.split('.')[0]]['series'][key.split('.')[1]]) measure = key.split('.')[0] if flat(serie_data): # Series with all data = None continue if serie_config.accumulate: serie_data = accumulate(serie_data) elif serie_config.interpolate: serie_data = interpolate(serie_data) # Compute min and max value for the serie and the whole chart min_data = amin(serie_data) chart_min = rmin(chart_min, min_data) if serie_data.__contains__(min_data): min_index = serie_data.index(min_data) else: min_index = None max_data = max(serie_data) chart_max = max(chart_max, max_data) if serie_data.__contains__(max_data): max_index = serie_data.index(max_data) else: max_index = None (serie_data, min_index, max_index) = compress_to(serie_data, config.nval, min_index, max_index) chart.add_data(serie_data) colors.append(_valid_color(serie_config.color)) if serie_config.max and not max_index == None : max_config = ChartConfig() max_config.__dict__.update(serie_config.__dict__) max_config.__dict__.update(serie_config.max) str_max_data = str(round(converter.convert(measure, max_data), 1)) chart.add_marker(index, max_index, 't'+str_max_data, _valid_color(max_config.text), max_config.size) chart.add_marker(index, max_index, max_config.style, _valid_color(max_config.color), max_config.thickness) if serie_config.min and not min_index == None: min_config = ChartConfig() min_config.__dict__.update(serie_config.__dict__) min_config.__dict__.update(serie_config.min) str_min_data = str(round(converter.convert(measure, min_data), 1)) chart.add_marker(index, min_index, 't'+str_min_data, _valid_color(min_config.text), min_config.size) chart.add_marker(index, min_index, min_config.style, _valid_color(min_config.color), min_config.thickness) if serie_config.last: last_config = ChartConfig() last_config.__dict__.update(serie_config.__dict__) last_config.__dict__.update(serie_config.last) last_index=len(serie_data)-1 last_data = serie_data[last_index] if last_data: str_last_data = str(round(converter.convert(measure, last_data), 1)) chart.add_marker(index, last_index, 't'+str(last_data), _valid_color(last_config.text), last_config.size) chart.add_marker(index, last_index, last_config.style, _valid_color(last_config.color), last_config.thickness) if serie_config.area: fill_config = ChartConfig() fill_config.__dict__.update(serie_config.__dict__) fill_config.__dict__.update(serie_config.area) to = ordered_keys.index(fill_config.to) chart.add_fill_range(_valid_color(fill_config.color), index, to) if serie_config.dash: chart.set_line_style(index, serie_config.thickness, serie_config.dash, serie_config.dash) else: chart.set_line_style(index, serie_config.thickness) if serie_config.legend: legend.append(serie_config.legend) legend_set = True else: legend.append('') if serie_config.marks: mark_config = ChartConfig() mark_config.__dict__.update(serie_config.__dict__) mark_config.__dict__.update(serie_config.marks) mark_data = copy.copy(data[mark_config.serie.split('.')[0]]['series'][mark_config.serie.split('.')[1]]) mark_data = compress_to(mark_data, config.nval, min_index, max_index)[0] for i, m in enumerate(mark_data): if not m: mark_data[i] = " " density = max(1.0, 1.0 * mark_config.space * len("".join(mark_data))*mark_config.size / config.width) for i, v in enumerate(mark_data): if (i +1) % round(density) == 0: if serie_data[i] != 0: text = str(mark_data[i]) else: text = " " chart.add_marker(index, i, 't'+text, _valid_color(mark_config.color), mark_config.size) index = index + 1 # Compute vertical range if config.axes: range_min_ref_units = 0 if not chart_min == sys.maxint and not chart_max == -sys.maxint: range_min = chart_min-config.ymargin[0] range_max = chart_max+config.ymargin[1] range_min_target_units = math.floor(converter.convert(measure, range_min)) range_max_target_units = math.ceil(converter.convert(measure, range_max)) range_min_ref_units = converter.convert_back(measure, range_min_target_units) range_max_ref_units = converter.convert_back(measure, range_max_target_units) self.logger.debug("Y range: "+str(range_min_target_units) +" "+str(range_max_target_units)) chart.set_axis_range(Axis.LEFT, range_min_target_units, range_max_target_units+1) chart.add_data([range_min_ref_units, range_max_ref_units]) colors.append("00000000") else: chart.set_axis_range(Axis.LEFT, 0, 100) chart.set_axis_style(0, _valid_color(config.text), config.size, 0, Axis.BOTH if config.ticks else Axis.AXIS_LINES) else: chart.set_axis_labels(Axis.LEFT, []) chart.set_axis_style(0, _valid_color(config.text), config.size, 0, Axis.TICK_MARKS, _valid_color(config.bgcolor)) if config.zero and config.axes and range_min_ref_units < 0 and range_max_ref_units > 0: zero_config = ChartConfig() zero_config.__dict__.update(config.__dict__) zero_config.__dict__.update(config.zero) chart.add_data([0]*2) colors.append(_valid_color(zero_config.color)) chart.set_line_style(index, zero_config.thickness) chart.set_colours(colors) chart.fill_solid(Chart.BACKGROUND, _valid_color(config.bgcolor)) if legend_set: chart.set_legend(legend) chart.set_legend_position(config.legend_pos) if self.labels: labels_data = copy.copy(data[self.labels.split('.')[0]]['series'][self.labels.split('.')[1]]) labels_data = compress_to(labels_data, config.nval, None, None)[0] if config.axes: density = 1.0 * len("".join(labels_data))*config.size / config.width if density > LABEL_DENSITY_THRESHOLD: for i, v in enumerate(labels_data): if i % round(density) != 0: labels_data[i] = ' ' chart.set_axis_labels(Axis.BOTTOM, labels_data) chart.set_axis_style(1, _valid_color(config.text), config.size, 0, Axis.BOTH if config.ticks else Axis.AXIS_LINES) else: chart.set_axis_labels(Axis.BOTTOM, []) chart.set_axis_style(1, _valid_color(config.text), config.size, 0, Axis.TICK_MARKS, _valid_color(config.color)) try: return chart.get_url()+"&chma=10,10,10,10" # add a margin except: self.logger.exception("Could not render chart") return "http://chart.apis.google.com/chart?cht=lc&chs="+str(config.width)+"x"+str(config.height)
def _line_strip_graph(data, legends, axis_labels, size, steps, type=SimpleLineChart, multiline=False, **kwargs): if multiline: max_values = [] min_values = [] for row in data: max_values.append(max(row)) min_values.append(min(row)) max_y = max(max_values) min_y = min(min_values) else: max_y = max(data) min_y = min(data) #validando si hay datos para hacer grafico if max_y == 0: return None chart = SimpleLineChart(size[0], size[1], y_range=[0, max_y * 1.05]) if multiline: for row in data: chart.add_data(row) else: chart.add_data(data) step = ((max_y * 1.05) - (min_y * 0.95)) / steps #validando en caso de el paso sea menor que uno y de cero en la conversion if step < 1: step = 1 max_value = max_y tope = int(round(max_value * 1.05)) if tope < max_value: tope += 2 else: tope += 1 try: left_axis = range(int(round(min_y * 0.95)), tope, int(step)) except ValueError: #error por que los range no soportan decimales left_axis = range(0, 2) left_axis[0] = '' chart.set_axis_range(Axis.LEFT, min_y, tope) if 'units' in kwargs: chart.set_axis_labels(Axis.LEFT, kwargs['units']) if 'time' in kwargs: chart.set_axis_labels(Axis.BOTTOM, kwargs['time']) chart.set_grid( 0, 25, 4, 4, ) chart.chls = 4 | 4 #chart.fill_linear_stripes(Chart.CHART, 0, 'FFFFEF', 0.2, 'FFFFFF', 0.2) chart.set_colours(COLORS) if axis_labels: chart.set_axis_labels(Axis.BOTTOM, axis_labels) chart.set_legend(legends) chart.set_legend_position('b') if 'thickness' in kwargs: if multiline: for i in range(len(data)): chart.set_line_style(index=i, thickness=kwargs['thickness']) else: chart.set_line_style(index=0, thickness=kwargs['thickness']) return chart
def lambda_handler(event, context): # http://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/weather.html url = "http://weather.olp.yahooapis.jp/v1/place" payload = {'appid': YAHOO_APP_ID, 'coordinates': LON + "," + LAT, 'output': 'json'} result = requests.get(url, params=payload) timeString = getTimeString(30) send_message = False json_data = json.loads(result.content) rainfall = json_data['Feature'][0]['Property']['WeatherList']['Weather']#[3]['Rainfall'] dynamodb = boto3.resource('dynamodb') table = dynamodb.Table(inifile.get('dynamodb', 'table_id')) key_id = int(inifile.get('dynamodb', 'id_value')) result = table.get_item( Key={ 'Id': key_id } ) if 'raining' not in result: table.put_item( Item={ "Id":key_id, "raining": False, "source": inifile.get('dynamodb', 'source')} ) raining = result['Item']['raining'] if rainfall[3]['Rainfall'] >= ALERT_THRESH and raining == False: send_message = True message = timeString + "で" + str(rainfall[3]['Rainfall']) + "mm/hの雨が予想されます。" elif rainfall[3]['Rainfall'] < ALERT_THRESH and raining == True: send_message = True message = timeString + "で" + "雨が止む予報です。" elif rainfall[3]['Rainfall'] >= ALERT_THRESH and raining == True: send_message = True message = timeString + "で" + str(rainfall[3]['Rainfall']) + "mm/hの雨が引き続き降る予報です。" elif rainfall[3]['Rainfall'] < ALERT_THRESH and raining == False: send_message = False if rainfall[3]['Rainfall'] >= ALERT_THRESH: table.put_item( Item={ "Id":key_id, "raining": True, "source": inifile.get('dynamodb', 'source')} ) else: table.put_item( Item={ "Id":key_id, "raining": False, "source": inifile.get('dynamodb', 'source')} ) if send_message == True: width = 500 height = 150 chart = SimpleLineChart(width, height) chart.set_colours(['719CFF']) rainfall_array = [rainfall[0]['Rainfall'], rainfall[1]['Rainfall'], rainfall[2]['Rainfall'], rainfall[3]['Rainfall'], rainfall[4]['Rainfall'], rainfall[5]['Rainfall'], rainfall[6]['Rainfall']] chart.add_data(rainfall_array) chart.set_axis_labels(Axis.BOTTOM, [getTimeString(0), getTimeString(10), getTimeString(20), getTimeString(30), getTimeString(40), getTimeString(50), getTimeString(60)]) chart.set_legend(['Rainfall(mm/h)']) chart.set_legend_position('bv') if math.ceil(max(rainfall_array)) < 1.0: chart.y_range=(0, 1) chart.set_axis_range(Axis.LEFT, 0, 1) else: chart.y_range=(0, math.ceil(max(rainfall_array))) chart.set_axis_range(Axis.LEFT, 0, math.ceil(max(rainfall_array))) d = datetime.now() + timedelta(hours=9, minutes=30) date_str = d.strftime("|date:%Y%m%d%H%M|datelabel:on") radar_url = "http://weather.yahoo.co.jp/weather/zoomradar/?lat=" + LAT + "&lon=" + LON + "&z=12" rainfall_image_url = getRainfallRadarUrl(LAT, LON, ZOOM, MAP_IMAGE_X, MAP_IMAGE_Y) + date_str chart_url = shorten_url(chart.get_url()) rainfall_image_url = shorten_url(rainfall_image_url) radar_url = shorten_url(radar_url) message = unicode(message, 'utf-8') + "\n" + chart_url + "\n" + timeString + u"の雨雲予想: " + rainfall_image_url + "\n" + u"詳細: " + radar_url + "\n" sc = SlackClient(inifile.get('slack', 'token')) res = sc.api_call("chat.postMessage", channel=inifile.get('slack', 'channel'), text=message, username=inifile.get('slack', 'username'), icon_emoji=inifile.get('slack', 'icon_emoji')) print(res)
def render(self, data={}, context={}): assert self.series is not None, "'chart.series' must be set" converter = wfcommon.units.Converter(context["units"]) # merge builtin defaults, context and renderer config config = ChartConfig() if context.has_key('chart'): config.__dict__.update(context['chart']) config.__dict__.update(self.__dict__) # create the chart chart = SimpleLineChart(config.width, config.height) colors = [] legend_set = False legend = [] chart_min = sys.maxint chart_max = -sys.maxint # Prepare series config ordered_series = [] for key, serie in self.series.iteritems(): serie_config = ChartConfig() serie_config.__dict__.update(config.__dict__) serie_config.__dict__.update(serie) ordered_series.append((serie_config.order, key, serie)) ordered_series.sort(cmp=lambda x, y: cmp(x[0], y[0])) ordered_keys = [] for order, key, serie in ordered_series: ordered_keys.append(key) # Draws for each serie index = 0 for order, key, serie in ordered_series: serie_config = ChartConfig() serie_config.__dict__.update(config.__dict__) serie_config.__dict__.update(serie) serie_data = copy.copy( data[key.split('.')[0]]['series'][key.split('.')[1]]) measure = key.split('.')[0] if flat(serie_data): # Series with all data = None continue if serie_config.accumulate: serie_data = accumulate(serie_data) elif serie_config.interpolate: serie_data = interpolate(serie_data) # Compute min and max value for the serie and the whole chart min_data = amin(serie_data) chart_min = rmin(chart_min, min_data) if serie_data.__contains__(min_data): min_index = serie_data.index(min_data) else: min_index = None max_data = max(serie_data) chart_max = max(chart_max, max_data) if serie_data.__contains__(max_data): max_index = serie_data.index(max_data) else: max_index = None (serie_data, min_index, max_index) = compress_to(serie_data, config.nval, min_index, max_index) chart.add_data(serie_data) colors.append(_valid_color(serie_config.color)) if serie_config.max and not max_index == None: max_config = ChartConfig() max_config.__dict__.update(serie_config.__dict__) max_config.__dict__.update(serie_config.max) str_max_data = str( round(converter.convert(measure, max_data), 1)) chart.add_marker(index, max_index, 't' + str_max_data, _valid_color(max_config.text), max_config.size) chart.add_marker(index, max_index, max_config.style, _valid_color(max_config.color), max_config.thickness) if serie_config.min and not min_index == None: min_config = ChartConfig() min_config.__dict__.update(serie_config.__dict__) min_config.__dict__.update(serie_config.min) str_min_data = str( round(converter.convert(measure, min_data), 1)) chart.add_marker(index, min_index, 't' + str_min_data, _valid_color(min_config.text), min_config.size) chart.add_marker(index, min_index, min_config.style, _valid_color(min_config.color), min_config.thickness) if serie_config.last: last_config = ChartConfig() last_config.__dict__.update(serie_config.__dict__) last_config.__dict__.update(serie_config.last) last_index = len(serie_data) - 1 last_data = serie_data[last_index] if last_data: str_last_data = str( round(converter.convert(measure, last_data), 1)) chart.add_marker(index, last_index, 't' + str(last_data), _valid_color(last_config.text), last_config.size) chart.add_marker(index, last_index, last_config.style, _valid_color(last_config.color), last_config.thickness) if serie_config.area: fill_config = ChartConfig() fill_config.__dict__.update(serie_config.__dict__) fill_config.__dict__.update(serie_config.area) to = ordered_keys.index(fill_config.to) chart.add_fill_range(_valid_color(fill_config.color), index, to) if serie_config.dash: chart.set_line_style(index, serie_config.thickness, serie_config.dash, serie_config.dash) else: chart.set_line_style(index, serie_config.thickness) if serie_config.legend: legend.append(serie_config.legend) legend_set = True else: legend.append('') if serie_config.marks: mark_config = ChartConfig() mark_config.__dict__.update(serie_config.__dict__) mark_config.__dict__.update(serie_config.marks) mark_data = copy.copy(data[mark_config.serie.split( '.')[0]]['series'][mark_config.serie.split('.')[1]]) mark_data = compress_to(mark_data, config.nval, min_index, max_index)[0] for i, m in enumerate(mark_data): if not m: mark_data[i] = " " density = max( 1.0, 1.0 * mark_config.space * len("".join(mark_data)) * mark_config.size / config.width) for i, v in enumerate(mark_data): if (i + 1) % round(density) == 0: if serie_data[i] != 0: text = str(mark_data[i]) else: text = " " chart.add_marker(index, i, 't' + text, _valid_color(mark_config.color), mark_config.size) index = index + 1 # Compute vertical range if config.axes: range_min_ref_units = 0 if not chart_min == sys.maxint and not chart_max == -sys.maxint: range_min = chart_min - config.ymargin[0] range_max = chart_max + config.ymargin[1] range_min_target_units = math.floor( converter.convert(measure, range_min)) range_max_target_units = math.ceil( converter.convert(measure, range_max)) range_min_ref_units = converter.convert_back( measure, range_min_target_units) range_max_ref_units = converter.convert_back( measure, range_max_target_units) self.logger.debug("Y range: " + str(range_min_target_units) + " " + str(range_max_target_units)) chart.set_axis_range(Axis.LEFT, range_min_target_units, range_max_target_units + 1) chart.add_data([range_min_ref_units, range_max_ref_units]) colors.append("00000000") else: chart.set_axis_range(Axis.LEFT, 0, 100) chart.set_axis_style( 0, _valid_color(config.text), config.size, 0, Axis.BOTH if config.ticks else Axis.AXIS_LINES) else: chart.set_axis_labels(Axis.LEFT, []) chart.set_axis_style(0, _valid_color(config.text), config.size, 0, Axis.TICK_MARKS, _valid_color(config.bgcolor)) if config.zero and config.axes and range_min_ref_units < 0 and range_max_ref_units > 0: zero_config = ChartConfig() zero_config.__dict__.update(config.__dict__) zero_config.__dict__.update(config.zero) chart.add_data([0] * 2) colors.append(_valid_color(zero_config.color)) chart.set_line_style(index, zero_config.thickness) chart.set_colours(colors) chart.fill_solid(Chart.BACKGROUND, _valid_color(config.bgcolor)) if legend_set: chart.set_legend(legend) chart.set_legend_position(config.legend_pos) if self.labels: labels_data = copy.copy(data[self.labels.split('.')[0]]['series'][ self.labels.split('.')[1]]) labels_data = compress_to(labels_data, config.nval, None, None)[0] if config.axes: density = 1.0 * len( "".join(labels_data)) * config.size / config.width if density > LABEL_DENSITY_THRESHOLD: for i, v in enumerate(labels_data): if i % round(density) != 0: labels_data[i] = ' ' chart.set_axis_labels(Axis.BOTTOM, labels_data) chart.set_axis_style( 1, _valid_color(config.text), config.size, 0, Axis.BOTH if config.ticks else Axis.AXIS_LINES) else: chart.set_axis_labels(Axis.BOTTOM, []) chart.set_axis_style(1, _valid_color(config.text), config.size, 0, Axis.TICK_MARKS, _valid_color(config.color)) try: return chart.get_url() + "&chma=10,10,10,10" # add a margin except: self.logger.exception("Could not render chart") return "http://chart.apis.google.com/chart?cht=lc&chs=" + str( config.width) + "x" + str(config.height)