671
574
url_bits.append('chxt=%s' % ','.join(available_axis))
673
url_bits.append('chxl=%s' % '%7c'.join(label_axis))
576
url_bits.append('chxl=%s' % '|'.join(label_axis))
675
url_bits.append('chxr=%s' % '%7c'.join(range_axis))
578
url_bits.append('chxr=%s' % '|'.join(range_axis))
677
url_bits.append('chxp=%s' % '%7c'.join(positions))
580
url_bits.append('chxp=%s' % '|'.join(positions))
679
url_bits.append('chxs=%s' % '%7c'.join(styles))
582
url_bits.append('chxs=%s' % '|'.join(styles))
680
583
return '&'.join(url_bits)
682
585
# Markers, Ranges and Fill area (chm)
683
586
# -------------------------------------------------------------------------
685
def markers_to_url(self):
686
return 'chm=%s' % '%7c'.join([','.join(a) for a in self.markers])
588
def markers_to_url(self):
589
return 'chm=%s' % '|'.join([','.join(a) for a in self.markers])
688
def add_marker(self, index, point, marker_type, colour, size, priority=0):
591
def add_marker(self, index, point, marker_type, colour, size):
689
592
self.markers.append((marker_type, colour, str(index), str(point), \
690
str(size), str(priority)))
692
595
def add_horizontal_range(self, colour, start, stop):
693
self.markers.append(('r', colour, '0', str(start), str(stop)))
695
def add_data_line(self, colour, data_set, size, priority=0):
696
self.markers.append(('D', colour, str(data_set), '0', str(size), \
699
def add_marker_text(self, string, colour, data_set, data_point, size, \
701
self.markers.append((str(string), colour, str(data_set), \
702
str(data_point), str(size), str(priority)))
596
self.markers.append(('r', colour, '1', str(start), str(stop)))
704
598
def add_vertical_range(self, colour, start, stop):
705
self.markers.append(('R', colour, '0', str(start), str(stop)))
599
self.markers.append(('R', colour, '1', str(start), str(stop)))
707
601
def add_fill_range(self, colour, index_start, index_end):
708
602
self.markers.append(('b', colour, str(index_start), str(index_end), \
942
826
yield ('y', dataset)
945
class RadarChart(Chart):
947
def type_to_url(self):
951
class SplineRadarChart(RadarChart):
953
def type_to_url(self):
957
class MapChart(Chart):
959
def __init__(self, *args, **kwargs):
960
Chart.__init__(self, *args, **kwargs)
961
self.geo_area = 'world'
963
self.__areas = ('africa', 'asia', 'europe', 'middle_east',
964
'south_america', 'usa', 'world')
966
'AD', 'AE', 'AF', 'AG', 'AI', 'AL', 'AM', 'AN', 'AO', 'AQ', 'AR',
967
'AS', 'AT', 'AU', 'AW', 'AX', 'AZ', 'BA', 'BB', 'BD', 'BE', 'BF',
968
'BG', 'BH', 'BI', 'BJ', 'BL', 'BM', 'BN', 'BO', 'BR', 'BS', 'BT',
969
'BV', 'BW', 'BY', 'BZ', 'CA', 'CC', 'CD', 'CF', 'CG', 'CH', 'CI',
970
'CK', 'CL', 'CM', 'CN', 'CO', 'CR', 'CU', 'CV', 'CX', 'CY', 'CZ',
971
'DE', 'DJ', 'DK', 'DM', 'DO', 'DZ', 'EC', 'EE', 'EG', 'EH', 'ER',
972
'ES', 'ET', 'FI', 'FJ', 'FK', 'FM', 'FO', 'FR', 'GA', 'GB', 'GD',
973
'GE', 'GF', 'GG', 'GH', 'GI', 'GL', 'GM', 'GN', 'GP', 'GQ', 'GR',
974
'GS', 'GT', 'GU', 'GW', 'GY', 'HK', 'HM', 'HN', 'HR', 'HT', 'HU',
975
'ID', 'IE', 'IL', 'IM', 'IN', 'IO', 'IQ', 'IR', 'IS', 'IT', 'JE',
976
'JM', 'JO', 'JP', 'KE', 'KG', 'KH', 'KI', 'KM', 'KN', 'KP', 'KR',
977
'KW', 'KY', 'KZ', 'LA', 'LB', 'LC', 'LI', 'LK', 'LR', 'LS', 'LT',
978
'LU', 'LV', 'LY', 'MA', 'MC', 'MD', 'ME', 'MF', 'MG', 'MH', 'MK',
979
'ML', 'MM', 'MN', 'MO', 'MP', 'MQ', 'MR', 'MS', 'MT', 'MU', 'MV',
980
'MW', 'MX', 'MY', 'MZ', 'NA', 'NC', 'NE', 'NF', 'NG', 'NI', 'NL',
981
'NO', 'NP', 'NR', 'NU', 'NZ', 'OM', 'PA', 'PE', 'PF', 'PG', 'PH',
982
'PK', 'PL', 'PM', 'PN', 'PR', 'PS', 'PT', 'PW', 'PY', 'QA', 'RE',
983
'RO', 'RS', 'RU', 'RW', 'SA', 'SB', 'SC', 'SD', 'SE', 'SG', 'SH',
984
'SI', 'SJ', 'SK', 'SL', 'SM', 'SN', 'SO', 'SR', 'ST', 'SV', 'SY',
985
'SZ', 'TC', 'TD', 'TF', 'TG', 'TH', 'TJ', 'TK', 'TL', 'TM', 'TN',
986
'TO', 'TR', 'TT', 'TV', 'TW', 'TZ', 'UA', 'UG', 'UM', 'US', 'UY',
987
'UZ', 'VA', 'VC', 'VE', 'VG', 'VI', 'VN', 'VU', 'WF', 'WS', 'YE',
988
'YT', 'ZA', 'ZM', 'ZW')
990
def type_to_url(self):
993
def set_codes(self, codes):
994
'''Set the country code map for the data.
995
Codes given in a list.
1006
if cc in self.__ccodes:
1009
raise UnknownCountryCodeException(cc)
1011
self.codes = codemap
1013
def set_geo_area(self, area):
1014
'''Sets the geo area for the map.
1025
if area in self.__areas:
1026
self.geo_area = area
1028
raise UnknownChartType('Unknown chart type for maps: %s' %area)
1030
def get_url_bits(self, data_class=None):
1031
url_bits = Chart.get_url_bits(self, data_class=data_class)
1032
url_bits.append('chtm=%s' % self.geo_area)
1034
url_bits.append('chld=%s' % ''.join(self.codes))
1037
def add_data_dict(self, datadict):
1038
'''Sets the data and country codes via a dictionary.
1040
i.e. {'DE': 50, 'GB': 30, 'AT': 70}
1043
self.set_codes(datadict.keys())
1044
self.add_data(datadict.values())
1047
class GoogleOMeterChart(PieChart):
1048
"""Inheriting from PieChart because of similar labeling"""
1050
def __init__(self, *args, **kwargs):
1051
PieChart.__init__(self, *args, **kwargs)
1052
if self.auto_scale and not self.x_range:
1053
warnings.warn('Please specify an x_range with GoogleOMeterChart, '
1054
'otherwise one arrow will always be at the max.')
1056
def type_to_url(self):
1060
class QRChart(Chart):
1062
def __init__(self, *args, **kwargs):
1063
Chart.__init__(self, *args, **kwargs)
1064
self.encoding = None
1065
self.ec_level = None
1068
def type_to_url(self):
1071
def data_to_url(self, data_class=None):
1073
raise NoDataGivenException()
1074
return 'chl=%s' % urllib.quote(self.data[0])
1076
def get_url_bits(self, data_class=None):
1077
url_bits = Chart.get_url_bits(self, data_class=data_class)
1079
url_bits.append('choe=%s' % self.encoding)
1081
url_bits.append('chld=%s%%7c%s' % (self.ec_level, self.margin))
1084
def set_encoding(self, encoding):
1085
self.encoding = encoding
1087
def set_ec(self, level, margin):
1088
self.ec_level = level
1089
self.margin = margin
1092
class ChartGrammar(object):
1098
def parse(self, grammar):
1099
self.grammar = grammar
1100
self.chart = self.create_chart_instance()
1102
for attr in self.grammar:
1103
if attr in ('w', 'h', 'type', 'auto_scale', 'x_range', 'y_range'):
1104
continue # These are already parsed in create_chart_instance
1105
attr_func = 'parse_' + attr
1106
if not hasattr(self, attr_func):
1107
warnings.warn('No parser for grammar attribute "%s"' % (attr))
1109
getattr(self, attr_func)(grammar[attr])
1113
def parse_data(self, data):
1114
self.chart.data = data
1117
def get_possible_chart_types():
1118
possible_charts = []
1119
for cls_name in globals().keys():
1120
if not cls_name.endswith('Chart'):
1122
cls = globals()[cls_name]
1123
# Check if it is an abstract class
1125
a = cls(1, 1, auto_scale=False)
1127
except AbstractClassException:
1130
possible_charts.append(cls_name[:-5])
1131
return possible_charts
1133
def create_chart_instance(self, grammar=None):
1135
grammar = self.grammar
1136
assert(isinstance(grammar, dict)) # grammar must be a dict
1137
assert('w' in grammar) # width is required
1138
assert('h' in grammar) # height is required
1139
assert('type' in grammar) # type is required
1140
chart_type = grammar['type']
1143
auto_scale = grammar.get('auto_scale', None)
1144
x_range = grammar.get('x_range', None)
1145
y_range = grammar.get('y_range', None)
1146
types = ChartGrammar.get_possible_chart_types()
1147
if chart_type not in types:
1148
raise UnknownChartType('%s is an unknown chart type. Possible '
1149
'chart types are %s' % (chart_type, ','.join(types)))
1150
return globals()[chart_type + 'Chart'](w, h, auto_scale=auto_scale,
1151
x_range=x_range, y_range=y_range)
830
chart = GroupedVerticalBarChart(320, 200)
831
chart = PieChart2D(320, 200)
832
chart = ScatterChart(320, 200)
833
chart = SimpleLineChart(320, 200)
834
sine_data = [math.sin(float(a) / 10) * 2000 + 2000 for a in xrange(100)]
835
random_data = [a * random.random() * 30 for a in xrange(40)]
836
random_data2 = [random.random() * 4000 for a in xrange(10)]
837
# chart.set_bar_width(50)
838
# chart.set_bar_spacing(0)
839
chart.add_data(sine_data)
840
chart.add_data(random_data)
841
chart.add_data(random_data2)
842
# chart.set_line_style(1, thickness=2)
843
# chart.set_line_style(2, line_segment=10, blank_segment=5)
844
# chart.set_title('heloooo')
845
# chart.set_legend(('sine wave', 'random * x'))
846
# chart.set_colours(('ee2000', 'DDDDAA', 'fF03f2'))
847
# chart.fill_solid(Chart.BACKGROUND, '123456')
848
# chart.fill_linear_gradient(Chart.CHART, 20, '004070', 1, '300040', 0,
850
# chart.fill_linear_stripes(Chart.CHART, 20, '204070', .2, '300040', .2,
852
axis_left_index = chart.set_axis_range(Axis.LEFT, 0, 10)
853
axis_left_index = chart.set_axis_range(Axis.LEFT, 0, 10)
854
axis_left_index = chart.set_axis_range(Axis.LEFT, 0, 10)
855
axis_right_index = chart.set_axis_range(Axis.RIGHT, 5, 30)
856
axis_bottom_index = chart.set_axis_labels(Axis.BOTTOM, [1, 25, 95])
857
chart.set_axis_positions(axis_bottom_index, [1, 25, 95])
858
chart.set_axis_style(axis_bottom_index, '003050', 15)
860
# chart.set_pie_labels(('apples', 'oranges', 'bananas'))
862
# chart.set_grid(10, 10)
864
# for a in xrange(0, 100, 10):
865
# chart.add_marker(1, a, 'a', 'AACA20', 10)
867
chart.add_horizontal_range('00A020', .2, .5)
868
chart.add_vertical_range('00c030', .2, .4)
870
chart.add_fill_simple('303030A0')
872
chart.download('test.png')
874
url = chart.get_url()
877
data = urllib.urlopen(chart.get_url()).read()
878
open('meh.png', 'wb').write(data)
879
os.system('start meh.png')
882
if __name__ == '__main__':